Существует ли аналог такого модуля. Я ранее использовал это в программе (скриншот), показалось это не сложно сделать. В некой области рисовать линии, рисовать сетку с заданными значениями, рисовать шкалу на осях.
Существует ли модуль создания графиков?
Сообщений 1 страница 6 из 6
Поделиться427.08.2020 17:39:50
Пётр
Если рисовать много графиков на одном поле, надо переделывать, так как автоматически рассчитывает сетку и для второго графика сетка накладывается с учётом максимального и минимального значений.
Вот поигрался (и перевёл на русский язык).
EnableExplicit
;{ Simple Graph }
; Еще одна штука для простых "визуальных эффектов"
; 2017 (c) Luna Sole
; v1.0.0.4 (+ взаимодействие с мышью)
; Рисует график с двумя линиями на заданном изображении с использованием векторной библиотеки PB
; hImgOut Изображение PB для рисования может быть любого размера [кроме, возможно, «очень низкого» разрешения ^^]
; GraphData() массив с элементами для визуализации, должен содержать как минимум 1 элемент [начиная с 0]
; OutGeoData() map для получения данных, необходимых для обработки взаимодействия с мышью. map key = координата X на изображении графика, value = связанный индекс GraphData()
; Average сколько элементов используется для расчета среднего значения для текущего элемента? 2 минимально, если меньше будет отключено
; GridStepX Шаг сетки X [вертикальные линии], измеренное в количестве GraphData (). используйте 0 для отключения
; GridStepY Шаг сетки Y [горизонтальные линии], измеренное в значениях GraphData (). 0 для отключения
; FontSize размер шрифта текстовых меток. используйте 0, чтобы отключить метки
; ColorN цвета для элементов графика (RGB)
; RETURN: нет, изображение изменено в случае успеха
Procedure DrawSimpleGraph (hImgOut, Array GraphData(1), Map OutGeoData(), Average, GridStepX = 10, GridStepY = 10, FontSize = 9, Color1 = $00DDDD, Color2 = $DDDD00)
ClearMap(OutGeoData()) ; сбросить данные мыши
Protected maxItems = ArraySize(GraphData()) ; количество пунктов (X)
Protected maxValues ; количество значений (Y)
Protected highValue, lowValue ; самые высокие и самые низкие значения GraphData
Protected t ; общая временная переменная
If maxItems < 0 : ProcedureReturn : EndIf ; выйти, если массив GraphData недействителен
; Найти минимум и максимум значений, чтобы трансформировать шкалу
Protected Dim TData(0)
CopyArray(GraphData(), TData())
SortArray(TData(), #PB_Sort_Ascending)
lowValue = TData(0)
highValue = TData(maxItems)
FreeArray(TData())
; сделать вещи, чтобы лучше подогнать фоновую сетку
If GridStepY > 0
If highValue >= 0
highValue + GridStepY - highValue % GridStepY
ElseIf highValue
highValue - highValue % GridStepY
EndIf
If lowValue > 0
lowValue - lowValue % GridStepY
ElseIf lowValue < 0
lowValue - (GridStepY + lowValue % GridStepY)
EndIf
EndIf
maxValues = highValue - lowValue
If maxValues <= 0
maxValues = 1
EndIf
; загрузить шрифт для текстовых меток
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))
; [n] - определить смещения графиков / размеры текстовых меток и т. д.
Protected.d oX = 1.0, oY = oX
Protected.d mtW = 1.0, mtH = mtW
If IsFont(Font)
VectorFont(FontID(Font), FontSize)
If VectorTextWidth(Str(highValue)) > VectorTextWidth(Str(lowValue)) ; задаём ширину текста
oX = VectorTextWidth(Str(highValue)) + 2.0
Else
oX = VectorTextWidth(Str(lowValue)) + 2.0
EndIf
oY = VectorTextHeight("0A") + 2.0
If oX > oY
oY = oX
Else
oX = oY
EndIf
mtW = VectorTextWidth(Str(maxItems)) * 1.2
mtH = VectorTextHeight(Str(highValue)) * 0.8
EndIf
; ширина линии (в пикселях)
Protected.d LineWidth = 1.0
; множители для масштабирования координат графика
Protected.d mX = (VectorOutputWidth() - oX * 2.0) / (maxItems + Bool(maxItems = 0))
Protected.d mY = (VectorOutputHeight() - oY * 2.0) / maxValues
; временные переменные, используемые при рисовании
Protected.d cX, cY
; [0] - рисовать текстовые метки и линии сетки
VectorSourceColor($77FFFFFF) ; цвет меток и сетки шкалы
Protected.d tLast
; горизонтальные линии / метки
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(highValue - t))), cY - VectorTextHeight(Str(highValue - t)) * 0.5)
DrawVectorText(Str(highValue - t))
tLast = cY - mtH
EndIf
; нарисовать линию сетки
MovePathCursor(oX, oY + mY * t)
AddPathLine(oX + maxItems * mX, oY + mY * t)
EndIf
Next t
EndIf
; вертикальные линии / метки
tLast = 0.0
If GridStepX > 0
;GridStepX + 1
For t = 0 To maxItems
If t % GridStepX = 0 Or t = maxItems
cX = oX + t * mX
cY = oY + maxValues * mY
; нарисовать текстовую метку
If IsFont(Font) And cX > tLast
MovePathCursor(cX - VectorTextWidth(Str(t)) * 0.5, cY + 2.0)
DrawVectorText(Str(t))
tLast = cX + mtW
EndIf
; нарисовать линию сетки
MovePathCursor(cX, oY)
AddPathLine(cX, cY)
EndIf
Next t
EndIf
; fin
If GridStepX > 0 Or GridStepY > 0
DashPath(1.0, 3.0)
EndIf
; [1] - нарисуйте основную линию / элементы и сформируйте "геоданные"
Protected.d gX = oX
Protected.d gX2
VectorSourceColor(Color1 | $FF000000)
MovePathCursor(oX, oY + mY * (highValue - GraphData(0)))
For t = 0 To maxItems
cX = oX + mX * t
cY = oY + mY * (highValue - GraphData(t))
AddPathLine(cX, cY) ; добавить линию
AddPathCircle(cX, cY, 2.0) ; добавить точку
MovePathCursor(cX, cY) ; восстановить позицию курсора
; построить те "геоданные", которые используются для работы с мышью
gX2 = gX + (cX - gX) * 0.5
While gX < gX2
OutGeoData(Str(Int(gX))) = t - 1
gX + 1.0
Wend
While gX < cX
OutGeoData(Str(Int(gX))) = t
gX + 1.0
Wend
gX = cX
Next t
StrokePath(LineWidth)
; [2] - нарисовать «тренд» / усредненную линию
Protected NewList Avg() ; стек для хранения последних значений
Protected.d Avg ; рассчитать текущий результат
If Average > maxItems + 1
Average = maxItems + 1
EndIf
If Average > 1 ; имеет смысл рисовать, только если он больше 1
While ListSize(Avg()) < Average
AddElement(Avg()) ; 'экстраполировать' с использованием данных первого элемента, без этого все выглядит хуже для меня: 3
Avg() = GraphData(0)
Wend
MovePathCursor(oX, oY + (highValue - GraphData(0)) * mY)
For t = 0 To maxItems
FirstElement(Avg()) ; все это работает как стековая структура с максимальной глубиной = Average
DeleteElement(Avg())
LastElement(Avg())
AddElement(Avg())
Avg() = GraphData(t) ; нажать новый элемент
Avg = 0.0 ; рассчитать среднее значение по последним элементам
ForEach Avg()
Avg + Avg()
Next
cX = oX + mX * t
cY = oY + (highValue - Avg / Average) * mY
AddPathLine(cX, cY) ; добавить линию
AddPathCircle(cX, cY, 1.0) ; добавить точку
MovePathCursor(cX, cY) ; восстановить позицию курсора
Next t
VectorSourceColor(Color2 | $FF000000)
StrokePath(LineWidth)
EndIf
; очистить
FreeList(Avg())
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
; Эта процедура обрабатывает события мыши на холсте графика.
Procedure GraphCB()
Protected cX = GetGadgetAttribute(tCanvas, #PB_Canvas_MouseX)
Select EventType()
Case #PB_EventType_LeftButtonDown:
If FindMapElement(GraphGeodata(), Str(cX))
Debug "Нажата левая кнопка мыши " + GraphGeodata()
EndIf
Case #PB_EventType_LeftButtonUp:
If FindMapElement(GraphGeodata(), Str(cX))
Debug "Отпущена левая кнопка мыши " + GraphGeodata()
EndIf
Case #PB_EventType_LeftClick:
If FindMapElement(GraphGeodata(), Str(cX))
Debug "Клик левой кнопкой мыши " + GraphGeodata()
EndIf
Case #PB_EventType_RightButtonDown:
If FindMapElement(GraphGeodata(), Str(cX))
Debug "Нажата правая кнопка мыши " + GraphGeodata()
EndIf
Case #PB_EventType_RightButtonUp:
If FindMapElement(GraphGeodata(), Str(cX))
Debug "Отпущена правая кнопка мыши " + GraphGeodata()
EndIf
Case #PB_EventType_RightClick:
If FindMapElement(GraphGeodata(), Str(cX))
Debug "Клик правой кнопкой мыши " + GraphGeodata()
EndIf
Case #PB_EventType_MouseMove:
If FindMapElement(GraphGeodata(), Str(cX))
Debug "Мышь наведена на элемент " + GraphGeodata()
EndIf
EndSelect
EndProcedure
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; сгенерировать графические данные
Dim GraphValues (127) ; размер массива определяет число точек по оси Y
Define t
Define j=0
For t = 0 To ArraySize(GraphValues())
; GraphValues(t) =Pow(t , 2)
; GraphValues(t) =60 * Cos(Radian(j-90))
GraphValues(t) =60 * Sin(Radian(j-90))
j+5
Next t
; создать изображение для получения вывода
tImg = CreateImage(#PB_Any, W, H, 32, $1B1B1B) ; цвет фона тут
; нарисовать график на созданном изображении
DrawSimpleGraph(tImg, GraphValues(), GraphGeodata(), 0, 10, 10, 12)
; рисуем ещё поверх
j=0
For t = 0 To ArraySize(GraphValues())
; GraphValues(t) =Pow(t , 2)
GraphValues(t) =60 * Cos(Radian(j-90))
; GraphValues(t) =60 * Sin(Radian(j-90))
j+5
Next t
DrawSimpleGraph(tImg, GraphValues(), GraphGeodata(), 0, 10, 10, 12, $80A800)
; рисуем ещё поверх
j=0
For t = 0 To ArraySize(GraphValues())
; GraphValues(t) =Pow(t , 2)
; GraphValues(t) =60 * Cos(Radian(j-90))
GraphValues(t) = - 60 * Sin(Radian(j-90))
j+5
Next t
DrawSimpleGraph(tImg, GraphValues(), GraphGeodata(), 0, 10, 10, 12, $9900FF)
; рисуем ещё поверх
; For t = 0 To ArraySize(GraphValues())
; GraphValues(t) = t * 0.8 - 60 ; линия наклонная
; GraphValues(t) = 60*Exp(- t / 24) ; экпонента
; GraphValues(t) =60 * Abs(Sin(Radian(j-90)))
; Next t
; DrawSimpleGraph(tImg, GraphValues(), GraphGeodata(), 0, 10, 10, 12, $80A800)
; показать
tWindow = OpenWindow(#PB_Any, 0, 0, W, H, "График", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
tCanvas = CanvasGadget(#PB_Any, 0, 0, W, H)
SetGadgetAttribute(tCanvas, #PB_Canvas_Image, ImageID(tImg))
; привязать события, необходимые для взаимодействия с мышью
; BindEvent(#PB_Event_Gadget, @GraphCB(), tWindow, tCanvas, #PB_All)
; освободить изображение
FreeImage(tImg)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindowОтредактировано AZJIO (28.08.2020 08:41:16)
Поделиться528.08.2020 08:46:15
разделил функции создания сетки и графика. Теперь можно создавать несколько графиков. Оптимизировать ещё есть куда. В AutoIt3 функция не имела привязки к точкам, если это прямая то можно получить начало и конец и нарисовать прямую, без деление участка на отрезки для каждой координаты.
EnableExplicit
Global.d cX0, cY0
Global.d mX, mY
Global highValue, maxItems
;{ Simple Graph }
; Еще одна штука для простых "визуальных эффектов"
; 2017 (c) Luna Sole
; v1.0.0.4 (+ взаимодействие с мышью)
; Рисует график с двумя линиями на заданном изображении с использованием векторной библиотеки PB
; hImgOut Изображение PB для рисования может быть любого размера [кроме, возможно, «очень низкого» разрешения ^^]
; GraphData() массив с элементами для визуализации, должен содержать как минимум 1 элемент [начиная с 0]
; GridStepX Шаг сетки X [вертикальные линии], измеренное в количестве GraphData (). используйте 0 для отключения
; GridStepY Шаг сетки Y [горизонтальные линии], измеренное в значениях GraphData (). 0 для отключения
; FontSize размер шрифта текстовых меток. используйте 0, чтобы отключить метки
; ColorGrid цвета для элементов графика (RGB)
; RETURN: нет, изображение изменено в случае успеха
Procedure DrawGrid(hImgOut, Array GraphData.d(1), GridStepX = 10, GridStepY = 10, FontSize = 9, ColorGrid = $BBFFFFFF)
maxItems = ArraySize(GraphData()) ; количество пунктов (X)
Protected maxValues ; количество значений (Y)
Protected lowValue ; самые высокие и самые низкие значения GraphData
Protected t ; общая временная переменная
If maxItems < 0 : ProcedureReturn : EndIf ; выйти, если массив GraphData недействителен
; минимум и максимум значений оси Х
lowValue = -60
highValue = 60
; сделать вещи, чтобы лучше подогнать фоновую сетку
If GridStepY > 0
If highValue >= 0
highValue + GridStepY - highValue % GridStepY
ElseIf highValue
highValue - highValue % GridStepY
EndIf
If lowValue > 0
lowValue - lowValue % GridStepY
ElseIf lowValue < 0
lowValue - (GridStepY + lowValue % GridStepY)
EndIf
EndIf
maxValues = highValue - lowValue
If maxValues <= 0
maxValues = 1
EndIf
; загрузить шрифт для текстовых меток
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(highValue)) > VectorTextWidth(Str(lowValue)) ; задаём ширину текста
oX = VectorTextWidth(Str(highValue)) + 2.0
Else
oX = VectorTextWidth(Str(lowValue)) + 2.0
EndIf
oY = VectorTextHeight("0A") + 2.0
If oX > oY
oY = oX
Else
oX = oY
EndIf
mtW = VectorTextWidth(Str(maxItems)) * 1.2
mtH = VectorTextHeight(Str(highValue)) * 0.8
EndIf
; множители для масштабирования координат графика
mX = (VectorOutputWidth() - oX * 2.0) / (maxItems + Bool(maxItems = 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(highValue - t))), cY - VectorTextHeight(Str(highValue - t)) / 2)
DrawVectorText(Str(highValue - t))
tLast = cY - mtH
EndIf
; нарисовать линию сетки
MovePathCursor(oX, oY + mY * t)
AddPathLine(oX + maxItems * mX, oY + mY * t)
EndIf
Next t
EndIf
; вертикальные линии / метки
tLast = 0.0
If GridStepX > 0
;GridStepX + 1
For t = 0 To maxItems
If t % GridStepX = 0 Or t = maxItems
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 t
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
; Color цвет линии графика (RGB)
; LineWidth ширина линии (в пикселях)
; Plot_Dot показывать ли точки на графике
Procedure DrawGraph(hImgOut, Array GraphData.d(1), Color = $00DDDD, LineWidth.d = 1, Plot_Dot = 0)
Protected t ; общая временная переменная
; временные переменные, используемые при рисовании
Protected.d cX, cY
If StartVectorDrawing(ImageVectorOutput(hImgOut, #PB_Unit_Pixel))
; [1] - нарисуйте основную линию / элементы и сформируйте "геоданные"
VectorSourceColor(Color | $FF000000) ; цвет линии (с добавлением альфа-канала)
MovePathCursor(cX0, cY0 + mY * (highValue - GraphData(0)))
For t = 0 To maxItems
cX = cX0 + mX * t
cY = cY0 + mY * (highValue - GraphData(t))
AddPathLine(cX, cY) ; добавить линию
If Plot_Dot
AddPathCircle(cX, cY, 2.0) ; добавить точку
EndIf
MovePathCursor(cX, cY) ; восстановить позицию курсора
Next
; DotPath(4, 10, #PB_Path_RoundEnd)
StrokePath(LineWidth)
; очистить
StopVectorDrawing()
EndIf
EndProcedure
;}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Тест / пример
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; используется для обработки кликов мыши по графику
; mapkey - координата X изображения графика, value - соответствующий индекс в массиве GraphData()
Global NewMap GraphGeodata()
; Размеры графика
Global W = 800, H = 600
; Изображение для рисования графика
Global tImg
; Окно и холст для отображения графика
Global tWindow, tCanvas
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; сгенерировать графические данные
Global.d Dim GraphValues (127) ; размер массива определяет число точек по оси Y
; создать изображение для получения вывода
tImg = CreateImage(#PB_Any, W, H, 32, $1B1B1B) ; цвет фона тут
DrawGrid(tImg, GraphValues(), 10, 10, 12)
; нарисовать график на созданном изображении
Define t
; рисуем синусоиду (выпрямленный ток)
Define j=45
For t = 0 To ArraySize(GraphValues())
GraphValues(t) =60 * Abs(Sin(Radian(j-90)))
j+5
Next t
DrawGraph(tImg, GraphValues(), $00B1CB, 1, 1)
; рисуем поверх косинусоиду
j=0
For t = 0 To ArraySize(GraphValues())
GraphValues(t) =60 * Cos(Radian(j-90))
j+5
Next t
DrawGraph(tImg, GraphValues(), $80A800, 1)
; рисуем поверх синусоиду
j=0
For t = 0 To ArraySize(GraphValues())
GraphValues(t) = - 60 * Sin(Radian(j-90))
j+5
Next t
DrawGraph(tImg, GraphValues(), $9900FF, 1) ; $00A800
; рисуем экпоненту
For t = 0 To ArraySize(GraphValues())
; GraphValues(t) = t * 0.8 - 60 ; линия наклонная
GraphValues(t) = 60*Exp(- t / 24) ; экпонента
Next t
DrawGraph(tImg, GraphValues(), $2A04FF, 1)
; рисуем труеугольную
For t = 0 To ArraySize(GraphValues())
GraphValues(t) = 20 * (t/10 - 2 * Round((t/10 + 1) / 2, #PB_Round_Down)) * Pow(-1, Round((t/10 + 1) / 2, #PB_Round_Down)) - 40 ; Треугольный
Next t
DrawGraph(tImg, GraphValues(), $FF8C00, 1)
; показать окно с графиком
tWindow = OpenWindow(#PB_Any, 0, 0, W, H, "График", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
tCanvas = CanvasGadget(#PB_Any, 0, 0, W, H)
SetGadgetAttribute(tCanvas, #PB_Canvas_Image, ImageID(tImg))
; освободить изображение
FreeImage(tImg)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindowПоделиться628.08.2020 21:40:30
Продолжение улучшения.
Здесь линию можно задать началом и концом графика, то есть не перебирать в цикле для каждого значения. Аналогично создавая любой график, например синусоиду или экспоненту можно сделать с шагом Step 10 или другим, в зависимости от числа точек на волну, то есть снизить разрешение (при 40 точек на волну достаточно плавно) и даже сделать в виде ломаной кривой.
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)
tCanvas = CanvasGadget(#PB_Any, 0, 0, W, H)
SetGadgetAttribute(tCanvas, #PB_Canvas_Image, ImageID(tImg))
; освободить изображение
FreeImage(tImg)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindowОтредактировано AZJIO (28.08.2020 22:36:09)
