C++Builder
  Начало   Форум   Помощь Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Быстрая отрисовка 2D графика?  (Прочитано 2591 раз)
DimaKor
Участник


Сказали спасибо: +1/-0
Offline

Сообщений: 22


Быстрая отрисовка 2D графика?
« : 24 Март 2015, 16:30:35 »

Написал программу управления всяким лабораторным железом на LabWindows, в программе в частности таймер с шагом в 20 мс опрашивает АЦП и выводит точки на экран графиком. Поскольку LabWindows использует голый С, решил переписать на Rad Studio XE. Для начала решил проверить TChart на скорость, простенькая программа рисует 400 точек по таймеру с шагом 20. Вместо 8 секунд график рисуется 14 секунд (по часам)

Что это, TChart медленный, таймеру не дают срабатывать ровно через каждые 20 мс или еще что?

Содержательный кусок кода:

Код:
double x [400] = {};
double y [400] = {};
const double Pi = 3.14159;
int i = 0;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PlotBtnClick(TObject *Sender)
{
Series1->Clear();

i = 0;
Timer1->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
if( i {
        x[i] = i*Pi/200;
y[i] = sin(x[i]);

Series1->AddXY(x[i],y[i],"",clRed);
i++;
}
else
{
i = 0;
Timer1->Enabled = false;
}
}
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Быстрая отрисовка 2D графика?
« Ответ #1 : 24 Март 2015, 22:16:53 »

А если сразу по BottomAxis задать максимум сразу соответствующий 400-й точке?
Записан
DimaKor
Участник


Сказали спасибо: +1/-0
Offline

Сообщений: 22


Re: Быстрая отрисовка 2D графика?
« Ответ #2 : 25 Март 2015, 09:21:49 »

Это не помогает. Проверю таймер еще на всякий случай
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Быстрая отрисовка 2D графика?
« Ответ #3 : 25 Март 2015, 10:05:43 »

Чарт вообще не причём. Можешь AddXY убрать - будет те же 16 секунд.
Это таймер не гарантирует 20 мс.
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Быстрая отрисовка 2D графика?
« Ответ #4 : 25 Март 2015, 10:13:44 »

Вот так будет уже ближе к истине (код обработчика нажатия кнопки)
Код
        Series1->Clear();
dt_last = Now();
for (i = 0; i 400; i++)
{
// Ожидание 20 мс
while (MilliSecondSpan(Now(), dt_last) 20){};
dt_last = Now();
 
// расчет и отрисовка
x[i] = i*Pi/200;
y[i] = sin(x[i]);
Series1->AddXY(x[i],y[i],"",clRed);
Application->ProcessMessages();
}
 

Вот надо сделать поток, в нём расположить этот код.. ну модифицировать соответственно задаче и источнику появления данных.
Конечно обеспокоится потокобезопасностью данных (хотя бы на чарте отрисовывать через Synchronize). Собссно так точные таймера и строятся.
Да, внутри потока убрать Application->ProcessMessages()
« Последнее редактирование: 25 Март 2015, 10:19:58 от POV » Записан
DimaKor
Участник


Сказали спасибо: +1/-0
Offline

Сообщений: 22


Re: Быстрая отрисовка 2D графика?
« Ответ #5 : 25 Март 2015, 11:09:19 »

Да, это таймер. Даже если ничего не делать и выводить отсчет после 400 циклов по 20 мс, те же самые 14 секунд. В общем для работы в реальном времени он не годится

Попробую метод выше
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Быстрая отрисовка 2D графика?
« Ответ #6 : 25 Март 2015, 11:54:49 »

Точный таймер на потоке просто.. в его теле крутится
Код
while (MilliSecondSpan(Now(), dt_last)  20){};
dt_last = Now();
... тут вызов обработчика через Synchronize
 
и всех делов
Записан
DimaKor
Участник


Сказали спасибо: +1/-0
Offline

Сообщений: 22


Re: Быстрая отрисовка 2D графика?
« Ответ #7 : 27 Март 2015, 12:19:12 »

Торможу. Вместо того, чтобы добавлять по точке к графику каждые 20 мс, программа ждет 8 секунд, а потом выводит все 400 точек сразу.

Главная форма:

Код:
void __fastcall TThread_form::StartBtnClick(TObject *Sender)
{
Thr = new MyTime(false);
}

В потоке:

Код:
void __fastcall MyTime::Execute()
{
//---- Place thread code here ----
Synchronize(DrawTc);
}
//---------------------------------------------------------------------------
void __fastcall MyTime::DrawTc()
{
Thread_form->Series1->Clear();
TDateTime t = Now();

for (i = 0; i {
// Ожидание 20 мс
while (MilliSecondSpan(Now(), t) t = Now();

// расчет и отрисовка
x[i] = i*Pi/200;
y[i] = sin(x[i]);
Thread_form->Series1->AddXY(x[i],y[i],"",clRed);
}
}
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Быстрая отрисовка 2D графика?
« Ответ #8 : 27 Март 2015, 13:43:15 »

Ну, получилось ровно то, что ты запрограмировал )))
В потоке надо, как я выше показал, ждать наступления очередных 20 мс. После чего вызвать отрисовку ОДНОЙ очередной точки.
Записан
DimaKor
Участник


