|
@@ -0,0 +1,242 @@
|
|
|
+MODULE WMSimpleGraphs; (** AUTHOR "Patrick Hunziker"; PURPOSE "Minimum-overhead graph drawing and storing"; *)
|
|
|
+(** right-click on navigator thumbnail allows window storage as image file *)
|
|
|
+(* see WMMatrix.Mod in Matrix library for simple display of 2D Math array data as images *)
|
|
|
+
|
|
|
+(*ToDo: catch NaN and Inf in data and other strategies avoid erratic window sizes*)
|
|
|
+
|
|
|
+IMPORT WMWindowManager, Strings, WMGraphics, WMRectangles, Modules, Reals, KernelLog;
|
|
|
+
|
|
|
+TYPE
|
|
|
+ Histogram* = OBJECT (WMWindowManager.Window);
|
|
|
+ VAR
|
|
|
+ data:ARRAY [*] OF LONGREAL;
|
|
|
+ width,height:LONGINT;
|
|
|
+
|
|
|
+ PROCEDURE &New*(CONST data: ARRAY [*] OF LONGREAL; CONST title: ARRAY OF CHAR);
|
|
|
+ VAR max:LONGREAL;
|
|
|
+ BEGIN
|
|
|
+ SELF.data:=data;
|
|
|
+ max:=MAX(data);
|
|
|
+ width:=LEN(data,0); height:=ENTIER(max)+1;
|
|
|
+ Init(10*width, 10*height, FALSE);
|
|
|
+ WMWindowManager.GetDefaultManager().Add(100, 100, SELF, {WMWindowManager.FlagFrame,WMWindowManager.FlagClose});
|
|
|
+ SetTitle(Strings.NewString(title));
|
|
|
+ SetPointerInfo(manager.pointerCrosshair);
|
|
|
+ END New;
|
|
|
+
|
|
|
+ PROCEDURE Draw*(canvas : WMGraphics.Canvas; w, h, q : LONGINT);
|
|
|
+ VAR i:LONGINT;
|
|
|
+ BEGIN
|
|
|
+ canvas.Fill(WMRectangles.MakeRect(0, 0, w, h), WMGraphics.White, WMGraphics.ModeCopy);
|
|
|
+ FOR i:=0 TO LEN(data,0)-1 DO
|
|
|
+ canvas.Fill(WMRectangles.MakeRect( i*w DIV width , h-ENTIER(data[i]*h / height),
|
|
|
+ (i+1)*w DIV width , h), WMGraphics.Black, WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ INC(timestamp);
|
|
|
+ END Draw;
|
|
|
+ END Histogram;
|
|
|
+
|
|
|
+ Graph* = OBJECT (WMWindowManager.Window);
|
|
|
+ VAR
|
|
|
+ data:ARRAY [*] OF LONGREAL;
|
|
|
+ width,height:LONGINT;
|
|
|
+ max,min:LONGREAL;
|
|
|
+
|
|
|
+ PROCEDURE &New*(CONST data: ARRAY [*] OF LONGREAL; CONST title: ARRAY OF CHAR);
|
|
|
+ BEGIN
|
|
|
+ SELF.data:=data;
|
|
|
+ max:=MAX(data);
|
|
|
+ min:=MIN(0, MIN(data));
|
|
|
+ width:=LEN(data,0); height:=ENTIER(max-min)+1;
|
|
|
+ Init(10*width, 10*height, FALSE);
|
|
|
+ manager := WMWindowManager.GetDefaultManager();
|
|
|
+ manager.Add(150, 150, SELF, {WMWindowManager.FlagFrame,WMWindowManager.FlagClose});
|
|
|
+ SetTitle(Strings.NewString(title));
|
|
|
+ SetPointerInfo(manager.pointerCrosshair);
|
|
|
+ END New;
|
|
|
+
|
|
|
+ PROCEDURE Draw*(canvas : WMGraphics.Canvas; w, h, q : LONGINT);
|
|
|
+ VAR i:LONGINT; mn,mx:LONGINT;
|
|
|
+ BEGIN
|
|
|
+ canvas.Fill(WMRectangles.MakeRect(0, 0, w, h), WMGraphics.White, WMGraphics.ModeCopy);
|
|
|
+ mn:=ENTIER(0.5+min*h / height);
|
|
|
+ mx:=ENTIER(0.5+max*h / height);
|
|
|
+ FOR i:=0 TO LEN(data,0)-2 DO
|
|
|
+ canvas.Line(i*w DIV width, h+mn-ENTIER(0.5+data[i]*h / height),
|
|
|
+ (i+1)*w DIV width, h+mn-ENTIER(0.5+data[i+1]*h / height),
|
|
|
+ WMGraphics.Black, WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ IF mn#0 THEN
|
|
|
+ canvas.Line(0, h+mn, w, h+mn, WMGraphics.Black, WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ INC(timestamp);
|
|
|
+ END Draw;
|
|
|
+END Graph;
|
|
|
+
|
|
|
+GraphXY* = OBJECT (WMWindowManager.Window);
|
|
|
+ VAR
|
|
|
+ data:ARRAY [*,*] OF LONGREAL;
|
|
|
+ width,height:LONGINT;
|
|
|
+ max,min:LONGREAL;
|
|
|
+
|
|
|
+ PROCEDURE &New*(CONST data: ARRAY [*,*] OF LONGREAL; CONST title: ARRAY OF CHAR);
|
|
|
+ BEGIN
|
|
|
+ SELF.data:=data;
|
|
|
+ max:=MAX(0,MAX(data));
|
|
|
+ min:=MIN(0, MIN(data));
|
|
|
+ width:=ENTIER(max-min)+1; height:=ENTIER(max-min)+1;
|
|
|
+ Init(10*width, 10*height, FALSE);
|
|
|
+ manager := WMWindowManager.GetDefaultManager();
|
|
|
+ manager.Add(150, 150, SELF, {WMWindowManager.FlagFrame,WMWindowManager.FlagClose});
|
|
|
+ SetTitle(Strings.NewString(title));
|
|
|
+ SetPointerInfo(manager.pointerCrosshair);
|
|
|
+ END New;
|
|
|
+
|
|
|
+ PROCEDURE Draw*(canvas : WMGraphics.Canvas; w, h, q : LONGINT);
|
|
|
+ VAR i:LONGINT; mnw,mnh,mxw,mxh:LONGINT; scalex,scaley:REAL;
|
|
|
+ BEGIN
|
|
|
+ canvas.Fill(WMRectangles.MakeRect(0, 0, w, h), WMGraphics.White, WMGraphics.ModeCopy);
|
|
|
+ scalex:=w/width; scaley:=h/height;
|
|
|
+ mnw:=ENTIER(0.5+min* scalex); mxw:=ENTIER(0.5+max* scalex);
|
|
|
+ mnh:=ENTIER(0.5+min* scaley); mxh:=ENTIER(0.5+max* scaley);
|
|
|
+ FOR i:=0 TO LEN(data,1)-2 DO
|
|
|
+ canvas.Line(-mnw+ENTIER(0.5+data[0,i]*scalex), h+mnh-ENTIER(0.5+data[1,i]*scaley),
|
|
|
+ -mnw+ENTIER(0.5+data[0,i+1]*scalex), h+mnh-ENTIER(0.5+data[1,i+1]*scaley),
|
|
|
+ WMGraphics.Blue, WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ IF mnh#0 THEN
|
|
|
+ canvas.Line(0, h+mnh, w, h+mnh, WMGraphics.Black, WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ IF mnw#0 THEN
|
|
|
+ canvas.Line(-mnw, 0, -mnw, h, WMGraphics.Black, WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ INC(timestamp);
|
|
|
+ END Draw;
|
|
|
+END GraphXY;
|
|
|
+
|
|
|
+Graphs* = OBJECT (WMWindowManager.Window);
|
|
|
+ VAR
|
|
|
+ data:ARRAY [*,*] OF LONGREAL;
|
|
|
+ width,height:LONGINT;
|
|
|
+ max,min:LONGREAL;
|
|
|
+
|
|
|
+ PROCEDURE &New*(CONST data: ARRAY [*,*] OF LONGREAL; CONST title: ARRAY OF CHAR);
|
|
|
+ BEGIN
|
|
|
+ SELF.data:=data;
|
|
|
+ max:=MAX(data);
|
|
|
+ min:=MIN(0, MIN(data));
|
|
|
+ width:=LEN(data,1); height:=ENTIER(max-min)+1;
|
|
|
+ Init(10*width, 10*height, FALSE);
|
|
|
+ manager := WMWindowManager.GetDefaultManager();
|
|
|
+ manager.Add(200, 200, SELF, {WMWindowManager.FlagFrame,WMWindowManager.FlagClose});
|
|
|
+ SetTitle(Strings.NewString(title));
|
|
|
+ SetPointerInfo(manager.pointerCrosshair);
|
|
|
+ END New;
|
|
|
+
|
|
|
+ PROCEDURE Draw*(canvas : WMGraphics.Canvas; w, h, q : LONGINT);
|
|
|
+ VAR i,j:LONGINT; mn,mx:LONGINT;
|
|
|
+ BEGIN
|
|
|
+ canvas.Fill(WMRectangles.MakeRect(0, 0, w, h), WMGraphics.White, WMGraphics.ModeCopy);
|
|
|
+ mn:=ENTIER(0.5+min*h / height);
|
|
|
+ mx:=ENTIER(0.5+max*h / height);
|
|
|
+ FOR j:=0 TO LEN(data,0)-1 DO
|
|
|
+ FOR i:=0 TO LEN(data,1)-2 DO
|
|
|
+ canvas.Line(i*w DIV width, h+mn-ENTIER(0.5+data[j,i]*h / height),
|
|
|
+ (i+1)*w DIV width, h+mn-ENTIER(0.5+data[j,i+1]*h / height),
|
|
|
+ Colors[j MOD LEN(Colors,0)], WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ END;
|
|
|
+ IF mn#0 THEN
|
|
|
+ canvas.Line(0, h+mn, w, h+mn, WMGraphics.Black, WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ INC(timestamp);
|
|
|
+ END Draw;
|
|
|
+END Graphs;
|
|
|
+
|
|
|
+(** display matrix values in checkerboard like fashion. positive values are in black/grey/white, negative values in red*)
|
|
|
+Matrix* = OBJECT (WMWindowManager.Window);
|
|
|
+ VAR
|
|
|
+ data:ARRAY [*,*] OF LONGREAL;
|
|
|
+ width,height:LONGINT;
|
|
|
+ max,min, offset, gain:LONGREAL;
|
|
|
+
|
|
|
+ PROCEDURE &New*(CONST data: ARRAY [*,*] OF LONGREAL; CONST title: ARRAY OF CHAR);
|
|
|
+ BEGIN
|
|
|
+ SELF.data:=data;
|
|
|
+ min:=MIN(data); max:=MAX(data);
|
|
|
+ max:=MAX(ABS(min), ABS(max));
|
|
|
+ min:=MIN(0, min);
|
|
|
+ IF max=0 THEN max:=1 END;
|
|
|
+ width:=MAX(1,LEN(data,0));
|
|
|
+ height:=MAX(1,LEN(data,1));
|
|
|
+ Init(width, height, TRUE);
|
|
|
+ offset:=0; gain:=255/max;
|
|
|
+ IF( width<10) OR (height<10) THEN
|
|
|
+ bounds := WMGraphics.MakeRectangle(0, 0, 10*width, 10*height);(* grow small images *)
|
|
|
+ END;
|
|
|
+ manager := WMWindowManager.GetDefaultManager();
|
|
|
+ manager.Add(150, 150, SELF, {WMWindowManager.FlagFrame,WMWindowManager.FlagClose});
|
|
|
+ SetTitle(Strings.NewString(title));
|
|
|
+ SetPointerInfo(manager.pointerCrosshair);
|
|
|
+ END New;
|
|
|
+
|
|
|
+ PROCEDURE Draw*(canvas : WMGraphics.Canvas; w, h, q : LONGINT);
|
|
|
+ VAR col: WMGraphics.Color; x,y:LONGINT; val:LONGREAL; valI:LONGINT;
|
|
|
+ BEGIN
|
|
|
+ FOR y:=0 TO LEN(data,0)-1 DO
|
|
|
+ FOR x:=0 TO LEN(data,1)-1 DO
|
|
|
+ val:=data[y,x]; IF Reals.IsNaNL(val) THEN val:=0 END;
|
|
|
+ valI:=ENTIER(offset+gain*val);
|
|
|
+ valI:=MAX(-255, MIN( 255, valI));
|
|
|
+ IF valI>=0 THEN col:=WMGraphics.RGBAToColor(valI,valI,valI,255);
|
|
|
+ ELSE col:=WMGraphics.RGBAToColor(-valI,0,0,255);
|
|
|
+ END;
|
|
|
+ canvas.Fill(WMRectangles.MakeRect(x*w DIV width , h -ENTIER(0.5+(y+1)*h / height),
|
|
|
+ (x+1)*w DIV width , h-ENTIER(0.5+y*h / height)),
|
|
|
+ col, WMGraphics.ModeCopy);
|
|
|
+ END;
|
|
|
+ END;
|
|
|
+ INC(timestamp);
|
|
|
+ END Draw;
|
|
|
+END Matrix;
|
|
|
+
|
|
|
+VAR Colors: ARRAY [*] OF WMGraphics.Color;
|
|
|
+
|
|
|
+PROCEDURE Demo*;
|
|
|
+VAR h:Histogram; g:Graph; k: Graphs; gx:GraphXY; m:Matrix;
|
|
|
+BEGIN {EXCLUSIVE}
|
|
|
+ NEW(h,[4,7,8,4,5,9,6,5,3,2,12,17,3,0,2], "Histogram");
|
|
|
+ NEW(g,[4,7,8,4,5,9,6,5,3,2,12,17,3,-3,2], "Graph");
|
|
|
+ NEW(k,[[-2,7,8,4,5,9,6,4,7,8,4,5,9,6],
|
|
|
+ [5,3,2,12,21,3,0,5,3,-2,12,17,3,1]], "MultiGraph");
|
|
|
+ NEW(gx,[ [-2,-1,0,1,5,9,6,4,7,3,4,5,9,6],
|
|
|
+ [1,3,4,7,12,3,0,5,3,-2,12,17,3,1]], "GraphXY");
|
|
|
+ NEW(m,[[1,2,3,4],[4,3,2,4],[5,4,-2,-6],[3,1,0,-1]], "Matrix");
|
|
|
+END Demo;
|
|
|
+
|
|
|
+PROCEDURE Cleanup;
|
|
|
+VAR manager:WMWindowManager.WindowManager; w,remove:WMWindowManager.Window;
|
|
|
+BEGIN {EXCLUSIVE}
|
|
|
+ manager:=WMWindowManager.GetDefaultManager();
|
|
|
+ manager.lock.AcquireWrite;
|
|
|
+ w:=manager.GetFirst();
|
|
|
+ WHILE w#NIL DO
|
|
|
+ remove:=w;
|
|
|
+ w:=manager.GetNext(w);
|
|
|
+ IF (remove#NIL)&
|
|
|
+ ((remove IS Histogram) OR (remove IS Graph) OR (remove IS GraphXY) OR (remove IS Graphs) OR (remove IS Matrix))
|
|
|
+ THEN manager.Remove(remove);
|
|
|
+ END;
|
|
|
+ END;
|
|
|
+ manager.lock.ReleaseWrite;
|
|
|
+END Cleanup;
|
|
|
+
|
|
|
+BEGIN
|
|
|
+ Modules.InstallTermHandler(Cleanup);
|
|
|
+ Colors:=[WMGraphics.Red,WMGraphics.Blue,WMGraphics.Green,WMGraphics.Yellow, WMGraphics.Magenta, WMGraphics.Cyan, WMGraphics.Gray]
|
|
|
+END WMSimpleGraphs.
|
|
|
+
|
|
|
+SystemTools.Free WMSimpleGraphs ~
|
|
|
+
|
|
|
+WMSimpleGraphs.Demo ~
|
|
|
+
|