Страница 1 из 2
Визуализация численных данных
Добавлено: 08.08.2012 00:08:06
gooroong
Здравствуйте!
Помогите решить проблему. Есть телеметрия некой модели. Мне надо представить как изменяются параметры визуально (в виде графиков).
Данные хранятся в памяти в виде графа, но преобразовать я смогу его только в массив, т.к. слово "SQL" для меня ничего не значит, в TP6 его особо не было.
Визуализировать массив в лоб не выйдет - он 4-х мерный
На поверхности лежит решение - проекция n-мерного пространства на двумерное. Для этого я создаю два "ползунка" tTrackBar и предлагаю пользователю указать значения. После этого я могу сформировать массив (в минимальном случае [1..2, 1..n], но, лучше если я создам массив [1..4, 1..n])
Теперь надо этот массив нарисовать. В книге "Free Pascal и Lazarus Учебник по программированию" Алексеев, Чеснокова, Кучер достаточно подробно описана схема построения графика при помощи LineTo, что, в принципе, реально, но долго

. Думаю, что в Lazarus реализованы готовые схемы. Я нашел вкладку Chart и инструмент TChart.
Я не понял как работает эта штука и куда там "пихать" данные, кстати, там на вкладке есть еще много вариантов графиков, может быть среди них есть для трехмерных или n-мерных массивов, было бы прекрасно не изобретать велосипед.
Re: Визуализация численных данных
Добавлено: 08.08.2012 09:47:36
Oleg_D
В Лазарусе с TChart не работал, только в Дельфи. Предположим, что это одно и то же. Основными элементами TChart являются т.н. серии, то есть, графики. Графиков может быть сколько угодно, они создаются либо "вручную" через инспектор, либо в "ран-тайме", динамически. Доступ к графикам (сериям) осуществляется через список Series: Series[0], Series[1],... и т.д. Любой такой график можно создавать и уничтожать, очищать и добавлять к нему точки, скрывать и вновь показывать. Можно настраивать вид графика. Короче, гуглите TChart.
Для вашей задачи можно применить несколько графиков, изображая, таким образом, некоторую поверхность в трёхмерном пространстве, как это обычно принято в технической литературе. Графики создаем и заполняем динамически в соответствии с введёнными пользователем параметрами.
Re: Визуализация численных данных
Добавлено: 08.08.2012 10:43:58
gooroong
Огромное спасибо, но объясните мне тогда, есть ли в лазарусе то, что я нашел для дельфи
http://www.beluch.ru/progr/100comp/4_6_1.htm , и существует ли описание tChart для лазаруса на русском, а то все, что я нашел по запросу "tChart Lazarus" для Дельфи
Re: Визуализация численных данных
Добавлено: 08.08.2012 13:19:20
Oleg_D
Повторяю, что сам я в Лазарусе не работаю, но знающие люди тут на форуме утверждают, что дельфовые сведения годятся для лазаря. Так это, или нет? - придётся проверять на практике.
Re: Визуализация численных данных
Добавлено: 08.08.2012 18:05:54
Ask
TChart в Лазарусе немного похож, но не точно повторяет Дельфи.
Для визуализации двумерного массива есть два варианта -- ColorMap либо, если по одному измерению данных немного,
набор столбиков.
Визуализации типа surface на настоящий момент нет.
Документация по TAChart:
http://wiki.lazarus.freepascal.org/TAChart_documentationПошаговая инструкция для начинающих:
http://wiki.lazarus.freepascal.org/TAChart_tutorial:_Getting_startedДемонстрационные программы находятся каталоге components\tachart\demo
Re: Визуализация численных данных
Добавлено: 09.08.2012 14:30:47
gooroong
Так, кажется начал разбираться, но все же попрошу помощи, что бы не пыхтеть с английским.
у меня на форме есть чекбоксы (пока их мало - всего 12) в данный момент реакция на изменение одного из них выглядит вот так
Код: Выделить всё
procedure TBG.CBS1BeltChange(Sender: TObject);
begin
if CBS1BeltChange.Checked then begin
{создаем слой на BGChart с именем BGChartSim1Belt}
end else begin
{удаляем слой на BGChart с именем BGChartSim1Belt}
end;
end;
очень хочется что бы комментарии были перед кодом, который бы исполнял вышеописанное

