Помощь - Поиск - Пользователи - Календарь
Полная версия: Быстрое рисование графиков в TChart
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
Neon6868
Проблема в следующем:

С АЦП с большой скоростью поступают числовые значения. Необходимо выводить все эти значения на график. Пробовал использовать компонент TChart, но рисование выполняется очень медленно(использовал метод LineTo), вследствие чего переполняется буфер со значениями АЦП и программа закрывается. Возможно ли использовать для таких целей TChart?

Также пробовал использовать канву, график вроде как успевает рисоваться. Но возникает проблема с прокруткой изображения. Я помещал PaintBox на ScrollBox. Если изменять свойство Position у ScrollBox'a при выводе каждой точки, то график опять начинает рисоваться очень медленно.

Подскажите возможно ли мне использовать TChart? Если все же придется использовать канву, то как сделать автоматическую прокрутку изображения при рисовании графика?
volvo
Во-первых, показывай как пробовал рисовать (LineTo у TChart-а отродясь не было, ты что-то путаешь). И во-вторых - оцени примерно, с какой скоростью поступает информация (и в каком виде, кстати) с АЦП. Каков размер буфера?

Если данные будут продолжать поступать очень быстро - отрисовка все равно не справится, буфер будет переполняться. Другое дело - если в работе АЦП есть перерывы, когда данные либо прекращают поступать совсем, либо поступают с меньшей скоростью.

Если таких пауз не предусматривается - то, похоже, единственное решение - это писать данные с АЦП напрямую в БД, а уж из БД - отрисовывать. Но тогда возможно запаздывание, если рисовать все подряд. Можно еще поизвращаться и сделать вот так, например: пока буфер относительно пуст - рисовать все, что в него поступает. Как только он начинает переполняться - рисовать только каждое второе значение, а первое - просто отбрасывать. Опять быстро заполняется - отбрасывай 2 и рисуй каждое третье (если такая высокая скорость поступления данных - это не должно сказаться на качестве графика). В общем, "нужно больше информации", как говорил герой "Короткого замыкания" smile.gif

А, да. Вот еще что уточни: что ты подразумеваешь под "прокруткой"? То есть, ты в любое время должен иметь возможность прокручивать сколь угодно далеко назад и смотреть график, или имеется в виду, что как только отображение достигло границ формы, оно должно начать сдвигаться налево, и справа добавлять новые значения (а пользователь при этом не имеет возможность просмотреть, что было пару экранов назад)?
TarasB
Рисуй линиями на канве.
А ещё быстрее будет заранее взять DC := Canvas.Handle и использовать фукнции над этим DC (Windows.MoveToEx, Windows.LineTo), потому что канва, как и весь VCL - это страшный пахлава-код.
И делай сдвиг не при каждом новом поступлении данных, а только каждую секунду, например. Потому что копирование изображения - это операция дорогая, и тут уже дело в скорости памяти.
Neon6868
volvo
Насчет LineTo перепутал. Метод LineTo использовал конечно же при рисовании на канве. Для рисования на TChart просто добавлял новые значения к серии ( примерно так - Chart1.Series1.AddXY(x,y); ). Данные с АЦП идут со скоростью 10МГц, но большая их часть отбрасывается(сложно определить сколько) и те значения, которые остаются, необходимо вывести на график. Данные представляются собой целые значения от 0 до 7000.
Данные с АЦП поступают непрерывно с постоянной скоростью. Выводить на график требуется обязательно все значения. Прокрутка нужна такая: "как только отображение достигло границ формы, оно должно начать сдвигаться налево".

Я стал рисовать на канве. Все точки успевают выводиться. Но есть проблема. Выводится часть точек и затем точки начинают выводиться не на канве, а в произвольном месте формы (началом координат становится левый верхний угол экрана). Заметил, что начинается это часто после движения мышки или перемещения формы. Из-за чего такое может быть?
Также я решил отказаться от прокрутки.Как только отображение доходит до правого края канвы, содержимое канвы очищается и вывод продолжается с левого края.
TarasBer
> Выводится часть точек и затем точки начинают выводиться не на канве, а в произвольном месте формы (началом координат становится левый верхний угол экрана). Заметил, что начинается это часто после движения мышки или перемещения формы. Из-за чего такое может быть?

А картинку можно? Никогда такого не видел, то есть видел, но не с канвасом.
Neon6868
Цитата(TarasBer @ 25.01.2011 19:16) *

> Выводится часть точек и затем точки начинают выводиться не на канве, а в произвольном месте формы (началом координат становится левый верхний угол экрана). Заметил, что начинается это часто после движения мышки или перемещения формы. Из-за чего такое может быть?

А картинку можно? Никогда такого не видел, то есть видел, но не с канвасом.


Ок, завтра на работе скрин сделаю.
volvo
Цитата
Я стал рисовать на канве. Все точки успевают выводиться. Но есть проблема. Выводится часть точек и затем точки начинают выводиться не на канве, а в произвольном месте формы (началом координат становится левый верхний угол экрана). Заметил, что начинается это часто после движения мышки или перемещения формы. Из-за чего такое может быть?
Также я решил отказаться от прокрутки.Как только отображение доходит до правого края канвы, содержимое канвы очищается и вывод продолжается с левого края.
Не знаю уж, как ты рисовал на канве, что у тебя программа так себя ведет.

Я бы и от прокрутки не отказывался. Положил я на форму 2 кнопки (btnStart + btnStop) и PaintBox, и сделал так:

const
MaxValue = 7000;
Fresh = 10;

Function GetValue() : Integer;
begin
result := Random(MaxValue);
end;

procedure TForm1.DrawIt;
var
CurrX, CurrY, PrevY : Integer;
SrcR, DstR, FillR: TRect;
begin
CurrX := 0;
PaintBox1.Canvas.Pen.Color := clRed;
PaintBox1.Canvas.Brush.Color := clBtnFace;

SrcR := Rect(Fresh, 0, PaintBox1.Width, PaintBox1.Height);
DstR := Rect(0, 0, PaintBox1.Width - Fresh, PaintBox1.Height);
FillR := Rect(PaintBox1.Width - Fresh, 0, PaintBox1.Width, PaintBox1.Height);

PaintBox1.Canvas.MoveTo(CurrX, PaintBox1.Height);
while Draw_Graph do
begin
if CurrX + Fresh >= PaintBox1.Width then
begin
PaintBox1.Canvas.CopyRect(DstR, PaintBox1.Canvas, SrcR);
PaintBox1.Canvas.FillRect(FillR);
PaintBox1.Canvas.MoveTo(CurrX - Fresh, PaintBox1.Height - PrevY);
end
else
begin
Inc(CurrX, Fresh);
end;
CurrY := GetValue() * PaintBox1.Height div MaxValue;
PaintBox1.Canvas.LineTo(CurrX, PaintBox1.Height - CurrY);
PrevY := CurrY;

Sleep(100); // Для теста, тестировалось вплоть до Sleep(1)
Application.ProcessMessages; // Чтоб нажатие на btnStop отловить, да и другие сообщения
end;
end;

procedure TForm1.btnStartClick(Sender: TObject);
begin
if not Draw_Graph then
begin
Randomize;
Draw_Graph := True;
DrawIt;
end;
end;

procedure TForm1.btnStopClick(Sender: TObject);
begin
Draw_Graph := False;
end;
, прокручивается, рисует график. Что я не так делаю?
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.