home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
1990
/
10
/
ldm
/
dataed.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1990-07-20
|
16KB
|
467 lines
(* ------------------------------------------------------ *)
(* 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.