спасибо!
в частности я уже сделал процедуру, которая наполняет некий массив данных [1..2,1..n] из структуры
(мне друг на все это сказал вот так "М-да, вот он, настоящий ОлдСкул!")
Код: Выделить всё
sigma----t3-----t2----Data--Simulation1...3
| | |
| | t2--- Data--Simulation1..3
| | |
| | .....
| |
| t3-----t2----Data--Simulation1...3
| | |
| | t2--- Data--Simulation1..3
| | |
| | .....
| ....
|
Sigma---...
|
...
Добавлено спустя 1 час 19 минут 30 секунд:вот, курица слепая, такую вещь не найти
http://www.freepascal.ru/forum/viewtopic.php?f=5&t=2923
Re: Визуализация численных данных
Добавлено: 09.08.2012 14:55:54
Ask
gooroong писал(а):у меня на форме есть чекбоксы ... в данный момент реакция на изменение одного из них выглядит вот так
...создаем слой на BGChart с именем BGChartSim1Belt...
...удаляем слой на BGChart с именем BGChartSim1Belt...
См. демку "basic". Вообще если есть трудности с пониманием документации, рекомендую посмотреть на демки --
их довольно много, и большинство фич в них показаны.
В то же время, если количество серий известно заранее, Я бы их не создавал динамически, а создал бы заранее
и просто делал Active := true/false.
в частности я уже сделал процедуру, которая наполняет некий массив данных [1..2,1..n]
Я честно говоря не до конца понял, почему всего лишь 1..2?
Если размерность так мала, то не надо никакого 3d, достаточно просто двух серий.
В принципе там всё правильно, но это *очень* старый тред, с тех пор код TAChart был полностью переписан.
Возможно, есть мелкие несовместимости -- рекомендую всё-таки посмотреть на демки.
Re: Визуализация численных данных
Добавлено: 09.08.2012 18:42:13
gooroong
господа, в чем ошибка?
Код: Выделить всё
TBG = class(TForm)
BGChartS1Belt2: TLineSeries;
BGChartS2Umdl4: TLineSeries;
итд...
Код: Выделить всё
tmpArray:=GetArray(i,1,5); {array[1..2] of double;}
BGChartS1Belt1.AddXY(tmpArray[1],tmpArray[2]);
при трассировке возникает ошибка "проект вызвал класс исключения 'external: SIGSEGV'" при запуске exe-шника говорит, что "произошло corruption"
в массиве значения "нормальные" т.к. побовал вот так
Re: Визуализация численных данных
Добавлено: 09.08.2012 19:02:58
Pavia
Код: Выделить всё
tmpArray:=GetArray(i,1,5); {array[1..2] of double;}
BGChartS1Belt1.AddXY(tmpArray[1],tmpArray[2]);
Где объявление tmpArray?
Где функция GetArray?
Где создание BGChartS1Belt1?
Где создание tmpArray?
Re: Визуализация численных данных
Добавлено: 09.08.2012 21:10:41
gooroong
там модуль на 800 строк, ладно, терпите

вначале покажу заголовок с определением типов
Код: Выделить всё
unit buildgraphics;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ComCtrls, TAGraph, TASeries, gsc, types, TACustomSeries;
type
{ TBG }
TPointArray=array[1..2] of double;
TBG = class(TForm)
BGChartS1Belt2: TLineSeries;
BGChartS2Umdl4: TLineSeries;
BGChartS2Y2: TLineSeries;
BGChartS2Y3: TLineSeries;
BGChartS2Y4: TLineSeries;
BGChartS2Z2: TLineSeries;
BGChartS2Z3: TLineSeries;
BGChartS2Z4: TLineSeries;
BGChartS3Belt2: TLineSeries;
BGChartS3Umdl2: TLineSeries;
BGChartS3Y2: TLineSeries;
BGChartS1Umdl2: TLineSeries;
BGChartS3Z2: TLineSeries;
BGChartS1Y2: TLineSeries;
BGChartS1Z2: TLineSeries;
BGChartS2Belt2: TLineSeries;
BGChartS2Belt3: TLineSeries;
BGChartS2Belt4: TLineSeries;
BGChartS2Umdl2: TLineSeries;
BGChartS2Umdl3: TLineSeries;
BGChartS1Umdl1: TLineSeries;
BGChartS3Y1: TLineSeries;
BGChartS3Z1: TLineSeries;
BGChartS1Y1: TLineSeries;
BGChartS1Z1: TLineSeries;
BGChartS2Belt1: TLineSeries;
BGChartS2Umdl1: TLineSeries;
BGChartS2Y1: TLineSeries;
BGChartS2Z1: TLineSeries;
BGChartS3Belt1: TLineSeries;
BGChartS3Umdl1: TLineSeries;
BGChartS1Belt1: TLineSeries;
BGLabelSigmaValue: TLabel;
CBOne: TCheckBox;
CBS2Belt: TCheckBox;
CBS3Belt: TCheckBox;
CBS1Umdl: TCheckBox;
CBS2Umdl: TCheckBox;
CBS3Umdl: TCheckBox;
CBS1Y: TCheckBox;
CBS2Y: TCheckBox;
CBS3Y: TCheckBox;
CBS1Z: TCheckBox;
CBS2Z: TCheckBox;
CBS3Z: TCheckBox;
CBSim1: TCheckBox;
CBSim2: TCheckBox;
CBSim3: TCheckBox;
CBS1Belt: TCheckBox;
BGChart: TChart;
Label1: TLabel;
Label2: TLabel;
BGLabelSigma: TLabel;
Label4: TLabel;
Labelt2_t3: TLabel;
BGLabelTValue: TLabel;
stopT2: TRadioButton;
stopT3: TRadioButton;
BSTrackSigma: TTrackBar;
BSTrack_t: TTrackBar;
procedure BGChartS1Belt1DrawPointer(ASender: TChartSeries;
ACanvas: TCanvas; AIndex: Integer; ACenter: TPoint);
procedure CBS1BeltChange(Sender: TObject);
procedure CBS1UmdlChange(Sender: TObject);
procedure CBS1YChange(Sender: TObject);
procedure CBS1ZChange(Sender: TObject);
procedure CBS2BeltChange(Sender: TObject);
procedure CBS2UmdlChange(Sender: TObject);
procedure CBS2YChange(Sender: TObject);
procedure CBS2ZChange(Sender: TObject);
procedure CBS3BeltChange(Sender: TObject);
procedure CBS3UmdlChange(Sender: TObject);
procedure CBS3YChange(Sender: TObject);
procedure CBS3ZChange(Sender: TObject);
function GetArray(Step, key1, key2: integer): TPointArray;
procedure BSTrackSigmaChange(Sender: TObject);
procedure BSTrack_tChange(Sender: TObject);
procedure CBSim1Change(Sender: TObject);
procedure CBSim2Change(Sender: TObject);
procedure CBSim3Change(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure Label2Click(Sender: TObject);
procedure stopT2Change(Sender: TObject);
procedure stopT3Change(Sender: TObject);
procedure RedrawIntervals(redraw_all:integer);
procedure MakeGraph;
private
{ private declarations }
public
{ public declarations }
end;
var
BG: TBG;
BGHeadStructure,
BGSigma:TSigma;
BGt2:Tt2;
BGt3:Tt3;
BGA:TData;
BGSim1,
BGSim2,
BGSim3:TSim;
BGInterval_t2,
BGInterval_t3,
BGInterval_Sigma: integer;
BGSigmaStep,
BGt3Step,
BGt2Step: real;
PointArray: TPointArray;
SeriesCounter: integer;
implementation
{$R *.lfm}
Код: Выделить всё
{тут надо отследить, какие флажи поставлены и создать массивы
я не вижу варианто отличных от "если - то"}
procedure TBG.MakeGraph;
var
i: integer;
tmpArray: TPointArray;
begin
BGSigma:=BGHeadStructure;
while BGSigma^.Counter<>BSTrackSigma.Position do BGSigma:=BGSigma^.Up;
BGt3:=BGSigma^.Link;
for i:=1 to BSTrack_t.Max do begin
{общее правило выглядит так: если стоит галочка на поле и
включена галочка "искать только одно решение" то
сохраняем 5й вариант, иначе в цикле выводим все варианты}
if CBS1Belt.Checked then begin
if CBOne.Checked then begin
tmpArray:=GetArray(i,1,5);
BGChartS1Belt1.AddXY(tmpArray[1],tmpArray[2]);
end else begin
tmpArray:=GetArray(i,1,1);
BGChartS1Belt1.AddXY(3,3); {тут я как бы говорю, что этой процедуре пофиг на то, что ей кормят - будет ошибка}
tmpArray:=GetArray(i,1,2);
BGChartS1Belt2.AddXY(tmpArray[1],tmpArray[2]);
end;
end;
тут достаточно однообразно
BGt3:=BGt3^.Up;
end;
end;
Код: Выделить всё
{щписание ключа 1
симуляция 1
1 - бельта
2 - U среднее
3 - Y
4 - Z-Y
симуляция 2
11 - бельта
12 - U среднее
13 - Y
14 - Z-Y
симуляция 3
21 - бельта
22 - U среднее
23 - Y
24 - Z-Y
ключ 2 отвечает за выбор "варианта" каждого из значений
а как это работает
нам нужно пробежаться по гафу и собрать значения в массив
для этого мы определяем какоевремя закреплено и у нас есть два пути
1 простой нам надо прийти по указанной ветке сигма - т3 - т2 и
перемещаясь по т2 собрать все нужные знчения
2 не просто мы идем на ветку т3, переходим на т2,
далее по ветке спускаемся до закрепленного значения и собираем его
затем спускаемся на следующее т3}
function TBG.GetArray(Step, key1, key2: integer): TPointArray;
begin
if stopT3.Checked then begin
while BGt3^.Counter<>BSTrack_t.Position do BGt3:=BGt3^.Up;
BGt2:=BGt3^.Link;
while BGt2^.Counter<>Step do BGt2:=BGt2^.Up;
PointArray[1]:=BGt2^.Value;
BGA:=BGt2^.Link;
BGSim1:=BGA^.Sim1;
BGSim2:=BGA^.Sim2;
BGSim3:=BGA^.Sim3;
case key1 of
1 : PointArray[2]:=BGSim1^.Belt[Key2];
2 : PointArray[2]:=BGSim1^.Umdl[Key2];
3 : PointArray[2]:=BGSim1^.Y_i[Key2];
4 : PointArray[2]:=BGSim1^.Z_y[Key2];
11 : PointArray[2]:=BGSim2^.Belt[Key2];
12 : PointArray[2]:=BGSim2^.Umdl[Key2];
13 : PointArray[2]:=BGSim2^.Y_i[Key2];
14 : PointArray[2]:=BGSim2^.Z_y[Key2];
21 : PointArray[2]:=BGSim3^.Belt[Key2];
22 : PointArray[2]:=BGSim3^.Umdl[Key2];
23 : PointArray[2]:=BGSim3^.Y_i[Key2];
24 : PointArray[2]:=BGSim3^.Z_y[Key2];
end;
end else begin
while BGt3^.Counter<>Step do BGt3:=BGt3^.Up;
PointArray[1]:=BGt3^.Value;
BGt2:=BGt3^.Link;
while BGt2^.Counter<>BSTrack_t.Position do BGt2:=BGt2^.Up;
BGA:=BGt2^.Link;
BGSim1:=BGA^.Sim1;
BGSim2:=BGA^.Sim2;
BGSim3:=BGA^.Sim3;
case key1 of
1 : PointArray[2]:=BGSim1^.Belt[Key2];
2 : PointArray[2]:=BGSim1^.Umdl[Key2];
3 : PointArray[2]:=BGSim1^.Y_i[Key2];
4 : PointArray[2]:=BGSim1^.Z_y[Key2];
11 : PointArray[2]:=BGSim2^.Belt[Key2];
12 : PointArray[2]:=BGSim2^.Umdl[Key2];
13 : PointArray[2]:=BGSim2^.Y_i[Key2];
14 : PointArray[2]:=BGSim2^.Z_y[Key2];
21 : PointArray[2]:=BGSim3^.Belt[Key2];
22 : PointArray[2]:=BGSim3^.Umdl[Key2];
23 : PointArray[2]:=BGSim3^.Y_i[Key2];
24 : PointArray[2]:=BGSim3^.Z_y[Key2];
end;
end;
end;
Создание BGChartS1Belt1 я создал искусственно нажав на TChar, затем в окне edit series в поле на "+"
Возможно я что то не доделал?
Cоздание tmpArray в первом фрагменте представленного кода.
Re: Визуализация численных данных
Добавлено: 10.08.2012 20:08:19
Pavia
Очевидных ошибок не видно.
А в какой строчке вылетает не ясно так?
Где-то указатель убежал и повредил данные, повреждённые данные после вызывают сбой в самом не предсказуемом месте и времени.
Тогда дедовский способ комментируем определённые участки программа и проверяем где появляется ошибка.
Хотя тут лучше включить обнаружения выхода указателя за диапазон отведённой памяти.Range Check. И в менеджере памяти включить отладочный режим.
http://www.gunsmoker.ru/2009/05/blog-post_24.htmlЛучше вот по этой ссылке
http://www.gunsmoker.ru/2009/05/access-violation.htmlПравда в вашем случае у меня есть сомнения что эти утилиты помогут. А вот дедовский метод точно.
Re: Визуализация численных данных
Добавлено: 10.08.2012 23:07:34
gooroong
я уже писал, что ошибка происходит при исполнении вот этой строки, т.е. никаких выходов за пределы ссылок быть не может
я ставил прерывание и проводил трассировку
Re: Визуализация численных данных
Добавлено: 11.08.2012 10:24:55
Pavia
Здесь вылетать нечему. Разве только у вас BGChartS1Belt1=nil.
Значит это одно Вы где-то напортачили с указателями они попортили чужие данные. Ошибка прожила ещё какое-то время пока не наткнулась на вашу строчку.
Это трудно обнаруживаемая ошибка, так как проявляется не сразу.
Re: Визуализация численных данных
Добавлено: 11.08.2012 10:46:08
Ask
Лучше всего в таких случаях постить не куски кода, а полный проект, желательно урезанный до минимального,
на котором ошибка ещё проявляется.
Это существенно сэкономит время людей, пытающихся помочь -- отладка с полным проектом может занять 5 минут,
а так гадать можно неделями.
Re: Визуализация численных данных
Добавлено: 11.08.2012 16:07:16
gooroong
Господа, прошу прощения у меня в процедуре инициализации моLуля был сюрприз, который я сам себе подложил, т.к. вначале собирался создавать серии динамически, и поставил такую вот процедуры xxx.series.clean вот такой я молодец!
Ладно. попробую дальше колупаться, во всяком случае ошибка не вылетает, но пока не рисует

ДВА ДНЯ ЕЖЕДНЕВНОЙ ТРАССИРОВКИ
Добавлено спустя 2 часа 30 минут 36 секунд:Господа, практически финальный рывок!
Все рисуется, не скажу, что красиво, но верно
Вопрос: возможно ли что бы был не единый масштаб, а для каждой серии свой? Цифры выводить не надо