home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* DATAED.PAS *)
- (* Grafikgestützter Meßdateneditor *)
- (* Turbo Pascal ab 5.0 *)
- (* (C) 1990 Peter Kurzweil & TOOLBOX *)
- (* ------------------------------------------------------ *)
-
- PROGRAM Messdateneditor;
-
- USES Crt, Dos, Printer, Graph, PGRAPH;
-
- TYPE
- ScaleTyp = (linear, lineardown, log, logdown);
- CONST
- GraphActiv: BOOLEAN=FALSE;
- VAR
- ESC, UP, DOWN, LEFT, RIGHT, RETURN: BOOLEAN;
- ch: CHAR;
- x, y, z: Vektor; a, b: REAL; i, n: WORD; { Stützstellen }
-
- PROCEDURE DataEditor(VAR x, y, z: Vektor;
- VAR n: WORD;
- xTxt, yTxt, zTxt: strg80;
- xscal, yscal: ScaleTyp;
- AngleTrue: BOOLEAN); FORWARD;
-
- PROCEDURE Graphik(x, y: Vektor;
- n: WORD;
- xtitel, ytitel: strg80;
- x1, x2, y1, y2: REAL;
- UserUscale: BOOLEAN;
- xscal, yscal: ScaleTyp;
- Origin, AngleTrue: BOOLEAN;
- ex: REAL;
- Lintyp, Thickness, Color, CurvexCol: BYTE;
- Nr: INTEGER); FORWARD;
-
- PROCEDURE ManualScaling(x, y: Vektor; n: WORD;
- VAR xmin, xmax, ymin, ymax: REAL;
- VAR UserUscale, AngleTrue: BOOLEAN;
- xTxt, yTxt: strg80;
- xscal, yscal: ScaleTyp); FORWARD;
-
- {---------------------- Hilfsroutinen -------------------- }
-
- FUNCTION FORMAT(x:REAL; f:BYTE): strg80; { Zahlenformat }
- VAR S: strg80;
- BEGIN { Gleitkomma }
- IF Abs(LOG10(x))<=5 THEN Str(x:f:5,S) ELSE
- BEGIN { E-Format }
- Str(x:f,S);
- WHILE Length(S)>f DO Delete(S,Pos('E',S)+2,1);
- WHILE Length(S)>f DO Delete(S,Pos('E',S)-1,1);
- END;
- FORMAT:=S;
- END;
-
- FUNCTION SFORMAT(S: strg80; len: BYTE): strg80;
- VAR i,k:BYTE; S1:strg80;
- BEGIN
- WHILE Length(S)>len DO Delete(S, Length(S), 1);
- WHILE S[1]=#32 DO Delete(S, 1, 1); S1:=S;
- k:=(len-Length(S)) DIV 2; S:='';
- FOR i:=1 TO k DO S:=S+#32; S:=S+S1;
- FOR i:=Length(S)+1 TO len DO S:=S+#32;
- SFORMAT:=S;
- END;
-
- PROCEDURE InKey; { Tastaturabfrage }
- VAR Regs: Registers;
- BEGIN
- UP:=FALSE; DOWN:=FALSE; LEFT:=FALSE; RIGHT:=FALSE;
- RETURN:=FALSE; ESC:=FALSE;
- Regs.AX:=$0C00; MsDos(Regs); { Lösche Tastaturpuffer }
- ch:=UpCase(ReadKey);
- CASE ch OF
- #0: BEGIN
- ch:=ReadKey;
- CASE ch OF
- #$48: UP:=TRUE; { Cursor UP }
- #$50: DOWN:=TRUE; { Cursor DOWN }
- #$4B: LEFT:=TRUE; { Cursor LEFT }
- #$4D: RIGHT:=TRUE { Cursor RIGHT }
- END;
- ch:=#32;
- END;
- #13: RETURN:=TRUE; { CR }
- #27: ESC:=TRUE; { ESC }
- END;
- END;
-
- PROCEDURE SwapMinMax(VAR x1, x2: REAL); { Vertauschen }
- VAR h: REAL; { x1 < x2 }
- BEGIN
- IF x1>x2 THEN BEGIN h:=x1; x1:=x2; x2:=h; END;
- END;
-
- PROCEDURE SwapMaxMin(VAR x1, x2: REAL); { Vertauschen }
- VAR h: REAL; { x1 > x2 }
- BEGIN
- IF x1<x2 THEN BEGIN h:=x1; x1:=x2; x2:=h; END;
- END;
-
- PROCEDURE ExtremaAbs(z: Vektor; n: WORD;
- VAR zmin, zmax: REAL);
- VAR i: WORD; a: REAL;
- BEGIN
- zmin:=Abs(z[1]); zmax:=zmin;
- FOR i:=2 TO n DO BEGIN
- a:=Abs(z[i]);
- IF a<zmin THEN zmin:=a;
- IF a>zmax THEN zmax:=a;
- END;
- END;
-
- PROCEDURE InfoLine(Msg: strg80; Line, TCol, BCol: BYTE);
- VAR k: BYTE; { Zentrierte Textausgabe }
- BEGIN
- TextColor(TCol); TextBackground(BCol);
- k:=(80-Length(Msg)+1) DIV 2;
- GotoXY(1, Line); ClrEol; GotoXY(k, Line); Write(Msg);
- END;
-
- {----------------------------------------------------------}
- { Graphikgestützer Meßdateneditor }
- {----------------------------------------------------------}
-
- {$F+}
- PROCEDURE CloseGraphik; { Verbesserte Version für PGRAPH }
- BEGIN
- GraphActiv:=FALSE;
- CloseGraph;
- END;
- {$F-}
-
- PROCEDURE OpenGraphik; { Verbesserte Version für PGRAPH }
- BEGIN { Schutz vor mehrmaligem Öffnen }
- IF GraphActiv THEN CloseGraphik;
- GraphActiv:=TRUE; GraphDriver:=Detect;
- InitGraph(GraphDriver, GraphMode, '');
- IF GraphResult<>grOk THEN BEGIN
- WriteLn('FEHLER: ', GraphErrorMsg(ErrorCode)); Halt;
- END;
- IF GraphDriver IN [1, 2, 7] THEN BEGIN
- Black:=0; Blue:=7; Green:=15; Cyan:=15; Red:=15;
- Magenta:=15; Brown:=15; LightGray:=7; DarkGray:=15;
- LightBlue:=15; LightGreen:=15; LightCyan:=15;
- LightRed:=15; LightMagenta:=15; Yellow:=15; White:=15;
- END;
- Uaxmin:=0; Uaxmax:=GetMaxX; Vaxmin:=0; Vaxmax:=GetMaxY;
- END;
-
- PROCEDURE Cross(x, y: REAL); { Fadenkreuz }
- CONST len=12;
- VAR u, v: INTEGER;
- BEGIN
- SetWriteMode(XORPut);
- SetColor(White); Scale(x, y, u, v);
- Line(u-len, v, u+len, v); Line(u, v-len, u, v+len);
- PutPixel(u, v, White);
- SetWriteMode(NormalPut);
- END;
-
- PROCEDURE InfoLineGraphik(Msg: strg80; Line, Color: BYTE);
- VAR h, len, x: WORD; { Textausgabe im Graphikmodus }
- BEGIN
- SetColor(Color); SetTextStyle(Defaultfont, HorizDir, 1);
- SetTextJustify(CenterText, CenterText);
- h:=(GetMaxY DIV 24);
- len:=TextWidth(Msg+'MM') DIV 2; x:=(GetMaxX DIV 2);
- IF Line>=25 THEN
- SetViewPort(0, GetMaxY-h, GetMaxX, GetMaxY, TRUE)
- ELSE SetViewPort(x-len, (Line-1)*h, x+len, Line*h, TRUE);
- ClearViewPort;
- SetViewPort(0, 0, GetMaxX, GetMaxY, TRUE);
- OutTextXY(x, Trunc((Line-0.5)*h), Msg);
- END;
-
- PROCEDURE DataEditor; { Graphikgestützter Meßdateneditor }
- VAR
- Msg, S: strg80; i: INTEGER; k, i1, i2: WORD;
- x1, x2, y1, y2, a, b, r, da, db, xo, xm, ym, sx, sy: REAL;
- xx, yy: Vektor;
- UserUscale: BOOLEAN; lx, ly: STRING[4];
-
- PROCEDURE Reset; { Bildaufbau }
- BEGIN
- Graphik(x, y, n, xTxt, yTxt, x1, x2, y1, y2, UserUscale,
- xscal, yscal, FALSE, AngleTrue, 999, SolidLn,
- NormWidth, Yellow, White, 001);
- InfoLineGraphik('(CURSOR) Kreuz bewegen, (SHIFT CURSOR)'
- +' schnell bewegen, (ESC) Ende', 1, White);
- InfoLineGraphik('(L)öschen, (A)chsen anpassen,'+
- ' (N)eu zeichnen', 2, White);
- InfoLineGraphik(xTxt, 24, White);
- END;
-
- BEGIN
- UserUscale:=FALSE; Reset;
- lx:=''; ly:=''; i:=1; i1:=0; i2:=0;
- IF xscal IN [linear, lineardown] THEN xx:=x;
- IF yscal IN [linear, lineardown] THEN yy:=y;
- IF xscal IN [log, logdown] THEN BEGIN
- FOR k:=1 TO n DO xx[k]:=LOG10(x[k]); lx:='log ';
- END;
- IF yscal IN [log, logdown] THEN BEGIN
- FOR k:=1 TO n DO yy[k]:=LOG10(y[k]); ly:='log ';
- END;
- Cross(xx[i], yy[i]);
- REPEAT
- Str(i, S); { Zahlenleiste }
- Msg:='Wert-Nr. '+S+#32#32+xTxt+' = '+FORMAT(x[i],8)+
- #32#32+yTxt+' = '+FORMAT(y[i],8)+#32#32+zTxt+' = '+
- FORMAT(z[i], 8);
- InfoLineGraphik(Msg, 25, White);
- InKey;
- Cross(xx[i], yy[i]);
- IF UP OR LEFT THEN { Cursortasten }
- IF i>1 THEN
- Dec(i);
- IF DOWN OR RIGHT THEN
- IF i<n THEN
- Inc(i);
- CASE ch OF { Steuerzeichen }
- '8','4': BEGIN
- i:=i-5;
- IF i<=1 THEN BEGIN i:=1;
- Curve(xx, yy, n, SolidLn,
- NormWidth, Yellow);
- END;
- END;
- '6','2': BEGIN
- i:=i+5;
- IF i>=n THEN BEGIN i:=n;
- Curve(xx, yy, n, SolidLn,
- NormWidth, Yellow);
- END;
- END;
- 'L': BEGIN { Meßpunkt löschen }
- IF n>3 THEN BEGIN
- Curve(xx, yy, n, SolidLn,
- NormWidth, Black);
- FOR k:=i+1 TO n DO BEGIN
- x[k-1]:=x[k]; y[k-1]:=y[k];
- z[k-1]:=z[k]; xx[k-1]:=xx[k];
- yy[k-1]:=yy[k];
- END;
- n:=n-1; IF i>=n THEN i:=n;
- Curve(xx, yy, n, SolidLn, NormWidth,
- Yellow);
- END ELSE Write(#7);
- END;
- 'N': Reset; { Kurve auffrischen }
- 'A': BEGIN { Manuelle Skalierung }
- CloseGraphik;
- ManualScaling(x, y, n, x1, x2, y1, y2,
- UserUscale, AngleTrue, xTxt,
- yTxt, xscal, yscal);
- Reset;
- END;
- END;
- Cross(xx[i], yy[i]); { Kreuz verschieben }
- UNTIL ESC;
- CloseGraphik;
- END;
-
- PROCEDURE Graphik; { Treiberroutine für Graphikbibliothek }
- VAR h: INTEGER;
-
- PROCEDURE Scale; { Skalierung für log. Achsen }
- VAR i: WORD;
- BEGIN
- IF xscal IN [log, logdown] THEN
- FOR i:=1 TO n DO x[i]:=LOG10(x[i]);
- IF yscal IN [log, logdown] THEN
- FOR i:=1 TO n DO y[i]:=LOG10(y[i]);
- END;
-
- PROCEDURE MakeUscale; { Koordinatensystem }
- BEGIN
- IF (NOT UserUscale) THEN BEGIN { ...automatisch }
- extrema(x, n, x1, x2); extrema(y, n, y1, y2);
- END;
- IF UserUscale THEN BEGIN { ...vorgegeben }
- IF xscal IN [log, logdown] THEN BEGIN
- x1:=LOG10(x1); x2:=LOG10(x2);
- END;
- IF yscal IN [log, logdown] THEN BEGIN
- y1:=LOG10(y1); y2:=LOG10(y2);
- END;
- END;
- IF xscal IN [lineardown, logdown] THEN
- SwapMaxMin(x1, x2);
- IF yscal IN [lineardown, logdown] THEN
- SwapMaxMin(y1, y2);
- IF xscal IN [linear, log] THEN SwapMinMax(x1, x2);
- IF yscal IN [linear, log] THEN SwapMinMax(y1, y2);
- IF ex=999 THEN BEGIN { Ausweitung }
- ex:=5; IF UserUscale THEN ex:=0;
- END;
- uscale(x1, x2, y1, y2, Origin, AngleTrue, ex);
- END;
-
- PROCEDURE MakeAxis; { Achsen bestellen }
- BEGIN
- IF xscal IN [linear, lineardown] THEN { x-Achse linear }
- XAxis(x1, x2, xtitel, Defaultfont, 1);
- IF yscal IN [linear, lineardown] THEN { y-Achse linear }
- YAxis(y1, y2, ytitel, Defaultfont, 1);
- IF xscal IN [log, logdown] THEN { x-Achse log. }
- LogXAxis(x1, x2, xtitel, Defaultfont, 1);
- IF yscal IN [log, logdown] THEN { y-Achse log. }
- LogYAxis(y1, y2, ytitel, Defaultfont, 1);
- XGrid(0); { Nullinie }
- YGrid(0);
- END;
-
- BEGIN
- Scale;
- IF Nr=1 THEN BEGIN { Uscale bei erster Kurve }
- OpenGraphik;
- h:=TextHeight('Mg');
- GraphikWindow(5*h, GetMaxX-4*h, 4*h, GetMaxY-2*h);
- MakeUscale;
- MakeAxis;
- END;
- IF Nr<0 THEN MakeUscale; { Uscale wechseln }
- Curve(x, y, n, Lintyp, Thickness, Color);
- IF (CurvexCol IN [0..15]) THEN Curvex(x, y, n, CurvexCol);
- IF Nr=999 THEN CloseGraphik; { letztes Bild }
- END;
-
- PROCEDURE ManualScaling; { Menü zur Achsenanpassung }
- VAR Msg: strg80;
-
- PROCEDURE expand(VAR a, b: REAL; p: REAL;
- zscal: ScaleTyp);
- VAR zz, z1, z2: REAL;
- BEGIN { Vergrößern/Verkleinern }
- z1:=a; z2:=b;
- IF zscal IN [log, logdown] THEN
- BEGIN z1:=LOG10(a); z2:=LOG10(b); END;
- zz:=Abs(z2-z1)*0.005*p; IF z1>z2 THEN zz:=-zz;
- z1:=z1-zz; z2:=z2+zz;
- IF zscal IN [log, logdown] THEN
- BEGIN z1:=exp10(z1); z2:=exp10(z2); END;
- a:=z1; b:=z2;
- END;
-
- PROCEDURE WriteValues; { Achsenausdehnung anzeigen }
- VAR k: BYTE;
- BEGIN
- IF UserUscale THEN InfoLine(
- 'Benutzereigenes Koordinatensystem', 4, White, Black)
- ELSE
- InfoLine('Automatische Skalierung', 4, White, Black);
- TextBackground(Black); TextColor(Yellow);
- WriteLn(#13#10);
- WriteLn(' Achsenausdehnung ',
- ' Größe');
- WriteLn(' Minimum Maximum ');
- FOR k:=1 TO 75 DO Write('-'); WriteLn(#13#10);
- WriteLn('X-Achse: ', FORMAT(xmin, 12), ' ',
- FORMAT(xmax,12), ' ', xTxt, #13#10);
- WriteLn('Y-Achse: ', FORMAT(ymin, 12), ' ',
- FORMAT(ymax,12), ' ', yTxt, #13#10#10#10);
- END;
-
- PROCEDURE FindExtrema(z: Vektor; n: WORD; zscal: ScaleTyp;
- VAR zmin, zmax: REAL);
- BEGIN
- IF zscal IN [linear, lineardown] THEN
- extrema(z, n, zmin, zmax)
- ELSE ExtremaAbs(z, n, zmin, zmax);
- END;
-
- BEGIN
- TextBackground(0); ClrScr;
- InfoLine('Manuelle Skalierung', 2, Black, White);
- InfoLine('(X)-Achse (Y)-Achse (W)inkeltreu (A)utomatik'+
- ' (+) Größer (-) Kleiner (ESC) Ende',
- 3, Black, White);
- IF NOT UserUscale THEN BEGIN
- FindExtrema(x, n, xscal, xmin, xmax);
- FindExtrema(y, n, yscal, ymin, ymax);
- END;
- WriteValues;
- REPEAT
- TextColor(White); TextBackground(Black); InKey;
- CASE ch OF
- 'A': BEGIN
- UserUscale:=FALSE; { Autoskalierung }
- FindExtrema(x, n, xscal, xmin, xmax);
- FindExtrema(y, n, yscal, ymin, ymax);
- END;
- 'W': BEGIN
- AngleTrue:=NOT AngleTrue; { Winkeltreue }
- IF AngleTrue THEN
- InfoLine('Winkeltreue', 23, 0, 15)
- ELSE InfoLine('Winkeltreue AUS', 23, 0, 15);
- END;
- 'X': BEGIN { x-Ausdehnung }
- UserUscale:=TRUE; AngleTrue:=FALSE;
- Write('X-Achse minimum: ');
- ClrEol; ReadLn(xmin);
- Write(' maximum: ');
- ClrEol; ReadLn(xmax);
- IF (xscal IN [log, logdown]) AND ((xmin<=0) OR
- (xmax<=0)) OR (xmin=xmax) THEN BEGIN
- Write(#7);
- FindExtrema(x, n, xscal, xmin, xmax);
- END;
- END;
- 'Y': BEGIN { y-Ausdehnung }
- UserUscale:=TRUE; AngleTrue:=FALSE;
- Write('Y-Achse minimum: ');
- ClrEol; ReadLn(ymin);
- Write(' maximum: ');
- ClrEol; ReadLn(ymax);
- IF (yscal IN [log, logdown]) AND ((ymin<=0) OR
- (ymax<=0)) OR (ymin=ymax) THEN BEGIN
- Write(#7);
- FindExtrema(y, n, yscal, ymin, ymax);
- END;
- END;
- '-': BEGIN { Verkleinern }
- UserUscale:=TRUE;
- InfoLine('Kurve um 10 % verkleinert',
- 23, 0, 15);
- expand(xmin, xmax, 10, xscal);
- expand(ymin, ymax, 10, yscal);
- END;
- '+': BEGIN { Vergrößern }
- UserUscale:=TRUE;
- InfoLine('Kurve um 10 % vergrößert',
- 23, 0, 15);
- expand(xmin, xmax, -10, xscal);
- expand(ymin, ymax, -10, yscal);
- END;
- END;
- WriteValues;
- UNTIL ESC;
- ESC:=FALSE;
- END;
-
- {----------------------------------------------------------}
- { Hauptprogramm: Anwendungsbeispiele }
- {----------------------------------------------------------}
-
- BEGIN
- Geraet:=Bildschirm;
- Randomize;
- a:=-2*Pi; b:=2*Pi; n:=100; { Datensatz erzeugen }
- FOR i:=1 TO n DO BEGIN
- x[i]:=(i-1)*(b-a)/n+a;
- y[i]:=Sin(1.5*x[i])+2*Cos(2.5*x[i])-0.5;
- x[i]:=x[i]*(1.0+0.05*Random); { Rauschen }
- y[i]:=y[i]*(1.0+0.2*Random);
- z[i]:=Sqrt(x[i]*x[i]+y[i]*y[i]);
- END;
- DataEditor(x, y, z, n, 'A', 'B', 'Betrag', linear,
- linear, TRUE);
- DataEditor(x, y, z, n, 'x [ppm]', 'y-Signal', 'z', linear,
- log, FALSE);
- RestoreCRTMode;
- END.