Skip to content

Instantly share code, notes, and snippets.

@danko3
Last active December 14, 2015 05:49
Show Gist options
  • Save danko3/5038268 to your computer and use it in GitHub Desktop.
Save danko3/5038268 to your computer and use it in GitHub Desktop.
Function Grapher by jonny. Hacked by me to be used by PlotFile.ahk.
;;;;;;;;;;;;;;;
;
; Function Grapher by jonny
;
;
;;;Functions;;;
;
;GraphCreate(id,x,y,w,h,pre="")
; Initializes the graph, sets its options,
; and draws it at the specified location.
; Returns 1 if it's successful, 0 if there's
; a logical error (e.g. bad option), and blank
; if there's a problem allocating memory.
;
; id:
; The window ID (ahk_id) of the window to
; draw the graph on.
;
; x:
; The x-coordinate to draw the graph at.
;
; y:
; The y-coordinate to draw the graph at.
;
; w:
; The width of the graph.
;
; h:
; The height of the graph.
;
; pre:
; The prefix for the global option variables,
; explained further below.
; For example, if pre = "GraphOpts_", then it
; will read GraphOpts_xScl for the xScl option
;
; color:
; The color to draw the equation in. This must
; be in RGB form (0xRRGGBB), not an HTML color.
; If this parameter is unspecified or not a valid
; RGB color, the defGraphColor option will be used.
;
;
;GraphClear()
; Clears all equations off the graph.
;
;
;GraphDraw()
; Redraws the graph. Shouldn't be necessary to
; use, since GraphCreate binds this to WM_PAINT.
;
;
;GraphDestroy()
; Frees all memory associated with the graph.
; You MUST call this before exiting the script,
; or there will be a memory leak.
; Note that this will not remove the graph's image
; from the display. The window must be redrawn
; to visually clear it.
;
;
;
;;;Options;;;
;
; To use these, set any of them as global variables
; with a consistent prefix (required). Then pass
; the prefix to GraphCreate as a string, via the
; 'pre' parameter. Any options left unset will get
; their default values.
;
;
;paperColor (0xFFFFFF - white)
; The color of the graph's background, or the
; "graph paper." Must be a full RGB color.
;
;axisColor (0x000000 - black)
; The color of the x and y axes, if visible.
; Must be a full RGB color.
;
;gridColor (0xDFDFDF - light grey)
; The color of the grid beneath the graph.
; Must be a full RGB color.
;
;defGraphColor (0x0000FF - blue)
; The default color for Graph(), if the 'color'
; parameter isn't valid or specified.
;
;lineWidth (3)
; The width of the lines generated by Graph().
; Must be greater than or equal to zero.
;
;xScl (1)
; The scale of the x-plane of the grid, in
; logical units. For instance, a value of 10
; would draw a vertical line wherever x is
; a multiple of 10, and a value of 0.5 would
; draw two vertical lines for every integral
; x-value. Must be greater than zero.
;
;yScl (1)
; The scale of the y-plane of the grid, in
; logical units. Same as above, except for
; the horizontal lines with y. Must be greater
; than zero.
;
;xMin (-10)
; The smallest x-value displayed on the graph,
; or the left edge of its viewable area. Must
; be less than xMax.
;
;yMin (-10)
; The smallest y-value displayed on the graph,
; or the bottom edge of its viewable area. Must
; be less than yMax.
;
;xMax (10)
; The largest x-value displayed on the graph,
; or the right edge of its viewable area. Must
; be greater than xMin.
;
;yMax (10)
; The largest y-value displayed on the graph,
; or the top edge of its viewable area. Must be
; greater than yMin.
;
;
;
;;;Remarks;;;
;
; Use this at your own risk. I've tested it a lot,
; but there's still a chance it'll cause a serious
; memory leak.
;
; Avoid naming any global variables with the prefix
; '__graph_' while the graph is created, since these
; functions use it to communicate.
;
; Graph() uses two temporary files which it creates
; in A_Temp, so don't be alarmed if you notice that
; your script is suddenly opening weird files. (It
; deletes them when it's finished, so they'll only
; consume space for a few milliseconds.)
;
; ;; Mods by danko
; * xScl and yScl xMax yMax
; * added tics and labels
GraphCreate(WindowID,xCoord,yCoord,Width,Height,OptPre="")
{
global
local paperColor,axisColor,gridColor,xScl,yScl,xMin,yMin
,xMax,yMax,Pen,Brush
if __graph_Exists
return 0
;Grid options
;background color (white)
;paperColor := %OptPre%paperColor ? %OptPre%paperColor : 0xFFFFFF
paperColor := 0xFFFFFF
;color for axes (black)
axisColor := %OptPre%axisColor ? %OptPre%axisColor : 0x000000
;grid color (grey)
gridColor := %OptPre%gridColor ? %OptPre%gridColor : 0xDFDFDF
;default color for new equations (blue)
__graph_color := %OptPre%defGraphColor ? %OptPre%defGraphColor : 0x0000FF
;scale of grid for the x plane
xScl := %OptPre%xScl ? %OptPre%xScl : PlotWidth/10
;scale of grid for the y plane
yScl := %OptPre%yScl ? %OptPre%yScl : PlotHeight/10
;lowest x-value shown on graph
xMin := %OptPre%xMin ? %OptPre%xMin : 0
;lowest y-value shown on graph
yMin := %OptPre%yMin ? %OptPre%yMin : 0
;highest x-value shown on graph
xMax := %OptPre%xMax ? %OptPre%xMax : Width
;highest y-value shown on graph
yMax := %OptPre%yMax ? %OptPre%yMax : Height
;sanity checks
if (paperColor > 0xFFFFFF || paperColor < 0
|| axisColor > 0xFFFFFF || axisColor < 0
|| gridColor > 0xFFFFFF || gridColor < 0
|| __graph_color > 0xFFFFFF || __graph_color < 0
|| __graph_lineWidth < 0
|| xScl <= 0 || yScl <= 0
|| xMin >= xMax || yMin >= yMax)
{
__graph_color =
__graph_lineWidth =
return 0
}
__graph_X := xCoord
__graph_Y := yCoord
__graph_W := Width
__graph_H := Height
;compute how many units on the graph each pixel
;corresponds to
__graph_xUnit := Width / (xMax - xMin)
__graph_yUnit := Height / (yMax - yMin)
;how far, in graph units, the left
;edge is from the origin
__graph_leftDist := xMin * __graph_xUnit
;how far the top edge is from the
;origin, this time in terms of y
__graph_topDist := yMax * __graph_yUnit
;Device Context for the window to be drawn to
__graph_WindowDC := DllCall("GetDC", UInt,WindowID)
if not __graph_WindowDC
return
;first memory DC, containing the "graph paper,"
;the background of the graph
__graph_PaperDC := DllCall("CreateCompatibleDC", UInt,WindowDC)
if not __graph_PaperDC
return
;create a bitmap on the DC
__graph_PaperDC_BM := DllCall("CreateCompatibleBitmap"
, UInt,__graph_WindowDC, UInt,Width, UInt,Height)
DllCall("SelectObject", UInt,__graph_PaperDC
, UInt,__graph_PaperDC_BM)
;second Memory DC, containing the finished product
;of the paper with the graphed equations on it
__graph_MemoryDC := DllCall("CreateCompatibleDC", UInt,WindowDC)
if not __graph_MemoryDC
return
;create a bitmap on the DC
__graph_MemoryDC_BM := DllCall("CreateCompatibleBitmap"
, UInt,__graph_WindowDC, UInt,Width, UInt,Height)
DllCall("SelectObject", UInt,__graph_MemoryDC
, UInt,__graph_MemoryDC_BM)
;set up the graph paper
;first the background and border
Pen := DllCall("CreatePen", UInt,0, UInt,0, UInt,paperColor)
DllCall("SelectObject", UInt,__graph_PaperDC, UInt,Pen)
Brush := DllCall("CreateSolidBrush", UInt,paperColor)
DllCall("SelectObject", UInt,__graph_PaperDC, UInt,Brush)
DllCall("Rectangle", UInt,__graph_PaperDC, UInt,0, UInt,0
, UInt,Width, UInt,Height)
DllCall("DeleteObject", UInt,Pen)
DllCall("DeleteObject", UInt,Brush)
;now the grid
Pen := DllCall("CreatePen", UInt,0, UInt,0, UInt,gridColor)
DllCall("SelectObject", UInt,__graph_PaperDC, UInt,Pen)
;vertical lines (x-plane)
Loop
{
if (A_Index >= ( (xMax - xMin) / xScl ))
break
DllCall("MoveToEx", UInt,__graph_PaperDC
, UInt,Round(A_Index*__graph_xUnit*xScl), UInt,0, UInt,0)
DllCall("LineTo", UInt,__graph_PaperDC
, UInt,Round(A_Index*__graph_xUnit*xScl), UInt,Height)
}
;horizontal lines (y-plane)
Loop
{
if (A_Index >= ( (yMax - yMin) / yScl ))
break
DllCall("MoveToEx", UInt,__graph_PaperDC
, UInt,0, UInt,Round(A_Index*__graph_yUnit*yScl), UInt,0)
DllCall("LineTo", UInt,__graph_PaperDC
, UInt,Width, UInt,Round(A_Index*__graph_yUnit*yScl))
}
DllCall("DeleteObject", UInt,Pen)
;axes
Pen := DllCall("CreatePen", UInt,0, UInt,0, UInt,axisColor)
DllCall("SelectObject", UInt,__graph_PaperDC, UInt,Pen)
if (xMin < 0 and xMax > 0)
{
DllCall("MoveToEx", UInt,__graph_PaperDC
, UInt,Round((-xMin)*__graph_xUnit), UInt,0, UInt,0)
DllCall("LineTo", UInt,__graph_PaperDC
, UInt,Round((-xMin)*__graph_xUnit), UInt,Height)
}
if (yMin < 0 and yMax > 0)
{
DllCall("MoveToEx", UInt,__graph_PaperDC
, UInt,0, UInt,Round(yMax*__graph_yUnit), UInt,0)
DllCall("LineTo", UInt,__graph_PaperDC
, UInt,Width, UInt,Round(yMax*__graph_yUnit))
}
DllCall("DeleteObject", UInt,Pen)
__graph_Exists := true
GraphClear()
; WM_PAINT: 0x0F
OnMessage(0x0F,"GraphDraw")
return 1
}
Graph(Equation,Color = -1)
{
global
local EquDC,EquDC_BM,Pen,FirstVal,GraphSpec,R,G,B
if (!__graph_Exists or !A_AhkPath)
return 0
if (Color < 0 or Color > 0xFFFFFF)
Color := __graph_color
;CreatePen expects a BGR-formatted COLORREF
R := Color & 0x0000FF
G := Color & 0x00FF00
B := Color & 0xFF0000
R <<= 16
B >>= 16
Color := R | G | B
;px/py: Positional coordinates used to
; place the graph
;
;x/y: Actual coordinates that the function
; is computed in
;
;Equation must be in terms of 'x'
FileAppend,
( LTrim
#NoTrayIcon
Loop %__graph_W%
{
px := A_Index
x := (px + %__graph_leftDist%) / %__graph_xUnit%
y := (%Equation%) * %__graph_yUnit%
py := Round(%__graph_topDist% - y)
GraphSpec .= py . ";"
}
FileDelete gspec
FileAppend,`%GraphSpec`%,gspec
),%A_Temp%\tempGraph.ahk
RunWait,"%A_AhkPath%" "%A_Temp%\tempGraph.ahk",%A_Temp%
FileRead,GraphSpec,%A_Temp%\gspec
FileDelete %A_Temp%\tempGraph.ahk
FileDelete %A_Temp%\gspec
Pen := DllCall("CreatePen", UInt,0, UInt,__graph_lineWidth, UInt,Color)
DllCall("SelectObject", UInt,__graph_MemoryDC, UInt,Pen)
StringTrimRight,GraphSpec,GraphSpec,1
FirstVal := InStr(GraphSpec,";")
DllCall("MoveToEx", UInt,__graph_MemoryDC, UInt,1, UInt,SubStr(GraphSpec,1,FirstVal-1), UInt,0)
StringTrimLeft,GraphSpec,GraphSpec,FirstVal
Loop,Parse,GraphSpec,;
DllCall("LineTo", UInt,__graph_MemoryDC, UInt,A_Index + 1, UInt,A_LoopField)
DllCall("DeleteObject", UInt,Pen)
GraphDraw()
return 1
}
GraphClear()
{
global
if not __graph_Exists
return
DllCall("BitBlt", UInt,__graph_MemoryDC, UInt,0, UInt,0
, UInt,__graph_W, UInt,__graph_H, UInt,__graph_PaperDC
, UInt,0, UInt,0, UInt,0x00CC0020)
GraphDraw()
}
GraphDraw()
{
global
if not __graph_Exists
return
DllCall("BitBlt", UInt,__graph_WindowDC, UInt,__graph_X
, UInt,__graph_Y, UInt,__graph_W, UInt,__graph_H
, UInt,__graph_MemoryDC, UInt,0, UInt,0, UInt,0x00CC0020)
}
GraphDestroy()
{
global
;WM_PAINT: 0x0F
OnMessage(0x0F,"")
DllCall("DeleteObject", UInt,__graph_PaperDC)
DllCall("DeleteObject", UInt,__graph_PaperDC_BM)
DllCall("DeleteObject", UInt,__graph_MemoryDC)
DllCall("DeleteObject", UInt,__graph_MemoryDC_BM)
DllCall("ReleaseDC", UInt,0, UInt,__graph_WindowDC)
__graph_PaperDC =
__graph_PaperDC_BM =
__graph_MemoryDC =
__graph_MemoryDC_BM =
__graph_WindowDC =
__graph_X =
__graph_Y =
__graph_W =
__graph_H =
__graph_color =
__graph_lineWidth =
__graph_xUnit =
__graph_yUnit =
__graph_leftDist =
__graph_topDist =
__graph_Exists =
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; added by danko
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Setup plot window, size, margins, etc.
; linewidth of graphs
__graph_lineWidth = 1
; Plot window size (real estate)
PlotHeight = 500
PlotWidth := round(x_A + x_A/10,-2)
if PlotWidth < 100
PlotWidth = 100
Topmargin = 40
BottomMargin = 80
LeftMargin = 60
;RightMargin = 50
tic = 5
longtic = 10
ylabel := round(ydif/plotheight,4)
;MsgBox, ylabel= %ylabel%
Y_Pos_top_X_Scale_tic := TopMargin-tic
Y_Pos_top_X_Scale_longtic := TopMargin-longtic
Y_Pos_bottom_X_Scale := PlotHeight+TopMargin
X_Pos_Left_Y_Scale_tic := LeftMargin-tic
X_Pos_Left_Y_Scale_longtic := LeftMargin-longtic
X_Pos_Right_Y_Scale := Plotwidth+LeftMargin
; Labelpositions
Y_Pos_top_X_label := TopMargin-3*longtic
Y_Pos_bottom_X_label := TopMargin+PlotHeight+longtic+5
X_Pos_Left_Y_label := LeftMargin-4*longtic
LegendaPos := Plotheight+Topmargin+50
; Plot window size (including borders)
WindowWidth := PlotWidth+LeftMargin+50
WindowHeight := PlotHeight+TopMargin+BottomMargin
; Scale / Ticmarks
; Made with tiny progress bars. Outside markers only
; because progress bars fall 'behind' the plot window.
; X-axis
;for the first Xtic (upper and lower axis)
Gui Add,Progress,w1 h10 x%LeftMargin% y%Y_Pos_top_X_Scale_longtic% background0000000
Gui Add,Progress,w1 h10 x%LeftMargin% y%Y_Pos_bottom_X_Scale% background0000000
; the first label
Gui Add,text, x%LeftMargin% y%Y_Pos_top_X_label% +Center, 0
;Gui Add,text, x%LeftMargin% y%Y_Pos_bottom_X_label% +Center, %time%
; tics and labels
loop, %PlotWidth%
{
if !mod(A_Index,10) ; tic every 10 units
{
pos := A_Index+LeftMargin
Gui Add,Progress,w1 h5 x%pos% y%Y_Pos_top_X_Scale_tic% background0000000
Gui Add,Progress,w1 h5 x%pos% y%Y_Pos_bottom_X_Scale% background0000000
}
if !mod(A_Index,50) ; long tic every 50 units
{
Gui Add,Progress,w1 h10 x%pos% y%Y_Pos_top_X_Scale_longtic% background0000000
Gui Add,Progress,w1 h10 x%pos% y%Y_Pos_bottom_X_Scale% background0000000
}
if !mod(A_Index,100) ; label every 100 units
Gui Add,text, x%pos% y%Y_Pos_top_X_label% +Center,%A_Index%
}
; Y-axis
;for the first Ytic (Left and right axis)
Gui Add,Progress,h1 w10 x%X_Pos_Left_Y_Scale_longtic% y%TopMargin% background0000000
Gui Add,Progress,h1 w10 x%X_Pos_Right_Y_Scale% y%TopMargin% background0000000
Y_label := round(ymin+ydif,2)
; the first Y label
Gui Add,text, y%Y_Pos_top_X_Scale_longtic% x%X_Pos_Left_Y_label% +Right w20,%Y_label%
;tics and labels
loop, %PlotHeight%
{
if !mod(A_Index,10) ; tic every 10 units
{
pos := A_Index+TopMargin
Gui Add,Progress,h1 w5 y%pos% x%X_Pos_Left_Y_Scale_tic% background0000000
Gui Add,Progress,h1 w5 y%pos% x%X_Pos_Right_Y_Scale% background0000000
}
if !mod(A_Index,50) ; long tic every 50 units
{
Gui Add,Progress,h1 w10 y%pos% x%X_Pos_Left_Y_Scale_longtic% background0000000
Gui Add,Progress,h1 w10 y%pos% x%X_Pos_Right_Y_Scale% background0000000
}
pos := pos-10
if !mod(A_Index,100) ; label every 100 units
{
Y_label := round(Ymin+ydif-A_Index*ylabel,2)
Gui Add,text, y%pos% x%X_Pos_Left_Y_label% +Right,%y_label%
}
}
; Legenda demo
; Red progressbar first
Gui Add,Progress,h10 w30 y%LegendaPos% x%LeftMargin% backgroundff00000
gui, font, bold cred
Gui Add,text, xp+35 yp-4, chan1
; Green progressbar
Gui Add,Progress,h10 w30 y%LegendaPos% xp+100 background00aa00
gui, font, c009900 ; a darker shade of green. (more esthetic?)
Gui Add,text, xp+35 yp-4, chan2
gui, font ; reset the font
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment