Существует ли аналог такого модуля. Я ранее использовал это в программе (скриншот), показалось это не сложно сделать. В некой области рисовать линии, рисовать сетку с заданными значениями, рисовать шкалу на осях.
Существует ли модуль создания графиков?
Сообщений 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)