|
This is the first of the five exercises 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 -- 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: |
|