Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Отрисовка графики за N сек. 
V
    Опции темы
Invisible_kid
Дата 6.4.2008, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 2.9.2007

Репутация: нет
Всего: 3



вобщем, на форме происходит куча разных прорисовок....ммммм.... есть 2-е ф-и:
 1-я) расчитывает и заносит в массив параметры линий; (координаты, цвет, толщину) 
 2-я) рисует это все 
функции вызываются таймером , но за установленный в нем интервал времени все не успевает отрисоваться т.к. линий много) (кст. рисую с помащью Canvas) , и заметно тормазит (на слабых машинах),выполняя каждую прорисовку, а мне необходимо  чтобы  на любой машине положение рисуемой "картинки"  после одного и тогоже интервала времени было одинаково. [допустимо не плавное изменение положения картинки]
Думаю привязаться к системному времени, но не знаю как)))))

PM MAIL   Вверх
korian
Дата 6.4.2008, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Код

обработчик таймера:
{
    KillTimer(...);
    static time_t lastDrawTime = time(NULL);
    double elapsed_time = difftime(time(NULL), lastDrawTime);

     Calculate(elapsed_time);
     DoDraw(elapsed_time);

     time(&lastDrawTime);
     SetTimer(...);
}

и рисовать лучше сначала в памяти, а потом уже выводить на форму, так будет быстрее...

Это сообщение отредактировал(а) korian - 6.4.2008, 18:03
PM   Вверх
Invisible_kid
Дата 6.4.2008, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 2.9.2007

Репутация: нет
Всего: 3



..я-то сначало в памяти и рисую, иначе бы вобще жестоко сматрелось )))
а KillTimer.... или я чето не правильно понял, но его наверно трогать не  стоит, т.к. таймер вызывает ф-ю расчетов параметров, а ряд параметров зависит от предыдущих, т.е. нужно както сделать чтобы прорисовка переодически отключалась, если не успевает, только вот как расчитать время которое она не должна работать...?
PM MAIL   Вверх
korian
Дата 6.4.2008, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



насколько я знаю, таймер работает постоянно.
т.е. в данном случае, винда постоянно постит сообщение WM_TIMER для потока каждую секунду.
когда сам обработчик таймера требует 2 секунды для работы, то в поток пришло еще 2 сообщения WM_TIMER
которые будут обрабатываться сразу после того, как первый обработчик закончит работу.
в результате через некоторое время получаем, что нам только и надо что заниматься обработкой сообщения WM_TIMER.
чтобы этого не было, надо отключать таймер при входе в обработчик таймера. и включать его назад, когда выходим из обработчика.
тогда мы будем пропускать те выводы, которые не успеваем нарисовать.
а перерисовка будет происходить каждые (1+ (время необходимое для расчетов и вывода)) секунд.
у юзера будет 1 секунда между рассчетами, на то чтобы повлиять на программу.
а вообще, лучше конечено, такие расчеты с прорисовкой в отдельный поток, чтобы юзер всегда мог влиять на ход работы программы.

для борланда KillTimer и SetTimer надо заменить на соответсвующие Timer1->Enabled = false и Timer1->Enabled = true
elapsed_time в том коде - это сколько секунд прошло с последней прорисовки.


Это сообщение отредактировал(а) korian - 6.4.2008, 23:16
PM   Вверх
Lazin
Дата 7.4.2008, 08:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 18
Всего: 154



Цитата(korian @  6.4.2008,  17:57 Найти цитируемый пост)
рисовать лучше сначала в памяти, а потом уже выводить на форму, так будет быстрее...

ты не прав  smile 
Invisible_kid, обрабатывай событие OnIdle, и в нем рисуй. Если нужно отрисовывать много линий, то можно сделать следующие оптимизации:
  • Отсечение невидимых линий, те которые не видно полностью - не рисуешь.
  • Отрисовка только в случае изменений.
  • Можно еще все нарисовать на вне-экранном буфере, затем просто копировать видимую часть на экран (недостатки - если изменится масштаб нужно заново все перерисовывать, к тому-же при большом масштабе будет кушать много памяти)
  • Есть еще фишка с xor, если нарисовать линию белым цветом на белом фоне методом xor - она будет черной, если потом нарисовать ее по тем-же координатам еще раз она исчезнет (даже если фон не однотонный), так-вот все то, что не меняется рисуешь один раз. Ту линию, которая в данный момент меняется рисуешь методом xor, потом, когда надо перерисовать, а у тебя изменилась только эта линия - стираешь ее, потом рисуешь в другом месте.