Сказали спасибо: +1/-0
Offline

Сообщений: 22


Re: Быстрая отрисовка 2D графика?
« Ответ #9 : 27 Март 2015, 13:47:22 »

Не очень понял. Но помогло добавление в конец рисующей функции

Application->ProcessMessages();

после чего стала рисовать как надо
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Быстрая отрисовка 2D графика?
« Ответ #10 : 27 Март 2015, 14:52:10 »

Погодь.. ты совсем не то сделал. Ты попросту в поток перенес код который исполняется непрерывно, сразу весь. Это ровно то же самое что безо всяких потоков сделать.
Изначально же ты задачу ставил на появление данных каждых 20 мс и соответствующую отрисовку. Вот и надо в потоке "дожидаться" данных (т.е. пауза на 20 мс), а затем перенос этой одной точки на график.

основном потоке имеется
Код
int i;
 
func()
{
// здесь на график выводится i-я точка
...
i++;
}

а в потоке каждые 20 мс

Код
Synchronize(func);
Записан
DimaKor
Участник


Сказали спасибо: +1/-0
Offline

Сообщений: 22


Re: Быстрая отрисовка 2D графика?
« Ответ #11 : 27 Март 2015, 15:50:38 »

То есть перенести весь цикл в Execute, а в функции оставить только таймер?

Код:
void __fastcall MyTime::Execute()
{
//---- Place thread code here ----
Thread_form->Series1->Clear();

for (i = 0; i {
x[i] = i*Pi/200;
y[i] = sin(x[i]);
Thread_form->Series1->AddXY(x[i],y[i],"",clRed);
Synchronize(DrawTc);
}
}
//---------------------------------------------------------------------------
void __fastcall MyTime::DrawTc()
{
TDateTime t = Now();
while (MilliSecondSpan(Now(), t) t = Now();
}

Есть какая-нибудь существенная разница с предыдущим вариантом?
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


« Ответ #12 : 27 Март 2015, 19:15:00 »

Код
t = Now();
while (MilliSecondSpan(Now(), t) 20){};
в потоке.

TDateTime t; - это не локальная переменная, а глобальная. Или лучше переменная класса потока.

Добавив к этим трем строчкам вызов какой-либо функции (обработчик таймера) посредством Synchronize; мы получаем самый настоящий таймер. Величину 20 также можно как переменную класса сделать чтобы интервал настраивать.

Код
void __fastcall MyTime::Execute()
{
t = Now();
while (!Terminated)
{
while (MilliSecondSpan(Now(), t) 20){};
t = Now();
Synchronize(func);
}
}
 


В главном потоке выводим эти точки
Код
func()
{
x[i] = i*Pi/200;
y[i] = sin(x[i]);
Series1->AddXY(x[i],y[i],"",clRed);
i++;
if (i >= 400)
Thread_form->Suspend(); // ну или как-то еще прекращаем набирать данные
}
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  




....

Powered by SMF 1.1.21 | SMF © 2025, Simple Machines
Страница сгенерирована за 0.067 секунд. Запросов: 19.