home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TPTOOL4.ZIP / PLOTLIB.INC < prev    next >
Encoding:
Text File  |  1987-03-28  |  9.6 KB  |  418 lines

  1.  
  2. const plotlib_tag: string[90]
  3.    = #0'@(#)CURRENT_FILE LAST_UPDATE Graphics plotting library 1.0'#0;
  4. #log Graphics plotting library 1.0
  5.  
  6. (*
  7.  * plotlib - graphics graph plotting package
  8.  *
  9.  * revision history:
  10.  *    5/13/85 shs - initial coding
  11.  *    24/7/86 shs - added plot_data and event procedures
  12.  *)
  13.  
  14. const
  15.    green     = 1;
  16.    red       = 1;
  17.    yellow    = 1;
  18.    phys_maxx = 620.0;    {physical dimensions of graphics area}
  19.    phys_minx = 100.0;
  20.    phys_maxy = 30.0;
  21.    phys_miny = 154.0;
  22.    mark_x    = 4;        {size of marker}
  23.    mark_y    = 2;
  24.    numtics   = 5;        {number of ticks in scales}
  25.  
  26. var
  27.    maxx:    real;      {logical dimensions of screen}
  28.    minx:    real;
  29.    maxy:    real;
  30.    miny:    real;
  31.    xstep:   real;
  32.    ystep:   real;
  33.    nxsteps: integer;
  34.    nysteps: integer;
  35.    color:   integer;
  36.  
  37.  
  38. {translate logical x location into physical pixel location}
  39.  
  40. function get_phys_x(vx: real): integer;
  41. var x: real;
  42. begin
  43.    if (vx > maxx) then
  44.       vx := maxx;
  45.    if (vx < minx) then
  46.       vx := minx;
  47.  
  48.    x := (phys_maxx - phys_minx) * (vx - minx) / (maxx - minx) + phys_minx;
  49.    get_phys_x := trunc(x);
  50. end;
  51.  
  52.  
  53.  
  54. {translate logical y location into physical pixel location}
  55.  
  56. function get_phys_y(vy: real): integer;
  57. var y: real;
  58. begin
  59.    if (vy > maxy) then
  60.       vy := maxy;
  61.    if (vy < miny) then
  62.       vy := miny;
  63.  
  64.    y := (phys_maxy - phys_miny) * (vy - miny) / (maxy - miny) + phys_miny;
  65.    get_phys_y := trunc(y);
  66. end;
  67.  
  68.  
  69.  
  70. {connect two logical points with a line}
  71.  
  72. procedure connect(x1,y1,x2,y2: real);
  73. var
  74.   px1,py1,px2,py2: integer;
  75. begin
  76.    px1 := get_phys_x(x1);
  77.    if x2 <> x1 then
  78.       px2 := get_phys_x(x2)
  79.    else
  80.       px2 := px1;
  81.  
  82.    py1 := get_phys_y(y1);
  83.    if y2 <> y1 then
  84.       py2 := get_phys_y(y2)
  85.    else
  86.       py2 := py1;
  87.  
  88.    if (px1 <> px2) or (py1 <> py2) then
  89.       draw(px1,py1,px2,py2,color)
  90.    else
  91.       plot(px1,py1,color);
  92. end;
  93.  
  94.  
  95.  
  96. {place a tick mark on a point}
  97.  
  98. procedure tick(x1,y1: real);
  99. begin
  100.    plot(get_phys_x(x1),get_phys_y(y1),color);
  101. end;
  102.  
  103.  
  104.  
  105. {determine a nice looking scale}
  106.  
  107. procedure determinescale (var world_min:     real;
  108.                           var world_max:     real;
  109.                           var stepsz:        real;
  110.                           var stepcnt:       integer;
  111.                               maxstep:       integer);
  112.       var
  113.          new_min:          real;
  114.          new_max:          real;
  115.          damper:           integer;
  116.          pct:              real;
  117.          range:            real;
  118.          curstep:          integer;
  119.          w:                real;
  120.  
  121.       const
  122.          limit  =  32000;   {maximum number of iterations to determine
  123.                              the new scale boundries}
  124.  
  125.  
  126. (* return next higher stepsize multiplier *)
  127.       function nextstep: real;
  128.       begin
  129.          case curstep of
  130.             1:  nextstep := 2;    {2}
  131.             2:  nextstep := 2.5;  {5}
  132.             3:  nextstep := 2;    {10}
  133.          end;
  134.  
  135.          curstep := curstep + 1;
  136.          if curstep > 3 then
  137.             curstep := 1;
  138.       end;
  139.  
  140.  
  141.  
  142. (* return number of steps with current stepsz *)
  143.       function nsteps: integer;
  144.          var
  145.             n:  real;
  146.  
  147.          begin
  148.             if stepsz = 0.0 then
  149.                n := 0.0
  150.             else
  151.                n := (new_max - new_min)/ stepsz + 1.5;
  152.  
  153.             if n < 0.0 then
  154.                n := 0.0;
  155.  
  156.             if n >= maxint then
  157.                n := maxint-1.0;
  158.  
  159.             nsteps := trunc (n);
  160.          end;
  161.  
  162.  
  163.    begin                         {determine proper step size}
  164.  
  165. (* find best step size *)
  166.  
  167.       new_min := world_min;
  168.       new_max := world_max;
  169.       curstep := 1;
  170.       stepsz := 1;
  171.  
  172.       while (nsteps < maxstep) and (nsteps > 0) do
  173.             stepsz := stepsz / 10.0;
  174.  
  175.       while (nsteps > maxstep) and (nsteps > 0) do
  176.             stepsz := stepsz * nextstep;
  177.  
  178.  
  179. (*
  180.  * note - this process will take forever if you have a very narrow
  181.  *        range that is sitting on a huge offset.  the damper variable
  182.  *        will cause this routine to give up after limit iterations
  183.  *        if it has not found the endpoints
  184.  *)
  185.       damper := 0;
  186.       repeat
  187.  
  188.          new_min := 0.0;   {determine even endpoints based on stepsz}
  189.          new_max := 0.0;
  190.  
  191.          if stepsz <> 0.0 then
  192.          begin
  193.             while (new_min <= world_min) and (damper < limit) do
  194.             begin
  195.                damper := damper + 1;
  196.                new_min := new_min + abs(stepsz)*200.0;
  197.             end;
  198.  
  199.             w := world_min;
  200.             while (new_min > w) and (damper < limit) do
  201.             begin
  202.                damper := damper + 1;
  203.                new_min := new_min - abs(stepsz);
  204.             end;
  205.  
  206.             new_max := new_min;
  207.             while (new_max >= world_max) and (damper < limit) do
  208.             begin
  209.                damper := damper + 1;
  210.                new_max := new_max - abs(stepsz);
  211.             end;
  212.  
  213.             w := world_max;
  214.             while (new_max < w) and (damper < limit) do
  215.             begin
  216.                damper := damper + 1;
  217.                new_max := new_max + abs(stepsz);
  218.             end;
  219.          end;
  220.  
  221. (* if new min/max causes extra steps, then go to a larger step size
  222.    and try again *)
  223.          stepcnt := nsteps;
  224.  
  225.          if stepcnt > maxstep then
  226.             stepsz := stepsz * nextstep;
  227.  
  228.       until stepcnt <= maxstep;
  229.  
  230.       world_min := new_min;  {assign final return values}
  231.       world_max := new_max;
  232.    end;                       {PLOT_set_scale}
  233.  
  234.  
  235.  
  236. {place a marker at a logical point}
  237.  
  238. procedure marker(x,y: real; style: integer);
  239. begin
  240.  
  241.    case style of
  242.    1: begin     {place an X on the point}
  243.           draw(get_phys_x(x)-mark_x,get_phys_y(y)-mark_y,
  244.                get_phys_x(x)+mark_x,get_phys_y(y)+mark_y,yellow);
  245.           draw(get_phys_x(x)-mark_x,get_phys_y(y)+mark_y,
  246.                get_phys_x(x)+mark_x,get_phys_y(y)-mark_y,yellow);
  247.        end;
  248.  
  249.    2: begin     {place an box around the point}
  250.           draw(get_phys_x(x)-mark_x,get_phys_y(y)-mark_y,
  251.                get_phys_x(x)-mark_x,get_phys_y(y)+mark_y,yellow);
  252.           draw(get_phys_x(x)+mark_x,get_phys_y(y)-mark_y,
  253.                get_phys_x(x)+mark_x,get_phys_y(y)+mark_y,yellow);
  254.           draw(get_phys_x(x)-mark_x,get_phys_y(y)+mark_y,
  255.                get_phys_x(x)+mark_x,get_phys_y(y)+mark_y,yellow);
  256.           draw(get_phys_x(x)-mark_x,get_phys_y(y)-mark_y,
  257.                get_phys_x(x)+mark_x,get_phys_y(y)-mark_y,yellow);
  258.        end;
  259.  
  260.    3: begin     {place a triangle on the point}
  261.           draw(get_phys_x(x)-mark_x,get_phys_y(y)+mark_y,
  262.                get_phys_x(x)       ,get_phys_y(y)-mark_y,yellow);
  263.           draw(get_phys_x(x)+mark_x,get_phys_y(y)+mark_y,
  264.                get_phys_x(x)       ,get_phys_y(y)-mark_y,yellow);
  265.           draw(get_phys_x(x)+mark_x,get_phys_y(y)+mark_y,
  266.                get_phys_x(x)-mark_x,get_phys_y(y)+mark_y,yellow);
  267.        end;
  268.  
  269.    4: begin     {place an inverted triangle on the point}
  270.           draw(get_phys_x(x)-mark_x,get_phys_y(y)-mark_y,
  271.                get_phys_x(x)       ,get_phys_y(y)+mark_y,yellow);
  272.           draw(get_phys_x(x)+mark_x,get_phys_y(y)-mark_y,
  273.                get_phys_x(x)       ,get_phys_y(y)+mark_y,yellow);
  274.           draw(get_phys_x(x)+mark_x,get_phys_y(y)-mark_y,
  275.                get_phys_x(x)-mark_x,get_phys_y(y)-mark_y,yellow);
  276.        end;
  277.    end;
  278. end;
  279.  
  280.  
  281.  
  282. {place a label on the y axis}
  283.  
  284. procedure labely(y: real);
  285. begin
  286.    gotoxy(1,20 - trunc(16 * (y - miny) / (maxy - miny)) );
  287.    write(y:9:2);
  288. end;
  289.  
  290.  
  291.  
  292. {place a tick mark on the y axis}
  293.  
  294. procedure ticky(y: real);
  295. begin
  296.    draw(trunc(phys_minx-mark_x),get_phys_y(y),
  297.         trunc(phys_minx),       get_phys_y(y),color);
  298. end;
  299.  
  300.  
  301.  
  302. {place a label on the x axis}
  303.  
  304. procedure labelx(x: real);
  305. begin
  306.    gotoxy(trunc(65 * (x - minx) / (maxx - minx))+9,22);
  307.    write(x:6:1);
  308. end;
  309.  
  310.  
  311.  
  312. {place a tick mark on the x axis}
  313.  
  314. procedure tickx(x: real);
  315. begin
  316.    draw(get_phys_x(x),trunc(phys_miny-mark_y),
  317.         get_phys_x(x),trunc(phys_miny),color);
  318. end;
  319.  
  320.  
  321.  
  322. {output the x axis scales}
  323.  
  324. procedure putxscale;
  325. var
  326.    i,j:    integer;
  327.    y:      real;
  328.    x:      real;
  329.    px,py:  integer;
  330.  
  331. begin
  332.    x := minx;
  333.    for i := 1 to nxsteps do
  334.    begin
  335.       labelx(x);
  336.       px := get_phys_x(x);
  337.  
  338.       y := miny;
  339.       for j := 1 to numtics*nysteps do
  340.       begin
  341.          py := get_phys_y(y);
  342.          draw(px,py,px,py,color);
  343.          y := y + ystep/numtics;
  344.       end;
  345.  
  346.       for j := 1 to numtics do
  347.       begin
  348.          tickx(x);
  349.          x := x + xstep/numtics;
  350.       end;
  351.    end;
  352. end;
  353.  
  354.  
  355.  
  356. {output the y axis scales}
  357.  
  358. procedure putyscale;
  359. var
  360.    i,j:  integer;
  361.    y:    real;
  362.  
  363. begin
  364.    y := miny;
  365.  
  366.    for i := 1 to nysteps do
  367.    begin
  368.       labely(y);
  369.       connect(minx,y,maxx,y);
  370.  
  371.       for j := 1 to numtics do
  372.       begin
  373.          ticky(y);
  374.          y := y + ystep / numtics;
  375.       end;
  376.    end;
  377. end;
  378.  
  379.  
  380.  
  381. {output the border and scales for the graph}
  382.  
  383. procedure border;
  384. begin
  385.    hires;
  386.    hirescolor(white);
  387.  
  388.    determinescale(minx,maxx,xstep,nxsteps,6);
  389.    determinescale(miny,maxy,ystep,nysteps,6);
  390.  
  391.    color := green;
  392.    putxscale;
  393.    putyscale;
  394.  
  395.    color := red;
  396. end;
  397.  
  398.  
  399.  
  400. procedure plot_data(variable_number: integer;
  401.                     x:               integer;
  402.                     y:               real);
  403. begin
  404.    tick(int(x),y);
  405.  
  406.    if (x mod 40) = 0 then
  407.       marker(int(x),y,variable_number);
  408. end;
  409.  
  410.  
  411. procedure event(x: integer; note: anystring);
  412. begin
  413.    connect(int(x),miny,int(x),maxy);
  414.    writeln(note);
  415. end;
  416.  
  417.  
  418.