PM MAIL Skype GTalk   Вверх
Invisible_kid
Дата 7.4.2008, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 2.9.2007

Репутация: нет
Всего: 3



...ммммм.... ну линии каторих не видно я и так не рисую, а изменяются все т.к. происходит их постоянное  "затухание" (потому и хоr не нужен, т.к. рисую более бледные линии поверх старых, а те которые па цвету совпадают с цветом фона отбрасываю ), 
а что касается самой отрисовки, то ДаблБуфер использую, а сама отрисовка происходит на Graphics::TBitmap *Image;   а патом делаю так ImDraw->Canvas->Draw(0,0,Image); ....не успевает, т.к. каличество линий большое....

..вобщем, пайду разбираться с КиллТаймером и OnIdle-м.... если будут вапросы вернусь),
 ну а пока, спасибо за советы)
 
PM MAIL   Вверх
korian
Дата 7.4.2008, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Цитата(Lazin @  7.4.2008,  07:09 Найти цитируемый пост)
ты не прав  

Цитата(Lazin @  7.4.2008,  07:09 Найти цитируемый пост)
Можно еще все нарисовать на вне-экранном буфере

я только одного не понял. Сначала вы пишите что я не прав, а потом советуете тоже самое?
или есть какой-то другой смысл словосочетания "нарисовать в памяти"?

Это сообщение отредактировал(а) korian - 7.4.2008, 12:08
PM   Вверх
Lazin
Дата 7.4.2008, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 18
Всего: 154



Цитата(korian @  6.4.2008,  17:57 Найти цитируемый пост)
и рисовать лучше сначала в памяти, а потом уже выводить на форму, так будет быстрее...

я подумал что ты имеешь ввиду double bufering
я предлагал несколько иное =)
PM MAIL Skype GTalk   Вверх
korian
Дата 7.4.2008, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Цитата(Lazin @  7.4.2008,  07:09 Найти цитируемый пост)
затем просто копировать видимую часть на экран 

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

Это сообщение отредактировал(а) korian - 7.4.2008, 12:36
PM   Вверх
Lazin
Дата 7.4.2008, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 18
Всего: 154



многие VCL компоненты реализуют двойную буферизацию
если он использует Image, то он и так в памяти рисует =)

Цитата(korian @  7.4.2008,  12:33 Найти цитируемый пост)
рисуя на экране уже подготовленный битмап мы рисуем n*m точек.
а так, сначало надо нарисовать n*m точек, чтобы очистить экран, потом еще куча точек, которые надо отобразить.

а буфер очищать не надо? или ты предлагаешь каждый раз создавать рисовать а потом удалять?
допустим, в обоих случаях ты начинаешь с того, что заливаешь битмап одним цветом, затем рисуешь линии, а во втором случае еще и копируешь в битмап компонента, а компонент потом копирует свой битмап на экран.

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


PM MAIL Skype GTalk   Вверх
korian
Дата 7.4.2008, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Цитата(Lazin @  7.4.2008,  12:26 Найти цитируемый пост)
если он использует Image, то он и так в памяти рисует =)

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

Это сообщение отредактировал(а) korian - 7.4.2008, 13:43
PM   Вверх
Invisible_kid
Дата 9.4.2008, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 2.9.2007

Репутация: нет
Всего: 3



вроде научился пользоваться OnIdle-м) помогло)))
а вот с килтаймером, вроде идею понял [возможно еще пригодится, когда-нибудь)] но сделать пока не получилось(

Спасибо за помощь!
 вопрос решен)
PM MAIL   Вверх
SerK
Дата 9.4.2008, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 31.3.2007

Репутация: нет
Всего: нет



Invisible_kid, если не затруднит, дайте пример, как работать с OnIdle.


--------------------
Пусть будет миру хорошо!
PM MAIL   Вверх
Invisible_kid
Дата 10.4.2008, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 2.9.2007

Репутация: нет
Всего: 3



SerK, в самом хелпе билдера есть па-моему вполне панятный пример... я по нему и разбирался. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0622 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.