home *** CD-ROM | disk | FTP | other *** search
- unit PGRAPH;
- interface
- uses CRT,GRAPH;
- const
- {$IFDEF CPU87} MaxInt=2147483647; {$ENDIF}
- nmax=200;
- const
- Black:byte=0; Blue:byte=1; Green:byte=2; Cyan:byte=3;
- Red:byte=4; Magenta:byte=5; Brown:byte=6; LightGray:byte=7;
- DarkGray:byte=8; LightBlue:byte=9; LightGreen:byte=10; LightCyan:byte=11;
- LightRed:byte=12; LightMagenta:byte=13; Yellow:byte=14; White:byte=15;
- type
- {$IFDEF CPU87} real=extended; {$ELSE}
- double=real; single=real; extended=real; comp=real; {$ENDIF}
- GeraetTyp = (Bildschirm,Drucker,Plotter);
- Vektor = array[1..nmax] of real;
- strg80 = string[80];
- var
- Geraet:GeraetTyp; { fuer AngleTrueScale }
- GraphDriver,GraphMode,ErrorCode:integer;
- OldExitProc:Pointer;
- Xaxmin,Xaxmax,Yaxmin,Yaxmax:real; { fuer USCALE }
- Uaxmin,Uaxmax,Vaxmin,Vaxmax:integer; { fuer Graphikwindow }
-
- procedure AngleTrueScale(var x1,x2,y1,y2:real);
- procedure CloseGraphik;
- procedure Curve(var x,y:Vektor; n,Lintyp,Thickness,Color:word);
- procedure Curvex(var x,y:Vektor; n:word; Color:byte);
- function EXP10(x:real):real;
- function Exponent(x:real):integer;
- procedure Extrema(z:Vektor; n:word; var zmin,zmax:real);
- procedure GraphikText(Text:strg80; Font, Size, TxtCol, Line:byte);
- procedure GraphikWindow(x1,x2,y1,y2:integer);
- procedure LinaxScale(var a,b,dx,Ex:real; Density:byte; var ExpStrg:strg80);
- function LOG10(x:real):real;
- procedure LogXAxis(LogX1,LogX2:real; XText:strg80; Font,Size:word);
- procedure LogYAxis(LogY1,LogY2:real; YText:strg80; Font,Size:word);
- procedure OpenGraphik;
- function RealToString(x:real):strg80;
- procedure Scale(x,y:real; VAR u,v:integer);
- procedure Uscale(var X1,X2,Y1,Y2:real; Origin,AngleTrue:boolean; Expans:real);
- procedure XAxis(x1,x2:real; XText:strg80; Font,Size:word);
- procedure Xgrid(x:real);
- procedure Xmark(x:real; var u:integer; Len:byte);
- procedure YAxis(y1,y2:real; YText:strg80; Font,Size:word);
- procedure Ymark(y:real; var v:integer; Len:byte);
- procedure Ygrid(y:real);
-
- implementation
-
- procedure AngleTrueScale; { Winkeltreue Skalierung }
- var C,dx,dy,xx,yy,xm,ym,F:real; Xasp,Yasp:word;
- begin
- if Geraet=Bildschirm then begin { Laenge/Breite-Faktor }
- GetAspectRatio(Xasp,Yasp);
- F:=(Xasp/Yasp)*(ABS(UaxMin-UaxMax)/ABS(VaxMin-VaxMax)); end
- else begin
- F:=(2/3)*(ABS(UaxMin-UaxMax)/ABS(VaxMin-VaxMax))
- end;
- dx:=ABS(x2-x1);
- dy:=ABS(y2-y1);
- if dx>=dy then begin
- yy:=0.5*dx/F; if y1>y2 then yy:=-yy; { y-Achse strecken }
- ym:=0.5*(y1+y2); y1:=ym-yy; y2:=ym+yy; end
- else begin
- xx:=0.5*dy*F; if x1>x2 then xx:=-xx; { x-Achse strecken }
- xm:=0.5*(x1+x2); x1:=xm-xx; x2:=xm+xx;
- end;
- end;
-
- {$F+} procedure CloseGraphik; { Graphik beenden }
- begin
- ExitProc:=OldExitProc;
- SetBkColor(black);
- CloseGraph;
- DirectVideo:=true;
- Window(1,1,80,25);
- end; {$F-}
-
- procedure Curve; { Polygonzug }
- var i,u1,v1,u2,v2:integer;
- begin
- SetLineStyle(Lintyp,0,Thickness); SetColor(Color);
- Scale(x[1],y[1],u1,v1);
- for i:=2 to n do begin
- Scale(x[i],y[i],u2,v2); Line(u1,v1,u2,v2);
- u1:=u2; v1:=v2;
- end;
- end;
-
- procedure Curvex; { Punkte auftragen }
- var i,u,v:integer;
- begin
- for i:=1 to n do begin
- Scale(x[i],y[i],u,v); PutPixel(u,v,Color);
- end;
- end;
-
- function EXP10;
- var S:string[80]; E:real; Code:word;
- begin
- if x=INT(x) then begin { 10 hoch Integer }
- STR(TRUNC(x),S);
- VAL(('1.0E'+S),E,Code); EXP10:=E; Exit;
- end;
- EXP10:=EXP(x*LN(10)); { 10 hoch Real }
- end;
-
- function Exponent; { Groessenordnung }
- var EX,S:string[80]; n,code:integer; { einer Zahl }
- begin
- STR(x,S); EX:=COPY(S,POS('E',S)+1,Length(S));
- VAL(EX,n,code); Exponent:=n;
- end;
-
- procedure Extrema; { Maximum und Minimum }
- var i:word; { des Vektors z[1..n] }
- begin
- zmin:=z[1]; zmax:=z[1];
- for i:=2 to n do begin
- if z[i]<zmin then zmin:=z[i];
- if z[i]>zmax then zmax:=z[i];
- end;
- end;
-
- procedure GraphikText; { Textausgabe ins }
- var Xpos,Ypos:integer; { Graphikfenster }
- begin
- if (Font>4) or (Font<0) then Font:=1;
- if (Size>10) or (Size<1) then Size:=1;
- if (Line>24) then Line:=24; { Zeile 1..24 }
- if (Line<1) then Line:=1;
- if Font=2 then Size:=Size*2;
- SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
- SetColor(TxtCol);
- SetTextStyle(Font,HorizDir,Size);
- SetTextJustify(CenterText,CenterText); { Zentrieren }
- Xpos:=SUCC(GetMaxX) div 2;
- Ypos:=Line*(GetMaxY div 25);
- OutTextXY(Xpos,Ypos,Text);
- end;
-
- procedure GraphikWindow; { Graphikfenster }
- var h:integer;
- begin
- SetLineStyle(SolidLn,0,NormWidth); SetColor(White);
- if x1>x2 then begin h:=x1; x1:=x2; x2:=h; end;
- if y1>y2 then begin h:=y1; y1:=y2; y2:=h; end;
- Line(x1,GetMaxY-y1,x2,GetMaxY-y1); { Rahmen }
- Line(x2,GetMaxY-y1,x2,GetMaxY-y2);
- Line(x2,GetMaxY-y2,x1,GetMaxY-y2);
- Line(x1,GetMaxY-y2,x1,GetMaxY-y1);
- Uaxmin:=x1; Uaxmax:=x2; Vaxmin:=y1; Vaxmax:=y2; { Fensterkoordinaten }
- end;
-
- procedure LinaxScale; { Hilfsroutine fuer }
- var x1,x2:real; { Xaxis und Yaxis }
- begin
- if ABS(a)<ABS(b) then EX:=Exponent(b) else EX:=Exponent(a);
- x1:=a; x2:=b; dx:=0.25*EXP10(Exponent(b-a));
- ExpStrg:='0';
- if ABS(Ex)>3 then begin { Exponent abtrennen }
- a:=a*EXP10(-EX); b:=b*EXP10(-EX); dx:=dx*EXP10(-EX);
- STR(EX:4:0,ExpStrg); while ExpStrg[1]=#32 do Delete(ExpStrg,1,1);
- end;
- while ((b-a)/dx)>=Density do dx:=2*dx; { Skalendichte }
- if b<a then dx:=-dx;
- if a=b then begin a:=a-dx; b:=b+dx; end;
- a:=dx*ROUND(a/dx); { Guenstig runden }
- b:=dx*ROUND(b/dx);
- if a<b then begin
- if a<x1 then a:=a+dx; if b>x2 then b:=b-dx; end
- else begin
- if a>x1 then a:=a-dx; if b<x2 then b:=b+dx;
- end;
- end;
-
- function LOG10; { dekad. Logarithmus }
- begin
- if x<>0 then LOG10:=LN(ABS(x))/LN(10.0) else LOG10:=0;
- end;
-
- procedure LogXAxis; { Log. x-Achse }
- const Density=10; { Skalendichte }
- var dn,n1,n2,n,k,u,v:integer; x:real; S:string[6];
- begin
- Line(Uaxmin,GetMaxY-Vaxmin,Uaxmax,GetMaxY-Vaxmin);
- u:=(Uaxmax+Uaxmin) div 2;
- v:=GetMaxY-(Vaxmin-3*TextHeight(XText));
- SetTextStyle(Font,HorizDir,Size);
- SetTextJustify(CenterText,CenterText);
- OutTextXY(u,v,XText); { Achsenbeschriftung }
- n1:=TRUNC(LogX1); n2:=TRUNC(LogX2);
- if n1>n2 then begin k:=n1; n1:=n2; n2:=k; end;
- dn:=1; while (n2-n1) div dn>=Density do dn:=Density*dn;
- if dn=1 then begin { Log-Skala }
- for n:=n1-1 to n2+1 do
- for k:=2 to 9 do begin x:=n+LOG10(k); Xmark(x,u,3); end;
- end;
- for n:=n1 to n2 do begin
- if (dn<>1) and ((n mod (dn div 10))=0) then Xmark(n,u,3);
- if (n mod dn)=0 then begin
- Xmark(n,u,4);
- STR(n,S);
- OutTextXY(u+TextWidth(S)*4 div 5,GetMaxY-Vaxmin+(TextHeight('0') div 2),S);
- OutTextXY(u-TextWidth('0') div 2,GetMaxY-Vaxmin+TextHeight('0'),'10');
- end;
- end;
- end;
-
- procedure LogYAxis; { log. y-Achse }
- const Density=10; { Skalendichte }
- var dn,n1,n2,n,k,u,v:integer; y:real; S:string[6];
- begin
- Line(Uaxmin,GetMaxY-Vaxmin,Uaxmin,GetMaxY-Vaxmax);
- u:=Uaxmin-3*TextHeight(YText);
- v:=(Vaxmax-Vaxmin) div 2;
- SetTextStyle(Font,VertDir,Size);
- SetTextJustify(CenterText,CenterText);
- OutTextXY(u,v,YText); { Achsenbeschriftung }
- n1:=TRUNC(LogY1); n2:=TRUNC(LogY2);
- if n1>n2 then begin k:=n1; n1:=n2; n2:=k; end;
- dn:=1; while (n2-n1) div dn>=Density do dn:=Density*dn;
- if dn=1 then begin { Log-Skala }
- for n:=n1-1 to n2+1 do
- for k:=2 to 9 do begin y:=n+LOG10(k); Ymark(y,v,3); end;
- end;
- for n:=n1 to n2 do begin
- if (dn<>1) and ((n mod (dn div 10))=0) then Ymark(n,u,3);
- if (n mod dn)=0 then begin
- Ymark(n,v,4);
- STR(n,S);
- OutTextXY(Uaxmin-TextHeight('0'),v-TextWidth(S)*3 div 4,S);
- OutTextXY(Uaxmin-TextHeight('0') div 2,v+TextWidth('0') div 2,'10');
- end;
- end;
- end;
-
- procedure OpenGraphik; { Graphik starten }
- begin
- DirectVideo:=false; { Graphik- und Textmode }
- OldExitProc:=ExitProc; ExitProc:=ADDR(CloseGraphik);
- GraphDriver:=Detect;
- InitGraph(GraphDriver,GraphMode,'');
- ErrorCode:=GraphResult;
- if ErrorCode<>grOk then begin
- WriteLn('Graphics error: ',GraphErrorMsg(ErrorCode)); ReadLn;
- Halt(1);
- end;
- if GraphDriver=7 then begin
- Black:=0; Blue:=15; Green:=15; Cyan:=15;
- Red:=15; Magenta:=15; Brown:=15; LightGray:=15;
- DarkGray:=15; LightBlue:=15; LightGreen:=15; LightCyan:=15;
- LightRed:=15; LightMagenta:=15; Yellow:=15; White:=15;
- end;
- if Geraet in [Bildschirm,Drucker,Plotter] then else Geraet:=Drucker;
- Uaxmin:=0; Uaxmax:=GetMaxX; Vaxmin:=0; Vaxmax:=GetMaxY;
- end;
-
- function RealToString; { Reelle Zahl in }
- var S:strg80; Code:word; { handlichen String }
- begin
- STR(x:16:10,S);
- while s[1]=#32 do Delete(S,1,1);
- while S[Length(s)]='0' do begin Delete(S,Length(S),1); end;
- if POS('.',S)=Length(S) then Delete(S,Length(S),1);
- VAL(S,x,Code); if x=0 then S:='0';
- RealToString:=S;
- end;
-
- procedure Scale; { Absolute Skalierung }
- begin
- u:= Uaxmin+ROUND((x-Xaxmin)/(Xaxmax-Xaxmin)*(Uaxmax-Uaxmin));
- v:=GetMaxY-ROUND((y-Yaxmin)/(Yaxmax-Yaxmin)*(Vaxmax-Vaxmin))-Vaxmin;
- end;
-
- procedure Uscale; { Benutzer- }
- var xx,yy:real; { koordinatensystem }
- const Tol = 0.01;
- begin
- Expans:=ABS(Expans);
- xx:=ABS(x2-x1)*0.005*Expans; if x1>x2 then xx:=-xx; { 1. Ausweiten }
- X1:=X1-xx; X2:=X2+xx;
- if ABS(x2-x1)<1E-8 then
- begin x1:=x1*(1-0.01*Expans); x2:=x2*(1+0.01*Expans); end;
- yy:=ABS(y2-y1)*0.005*Expans; if y1>y2 then yy:=-yy;
- y1:=y1-yy; y2:=y2+yy;
- if ABS(y2-y1)<1E-8 then
- begin y1:=y1*(1-0.01*Expans); y2:=y2*(1+0.01*Expans); end;
- if Origin then begin { 2. Ursprung }
- if X1<=X2 then begin
- if X2<0 then X2:=0;
- if X1>0 then X1:=0; end
- else begin
- if X2>0 then X2:=0;
- if X1<0 then X1:=0;
- end;
- if Y1<=Y2 then begin
- if Y2<0 then Y2:=0;
- if Y1>0 then Y1:=0; end
- else begin
- if Y2>0 then Y2:=0;
- if Y1<0 then Y1:=0;
- end;
- end;
- if AngleTrue then AngleTrueScale(X1,X2,Y1,Y2); { 3. Winkeltreue }
- if ABS((X2-X1)/X2)<Tol then begin { 4. Minimalausdehnung }
- if X1<X2 then
- begin X1:=X1*(1-Tol); X2:=X2*(1+Tol); end
- else begin X2:=X2*(1-Tol); X1:=X1*(1+Tol); end;
- end;
- if ABS((Y2-Y1)/Y2)<Tol then begin
- if Y1<Y2 then
- begin Y1:=Y1*(1-Tol); Y2:=Y2*(1+Tol); end
- else begin Y2:=Y2*(1-Tol); Y1:=Y1*(1+Tol); end;
- end;
- Xaxmin:=X1; Xaxmax:=X2;
- Yaxmin:=Y1; Yaxmax:=Y2;
- end;
-
- procedure XAxis; { lineare x-Achse }
- var Xpos,Ypos:integer;
- Ex,U,V,a,b,x,dx,h:real; E,S:strg80;
- const Density=6; { Skalendichte }
- begin
- Line(Uaxmin,GetMaxY-Vaxmin,Uaxmax,GetMaxY-Vaxmin);
- Xpos:=(Uaxmax+Uaxmin) div 2;
- Ypos:=GetMaxY-(Vaxmin-3*TextHeight(XText));
- a:=x1; b:=x2; if a>b then begin h:=b; b:=a; a:=b; end;
- LinaxScale(x1,x2,dx,Ex,Density,E);
- if x1>x2 then begin h:=x1; x1:=x2; x2:=h; dx:=ABS(dx); end;
- SetTextStyle(Font,HorizDir,Size);
- SetTextJustify(CenterText,CenterText);
- if E='0' then { Achsenbeschriftung }
- OutTextXY(Xpos,Ypos,XText)
- else begin
- U:=Xaxmin; V:=XaxMax;
- OutTextXY(Xpos,Ypos,XText+' *E'+E);
- a:=a*EXP10(-Ex); b:=b*EXP10(-Ex); Xaxmin:=a; Xaxmax:=b;
- end;
- x:=x1; { lineare Skala }
- Xmark(x-dx/2,xpos,3);
- repeat
- Xmark(x+dx/2,xpos,3);
- Xmark(x,xpos,3);
- S:=RealToString(x);
- Line(Xpos,GetMaxY-Vaxmin,Xpos,GetMaxY-Vaxmin-3);
- if Length(S)<6 then OutTextXY(Xpos,GetMaxY-Vaxmin+TextHeight('0'),S);
- x:=x+dx;
- until (x>=b) or (x<=a);
- if E<>'0' then begin Xaxmin:=U; XaxMax:=V; end;
- end;
-
- procedure Xgrid; { Parallele zur }
- var u,v:integer; { x-Achse }
- begin
- Scale(x,0,u,v);
- if u>Uaxmin then Line(u,GetMaxY-Vaxmin,u,GetMaxY-Vaxmax);
- end;
-
- procedure Xmark; { x-Achsenmarken: }
- var v:integer; { Hilfsroutine fuer }
- begin { Xaxis und LogXAxis }
- Scale(x,Yaxmin,u,v);
- if (u>=UaxMin) and (u<=UaxMax) then
- Line(u,GetMaxY-Vaxmin,u,GetMaxY-Vaxmin-Len);
- end;
-
- procedure YAxis; { lineare y-Achse }
- var Xpos,Ypos:integer;
- Ex,U,V,a,b,y,dy,h:real; E,S:strg80;
- const Density=8; { Skalendichte }
- begin
- Line(Uaxmin,GetMaxY-Vaxmin,Uaxmin,GetMaxY-Vaxmax);
- Xpos:=Uaxmin-3*TextHeight(YText);
- Ypos:=(Vaxmax-Vaxmin) div 2;
- a:=y1; b:=y2; if a>b then begin h:=b; b:=a; a:=b; end;
- LinaxScale(y1,y2,dy,Ex,Density,E);
- if y1>y2 then begin h:=y1; y1:=y2; y2:=h; dy:=ABS(dy); end;
- SetTextStyle(Font,VertDir,Size);
- SetTextJustify(CenterText,CenterText);
- if E='0' then { Achsenbeschriftung }
- OutTextXY(Xpos,Ypos,YText)
- else begin
- U:=Yaxmin; V:=YaxMax;
- OutTextXY(Xpos,Ypos,YText+' *E'+E);
- a:=a*EXP10(-Ex); b:=b*EXP10(-Ex); Yaxmin:=a; Yaxmax:=b;
- end;
- y:=y1; { lineare Skala }
- Ymark(y-dy/2,ypos,3);
- repeat
- Ymark(y+dy/2,ypos,3);
- S:=RealToString(y);
- Ymark(y,ypos,3);
- if Length(S)<6 then OutTextXY(Uaxmin-TextHeight('0'),Ypos,S);
- y:=y+dy;
- until (y>=b) or (y<=a);
- if E<>'0' then begin Yaxmin:=U; YaxMax:=V; end;
- end;
-
- procedure Ygrid; { Parallele zur }
- var u,v:integer; { y-Achse }
- begin
- Scale(0,y,u,v);
- if v<GetMaxY-Vaxmin then Line(Uaxmin,v,Uaxmax,v);
- end;
-
- procedure Ymark; { y-Achsenmarken: }
- var u:integer; { Hilfsroutine fuer }
- begin { Yaxis und LogYAxis }
- Scale(Xaxmin,y,u,v);
- if (v<GetMaxY-Vaxmin) and (v>GetMaxY-Vaxmax) then
- Line(Uaxmin,v,Uaxmin+Len,v);
- end;
-
- end.
-