I am trying to make multiple graphs on the same field. You can set the resolution of the graph, that is, the number of points per wave (Step 10). A straight line can be specified with two points.
Code: Select all
EnableExplicit
Global.d cX0, cY0
Global.d mX, mY
Global xMax2, yMax2
;{ Simple Graph }
; Еще одна штука для простых "визуальных эффектов"
; 2017 (c) Luna Sole
; v1.0.0.4 (+ взаимодействие с мышью)
; Рисует график с двумя линиями на заданном изображении с использованием векторной библиотеки PB
; hImgOut Изображение PB для рисования может быть любого размера [кроме, возможно, «очень низкого» разрешения ^^]
; xMax, xMin максимальная и максимальная величина X графика
; yMax максимальная величина Y графика
; GridStepX Шаг сетки X [вертикальные линии], измеренное в количестве GraphData (). используйте 0 для отключения
; GridStepY Шаг сетки Y [горизонтальные линии], измеренное в значениях GraphData (). 0 для отключения
; FontSize размер шрифта текстовых меток. используйте 0, чтобы отключить метки
; ColorGrid цвета для элементов графика (RGB)
; RETURN: нет, изображение изменено в случае успеха
Procedure DrawGrid(hImgOut, xMax, xMin, yMax, GridStepX = 10, GridStepY = 10, FontSize = 9, ColorGrid = $BBFFFFFF)
Protected maxValues ; разница между xMax - xMin
Protected t ; переменная цикла для перечисления во времени, по оси Y
If yMax < 1
ProcedureReturn ; выйти, если данные из одной точки, график должен быть из нескольких точек по оси Y
EndIf
yMax2 = yMax ; задаём внешний, чтобы перечислять в цикле
; сделать вещи, чтобы лучше подогнать фоновую сетку
If GridStepY > 0
If xMax >= 0
xMax + GridStepY - xMax % GridStepY
ElseIf xMax
xMax - xMax % GridStepY
EndIf
If xMin > 0
xMin - xMin % GridStepY
ElseIf xMin < 0
xMin - (GridStepY + xMin % GridStepY)
EndIf
EndIf
maxValues = xMax - xMin
If maxValues <= 0
maxValues = 1
EndIf
; минимум значений оси Х
xMax2 = xMax
; загрузить шрифт для текстовых меток
Protected Font
If FontSize > 0
Font = LoadFont(#PB_Any, "arial", FontSize)
If Not IsFont(Font) ; и так далее
Font = LoadFont(#PB_Any, "tahoma", FontSize)
If Not IsFont(Font) ; и так далее.. :)
Font = LoadFont(#PB_Any, "consolas", FontSize)
EndIf
EndIf
EndIf
; рисовать данные в изображение
If StartVectorDrawing(ImageVectorOutput(hImgOut, #PB_Unit_Pixel))
Protected.d oX = 1.0, oY = oX
Protected.d mtW = 1.0, mtH = mtW
; временные переменные, используемые при рисовании
Protected.d cX, cY
Protected.d tLast
; [n] - определить смещения графиков / размеры текстовых меток и т. д.
If IsFont(Font)
VectorFont(FontID(Font), FontSize)
If VectorTextWidth(Str(xMax)) > VectorTextWidth(Str(xMin)) ; задаём ширину текста
oX = VectorTextWidth(Str(xMax)) + 2.0
Else
oX = VectorTextWidth(Str(xMin)) + 2.0
EndIf
oY = VectorTextHeight("0A") + 2.0
If oX > oY
oY = oX
Else
oX = oY
EndIf
mtW = VectorTextWidth(Str(yMax)) * 1.2
mtH = VectorTextHeight(Str(xMax)) * 0.8
EndIf
; множители для масштабирования координат графика
mX = (VectorOutputWidth() - oX * 2.0) / (yMax + Bool(yMax = 0))
mY = (VectorOutputHeight() - oY * 2.0) / maxValues
; [0] - рисовать текстовые метки и линии сетки
VectorSourceColor(ColorGrid) ; цвет меток и сетки шкалы
; горизонтальные линии / метки
tLast = oY + maxValues * mY + 5.0
If GridStepY > 0
For t = maxValues To 0 Step -1
If t % GridStepY = 0 Or t = maxValues
cY = oY + t * mY
; нарисовать текстовую метку
If IsFont(Font) And cY < tLast
MovePathCursor(oX - (2.0 + VectorTextWidth(Str(xMax - t))), cY - VectorTextHeight(Str(xMax - t)) / 2)
DrawVectorText(Str(xMax - t))
tLast = cY - mtH
EndIf
; нарисовать линию сетки
MovePathCursor(oX, oY + mY * t)
AddPathLine(oX + yMax * mX, oY + mY * t)
EndIf
Next
EndIf
; вертикальные линии / метки
tLast = 0.0
If GridStepX > 0
;GridStepX + 1
For t = 0 To yMax
If t % GridStepX = 0 Or t = yMax
cX = oX + t * mX
cY = oY + maxValues * mY
; нарисовать текстовую метку
If IsFont(Font) And cX > tLast
MovePathCursor(cX - VectorTextWidth(Str(t)) / 2, cY + 2.0)
DrawVectorText(Str(t))
tLast = cX + mtW
EndIf
; нарисовать линию сетки
MovePathCursor(cX, oY)
AddPathLine(cX, cY)
EndIf
Next
EndIf
; fin
If GridStepX > 0 Or GridStepY > 0
DashPath(1.0, 3.0)
EndIf
cX0 = oX
cY0 = oY
; StrokePath(LineWidth)
; очистить
StopVectorDrawing()
EndIf
; очистить
If IsFont(Font)
FreeFont(Font)
EndIf
EndProcedure
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Тест / пример
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; используется для обработки кликов мыши по графику
; mapkey - координата X изображения графика, value - соответствующий индекс в массиве GraphData()
Global NewMap GraphGeodata()
; Размеры графика
Global W = 800, H = 600
; Изображение для рисования графика
Global tImg
; Окно и холст для отображения графика
Global tWindow, tCanvas
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; сгенерировать графические данные
; 127 определяет число точек по оси Y
; создать изображение для получения вывода
tImg = CreateImage(#PB_Any, W, H, 32, $1B1B1B) ; цвет фона тут
DrawGrid(tImg, 60, -60, 127, 10, 10, 12)
; нарисовать график на созданном изображении
; Debug mX ; = 5.9
; Debug mY ; = 4
; Debug cX0 ; = 19.34375
; Debug cY0 ; = 19.34375
Define.d tmp, LineWidth = 1
Define t, j
Global Plot_Dot.b = 0
; Color цвет линии графика (RGB)
; LineWidth ширина линии (в пикселях)
; Plot_Dot показывать ли точки на графике
Procedure DrawGraph(tmp.d, t)
; временные переменные, используемые при рисовании
Protected.d cX, cY
cX = cX0 + mX * t
cY = cY0 + mY * (xMax2 - tmp)
If t = 0
MovePathCursor(cX0, cY)
EndIf
AddPathLine(cX, cY) ; добавить линию
If Plot_Dot
AddPathCircle(cX, cY, 2.0) ; добавить точку
EndIf
MovePathCursor(cX, cY) ; восстановить позицию курсора
EndProcedure
If StartVectorDrawing(ImageVectorOutput(tImg, #PB_Unit_Pixel)) ; открываем рисование
; рисуем синусоиду (выпрямленный ток) жёлтая
VectorSourceColor($FF00B1CB) ; задаём цвет линии (с добавлением альфа-канала слева ARGB)
j = 45
For t = 0 To yMax2
tmp = 60 * Abs(Sin(Radian(j-90)))
j+5
DrawGraph(tmp, t)
Next
StrokePath(LineWidth) ; рисует график в заданном цвете
; рисуем поверх косинусоиду
VectorSourceColor($FF80A800)
j = 0
For t = 0 To yMax2
tmp = 60 * Cos(Radian(j-90))
j+5
DrawGraph(tmp, t)
Next
StrokePath(LineWidth)
; рисуем поверх синусоиду
VectorSourceColor($FF9900FF) ; $00A800
j=0
For t = 0 To yMax2
tmp = - 60 * Sin(Radian(j-90))
j+5
DrawGraph(tmp, t)
Next
StrokePath(LineWidth)
; Plot_Dot = 1
; рисуем экпоненту
VectorSourceColor($FF2A04FF)
For t = 0 To yMax2 ; Step 6
; tmp = t * 0.8 - 60 ; линия наклонная
tmp = 60 * Exp(- t / 24) ; экпонента
DrawGraph(tmp, t)
Next
StrokePath(LineWidth)
; рисуем линию
VectorSourceColor($FF00A800)
DrawGraph(- 60, 0) ; начало
DrawGraph(127 * 0.8 - 60, 127) ; и конец линии
; For t = 0 To yMax2 Step 127
; tmp = t * 0.8 - 60 ; линия наклонная
; DrawGraph(tmp, t)
; Next
StrokePath(LineWidth)
; рисуем треугольную
VectorSourceColor($FFFF8C00)
For t = 0 To yMax2
tmp = 20 * (t/10 - 2 * Round((t/10 + 1) / 2, #PB_Round_Down)) * Pow(-1, Round((t/10 + 1) / 2, #PB_Round_Down)) - 40 ; Треугольный
DrawGraph(tmp, t)
Next
StrokePath(LineWidth)
StopVectorDrawing()
EndIf
; показать окно с графиком
tWindow = OpenWindow(#PB_Any, 0, 0, W, H, "График", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
; использовал ImageGadget вместо CanvasGadget, так заработало на Linux
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
tCanvas = CanvasGadget(#PB_Any, 0, 0, W, H)
SetGadgetAttribute(tCanvas, #PB_Canvas_Image, ImageID(tImg))
CompilerCase #PB_OS_Linux
ImageGadget(#PB_Any, 0, 0, W, H, ImageID(tImg))
CompilerEndSelect
; освободить изображение
FreeImage(tImg)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow