|
|
|
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: |
| ||||||||||||