Plot

on Michael Vorburger's Personal Homepage
Home Personal Projects alpha ware

 

This is the first of the five exercises Next ] we had to implement in the ADA programming course at EPFL [EXTERNAL]: Several programs which would draw graphical output.

As an example, one of them is given here, including the output it produced: (If you are interested, I would be glad to send you the complete project report: mike@vorburger.ch [E-MAIL])

-- PLOTINONE
-- A function plotting module
--
-- Description: Some points of a function are calculated (by different 
--              procedures for xy-, polar- and parametric functions)
--              and stored in an polygon array.
--              
--              DoPlot determines max & min x & y and draws the function
--              with LOGO.
--
--              Storage in an array was chosen so that the points
--              don't have to be recalculated several times (for example, at
--              each window redraw...)
--
-- Michael Vorburger [vorburger@abacus.ch]
-- December/Januar '95/'96

with LOGO;

with OPERATIONS;
use OPERATIONS.MES_FONCTIONS_ELEMENTAIRES;

with NUMERIC_IO; -- used for debug outputs

procedure PlotInOne is

  procedure DPRINT(F:FLOAT) is      -- for temporary debugging outputs
  begin NUMERIC_IO.DISPLAYNUMERIC("Debug Output: ",F); end;

  PI : constant FLOAT := 3.1415926;

  type FUNC is access function (X:FLOAT) return FLOAT;

  subtype COORD is FLOAT;  -- Coordinates are proper types!

  type POINT is record     -- Points anyway...
    X,Y : COORD;
  end record;

  type Polygon is array(INTEGER range <>) of POINT;
  -- An unconstrained Polygon. USAGE: p: Polygon(1..10);

procedure DOPLOT(Graph: Polygon) is 
  -- How can a parameter be passed INTO DrawMain, which is called
  -- as a generic procedure from package LOGO, if Draw is defined
  -- not to have parameters?
  -- The only way I could see is copying the "GRAPH" parameter from
  -- DOPLOT to a local variable POINTS, that can be accessed in DrawMain.
  -- That might be a bit clumpsy; but... (any better ideas?)
  -- 
  -- (some days later) Hey, are you sure these local variables are _really_
  -- preserved?? In these case, the might still be on the the stack; but
  -- that's not guaranted, is it?

  POINTS : POLYGON(GRAPH'FIRST..GRAPH'LAST);

  MINX, MAXX, MINY, MAXY : COORD; -- the "borders" of the graph. Auto-detected.

  procedure DrawMain;
  package LOGO is new LOGO(DrawMain);

  procedure DrawMain is
  begin
    LOGO.SETSCALE(MINX, MAXX, 0.0, "X", "Y"); -- Y-axe always equals X-axe
    LOGO.PENUP;
    LOGO.GO_TO(POINTS(POINTS'FIRST).X, POINTS(POINTS'FIRST).Y);
    LOGO.PENDOWN;
    for I in POINTS'FIRST+1..POINTS'Last loop
      LOGO.GO_TO(POINTS(I).X, POINTS(I).Y);
    End loop;
  end DrawMain;

begin
  POINTS:=Graph;

  -- Determine the graph's border:
  MINX:=POINTS(1).X; MAXX:=MINX;
  MINY:=POINTS(1).Y; MAXY:=MINY;
  for I in 2..POINTS'LAST loop
    MINX:=COORD'MIN(MINX,POINTS(I).X); -- if POINTS(I).X<MINX then MINX:=POINTS(I).X;
    MAXX:=COORD'MAX(MAXX,POINTS(I).X);
    MINY:=COORD'MIN(MINY,POINTS(I).Y);
    MAXY:=COORD'MAX(MAXY,POINTS(I).Y);
  end loop;
  -- DPRINT(MINX); DPRINT(MAXX); DPRINT(MINY); DPRINT(MAXy);
  MINX:=COORD'MIN(MINX,MINY); -- The Y-axe cannot be modified separately.
  MAXX:=COORD'MAX(MAXX,MAXY); -- We simply take the larger of the two (x/y)
  -- DPRINT(MINX); DPRINT(MAXX);

  LOGO.AFFICHER;
end DOPLOT;

-- This is almost identical with LOGO.DrawFunction. It was anyway implemented.
procedure PlotXY(F:FUNC; x0,xn:Float; N:Integer := 500) is
  POINTS : POLYGON(1..N);
  DX     : COORD   := (XN-X0)/FLOAT(N);
begin
  for I in POINTS'FIRST..POINTS'LAST loop
    POINTS(I).X:=FLOAT(I-POINTS'FIRST)*DX-abs(X0);
    POINTS(I).Y:=FLOAT( F(POINTS(I).X) );
  end loop;
  DOPLOT(POINTS);
end PlotXY;

procedure PlotPol(F:FUNC; Phi0,PHIN:float; N:integer) is
  POINTS : POLYGON(1..N);
  PHI    : float  := PHI0;
  step   : float  := (PHIN-PHI0)/float(N);
  r      : float;
begin
  for I in POINTS'FIRST..POINTS'LAST loop
     R:=F(PHI);
     POINTS(I).X:=R*COS(PHI);
     POINTS(I).Y:=R*SIN(PHI);
     PHI:=PHI+STEP;
  end loop;
  DOPLOT(POINTS);
end PLOTPOL;

-- procedure PLOTPARAM(X,Y:FUNC; T0, T1, N:REAL) is 
-- ... is NOT YET PROGRAMMED. (but easy, too)

-- ----------------------------------------------------------------
-- Here are the some examples for the PLOT commands:

  function CIRCLE(PHI :float) return float is
    R: constant := 10.0;
  begin
    return R;
  end CIRCLE;

  function henrysfunc(X:FLOAT) return FLOAT is
  begin
    return (TAN(SIN(X))-SIN(TAN(X)))/(ARCTAN(ARCSIN(X)-ARCSIN(ARCTAN(X))));
  end;

  function LOGSPIRALE(phi:FLOAT) return FLOAT is
    ALPHA : constant FLOAT := 0.1763; -- arctg(10°)
  begin
    return EXP(PHI*alpha);
  end LOGSPIRALE;

  function KARDIOIDE(PHI:FLOAT) return FLOAT is
    A : constant float := 45.0;
  begin
    return A*(1.0+COS(PHI));
  end;


begin -- PlotInOne
  PLOTPOL(Kardioide'ACCESS,0.0,4.0*PI, 100);
  --PLOTPOL(LOGSPIRALE'ACCESS, 0.0, 20.0*PI, 1000);
  -- PLOTPOL(circle'Access, 0.0, 2.0*PI, 360);
  -- PLOTXY(SIN'ACCESS, -4.0*PI, 4.0*PI, 360);
  -- PLOTXY(HENRYSFUNC'ACCESS,-1.0,1.0,100);
end;   

A "Spirale Logarithmique" (see function LogSpirale above)

more ADA: [ Plot ] Sorting ] OOP-Matrices ] Symbol Table ] Sym. Derivation ]

Go to TOP of page
Page last modified on 11-Jan-99
© Copyright 1998-99 homepage@vorburger.ch [E-MAIL]

Site hosted by
ItaWeb, Peruggia (Italy)

KISSfp FrontPage Add-On
KISSfp FrontPage

  URL: http://www.vorburger.ch/projects/epfl/ada/ex1_plot.html