Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.92/13: Рейтинг темы: голосов - 13, средняя оценка - 4.92
2 / 2 / 0
Регистрация: 11.07.2011
Сообщений: 4

TCanvas LineTo отрисовка графика

13.07.2011, 15:55. Показов 2767. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго всем времени суток! Не могу добиться быстрой отрисовки ( перерисовки) графика при
его зумировании, выполняемое в событии MouseMove при нажатой клавише Ctrl. (с++ builder 6)
Исходные данные - вектор структур в памяти (размер до 100к), считаю сколько экспериментальных точек приходится на 1 пиксель,
вычисляю мин и макс, делаю для каждого пикселя отрисовку :
LineTo(pix, min); LineTo(pix, max);
Подскажите пожалуста, может есть способ ускорить отрисовку или у меня ошибка где в алгоритме ?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.07.2011, 15:55
Ответы с готовыми решениями:

Отрисовка греческих букв на TCanvas
Надо отрисовать греческие буквы на канве шрифтом Times New Roman. При этом желательно уметь замерять ширину и высоту участка канвы, которую...

Графика, отрисовка диода
есть функция рисует на вертикальной линии диод void VD(pos q,String S,pos p) { if(q) { t->Pen->Width=1; ...

Некорректная отрисовка графика на канве
Где ошибка? Почему так плохо рисует график? //--------------------------------------------------------------------------- #include...

6
 Аватар для Питекантроп
251 / 145 / 21
Регистрация: 14.06.2010
Сообщений: 340
13.07.2011, 16:29
Выполняете ли вы пересчет значений при каждой перерисовке?
Сколько примерно точек получается?
1
2 / 2 / 0
Регистрация: 11.07.2011
Сообщений: 4
13.07.2011, 16:46  [ТС]
Да, при каждой перерисовке я вычисляю новые индексы вектора, от и до которых нужно вывести на экран, потом считаю сколько элементов вектора приходится на 1 пиксель (stepsPerPix), ищу
для таких "отрезков" Мин и Макс и провожу линию, потом для следующего пикселя и т.д.
Если зумировать с минимального масштаба, то stepsPerPix= 50-90

вот код функции:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
int drawZoom(int& i_begin, int& i_end, TImage* Image, vector<Line>& sourceTable,
                                          Line& glMaxY, Line& glMinY  )
{
         int imageWidth= Image->Width ;
         int imageHeight= Image->Height ;
         if(abs(i_begin-i_end)/imageWidth>2)  // отрисовка только Мин и Макс
         {
                  double stepsPerPix= (float)abs(i_begin-i_end)/imageWidth ;
                  double mainPart, leftPart; double* mainPName; mainPName= &mainPart;
                  leftPart= modf(stepsPerPix, mainPName) ;int ind1=0; int ind2=0;
                  Line maxYpoint, minYpoint ;
                  double dY= glMaxY.deriv-glMinY.deriv ;
              
              Image->Canvas->MoveTo(0,0) ;
              Image->Canvas->FillRect(Rect(0,0,imageWidth,imageHeight));
              
                  ind1=i_begin;
                  int y_win ;
                  for(int i=0; i<=imageWidth; i++)
                  {
                     if(!i)
                     {
                            y_win= imageHeight - (sourceTable[i_begin].deriv-
                                    glMinY.deriv)*imageHeight/dY ;
                                    Image->Canvas->MoveTo(i, y_win) ;
                      }
                     ind2=i_begin + stepsPerPix*i;
                      maxYpoint= *max_element(sourceTable.begin()+ind1, specTable.begin()+ind2, isMore) ;
                      minYpoint= *min_element(sourceTable.begin()+ind1, specTable.begin()+ind2, isMore) ;
                    y_win= imageHeight- (maxYpoint.deriv-
                                        glMinY.deriv)*imageHeight/dY ;
                     Image->Canvas->LineTo(i, y_win) ;
                    y_win= imageHeight- (minYpoint.deriv-
                                        glMinY.deriv)*imageHeight/dY ;
                     Image->Canvas->LineTo(i, y_win) ;
                     ind1=ind2 ;
 
                }
 
          }
          else {  // отрисовка в лоб всех точек
 
                  double pixNum ;
                  pixNum = (float)imageWidth/abs(i_begin-i_end) ;
                  double mainPart; double leftPart;
                  double* mainPName; mainPName= &mainPart ;
                  leftPart= modf(pixNum, mainPName);     //=============
                   int num=1;
                   int x_win, y_win ;
                   Image->Canvas->MoveTo(0,0) ;
                   Image->Canvas->FillRect(Rect(0,0,imageWidth,imageHeight));
                  for(int i=i_begin; i<=i_end; i++)
                 {
                      
                     if(i==i_begin)
                     {
                         y_win= imageHeight-
                         (sourceTable[i].deriv-glMinY.deriv)*imageHeight/(glMaxY.deriv-
                                                                     glMinY.deriv) ;
                         Image->Canvas->MoveTo(0, y_win) ;
 
                     }
 
                     y_win= imageHeight-
                    (sourceTable[i].deriv-glMinY.deriv)*imageHeight/(glMaxY.deriv-
                                                                     glMinY.deriv) ;
 
                      Image->Canvas->LineTo(x_win, y_win);
                      x_win= num*mainPart + num*leftPart ;
                       num++ ;
 
                 } // for
           }// else
 
   return 0;
}
0
 Аватар для Питекантроп
251 / 145 / 21
Регистрация: 14.06.2010
Сообщений: 340
13.07.2011, 17:11
Ian, вроде бы в коде все нормально.
Только зачем выполнять зумирование при каждом движение мыши? Это событие вызывается же довольно часто.
Может, вам нужно при прокрутке зумировать? Тогда событие MouseWheel.

И еще. Для ускорение создайте дополнительный TBitmap размером с Image, при рисовании рисуйте сначала на канве битмапа, а потом копируйте все в канву имейджа. Через Canvas->CopyRect. Иначе при рисовании прямо на визуальном компоненте могут лишний раз вызываться дополнительные методы, что замедляет дело.
1
2 / 2 / 0
Регистрация: 11.07.2011
Сообщений: 4
13.07.2011, 19:36  [ТС]
Спасибо большое, по движению мыши оно вроде как сподручнее, но если не устроит после битмапа скорость - буду делать прокруткой.

Добавлено через 2 часа 21 минуту
Все просто летает ! Надо было сразу потрудиться и поискать подробнее про TBitmap, а то искусился простотой TImage-а и потерял время ломая голову. Мораль...
Вот новая функция, может кому понадобится:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
int drawZoom(int& i_begin, int& i_end, TImage* Image, vector<Line>& sourceTable,
                                          Line& glMaxY, Line& glMinY,
                                          Graphics::TBitmap* Bitmap  )
{
         int imageWidth= Image->Width ;
         int imageHeight= Image->Height ;
         if(abs(i_begin-i_end)/imageWidth>2)  // отрисовка только Мин и Макс
         {
                  double stepsPerPix= (float)abs(i_begin-i_end)/imageWidth ;
                  double mainPart, leftPart; double* mainPName; mainPName= &mainPart;
                  leftPart= modf(stepsPerPix, mainPName) ;int ind1=0; int ind2=0;
                  Line maxYpoint, minYpoint ;
                  double dY= glMaxY.deriv-glMinY.deriv ;
              
              Bitmap->Canvas->MoveTo(0,0) ;
              Bitmap->Canvas->FillRect(Rect(0,0,imageWidth,imageHeight));
              
                  ind1=i_begin;
                  int y_win ;
                  for(int i=0; i<=imageWidth; i++)
                  {
                     if(!i)
                     {
                            y_win= imageHeight - (sourceTable[i_begin].deriv-
                                                             glMinY.deriv)*imageHeight/dY ;
                             Bitmap->Canvas->MoveTo(i, y_win) ;
                      }
                     ind2=i_begin + stepsPerPix*i;
                      maxYpoint= *max_element(sourceTable.begin()+ind1, 
                                                           sourceTable.begin()+ind2, isMore) ;
                      minYpoint= *min_element(sourceTable.begin()+ind1, 
                                                         sourceTable.begin()+ind2, isMore) ;
                    y_win= imageHeight- (maxYpoint.deriv-
                                        glMinY.deriv)*imageHeight/dY ;
                     Bitmap->Canvas->LineTo(i, y_win) ;
                    y_win= imageHeight- (minYpoint.deriv-
                                        glMinY.deriv)*imageHeight/dY ;
                     Bitmap->Canvas->LineTo(i, y_win) ;
                     ind1=ind2 ;
 
                }
         Image->Canvas->CopyRect(Rect(0,0,imageWidth,imageHeight), 
                                           Bitmap->Canvas, 
                Rect(0,0,Bitmap->Width, Bitmap->Height)) ;
          }
          else {  // отрисовка в лоб всех точек
 
                  double pixNum ;
                  pixNum = (float)imageWidth/abs(i_begin-i_end) ;
                  double mainPart; double leftPart;
                  double* mainPName; mainPName= &mainPart ;
                  leftPart= modf(pixNum, mainPName);     
                   int num=1;
                   int x_win, y_win ;
                   Bitmap->Canvas->MoveTo(0,0) ;
                   Bitmap->Canvas->FillRect(Rect(0,0,imageWidth,imageHeight));
                  for(int i=i_begin; i<=i_end; i++)
                 {
                      
                     if(i==i_begin)
                     {
                         y_win= imageHeight-
                              (sourceTable[i].deriv-glMinY.deriv)*imageHeight/(glMaxY.deriv-
                                                                     glMinY.deriv) ;
                         Bitmap->Canvas->MoveTo(0, y_win) ;
 
                     }
 
                     y_win= imageHeight-
                          (sourceTable[i].deriv-glMinY.deriv)*imageHeight/(glMaxY.deriv-
                                                                     glMinY.deriv) ;
 
                      Bitmap->Canvas->LineTo(x_win, y_win);
                      x_win= num*mainPart + num*leftPart ;
                       num++ ;
 
                 } // for
          Image->Canvas->CopyRect(Rect(0,0,imageWidth,imageHeight), 
                                           Bitmap->Canvas, 
                   Rect(0,0,Bitmap->Width, Bitmap->Height)) ;        
           }// else
 
   return 0;
}
1
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
13.07.2011, 21:29
Оно как бы да, но более "стандартным" все же принято считать масштабирование по MouseWheel , как советовал уважаемый Питекантроп, да и дополнительную кнопку клавиатуры задействовать при этом нужды нет.
1
2 / 2 / 0
Регистрация: 11.07.2011
Сообщений: 4
14.07.2011, 15:41  [ТС]
Спасибо за советы, попробую учесть.

Добавлено через 14 часов 59 минут
Прошу у всех прощения, но сегодня со свежей головы увидел недоделки в функции drawZoom(), и отрисовку лишней горизонтальной линии при масштабе "в лоб". Буду исправлять.

Добавлено через 1 час 40 минут
Проблема была в том, что прохлопал инициализацию x_win=0 перед циклом. И modf() тоже не нужно использовать. Повесил функцию на событие MouseWheel, действительно удобно, спасибо за совет =)

Вот переделанная функция:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
int drawZoom(int& i_begin, int& i_end, TImage* Image, vector<Line>& sourceTable,
                                          Line& glMaxY, Line& glMinY,
                                          Graphics::TBitmap* Bitmap  )
{
         int imageWidth= Image->Width ;
         int imageHeight= Image->Height ;
         if(abs(i_begin-i_end)/imageWidth>2)  // отрисовка только Мин и Макс
         {
                  double stepsPerPix= (float)abs(i_begin-i_end)/imageWidth ;
                  int ind1=0; int ind2=0;
                  Line maxYpoint, minYpoint ;
                  double dY= glMaxY.deriv-glMinY.deriv ;
              
              Bitmap->Canvas->MoveTo(0,0) ;
              Bitmap->Canvas->FillRect(Rect(0,0,imageWidth,imageHeight));
              
                  ind1=i_begin;
                  int y_win ;
                  for(int i=0; i<=imageWidth; i++)
                  {
                     if(!i)
                     {
                            y_win= imageHeight - (sourceTable[i_begin].deriv-
                                    glMinY.deriv)*imageHeight/dY ;
                                    Bitmap->Canvas->MoveTo(i, y_win) ;
                      }
                     ind2=i_begin + stepsPerPix*i;
                      maxYpoint= *max_element(sourceTable.begin()+ind1, sourceTable.begin()+ind2, isMore) ;
                      minYpoint= *min_element(sourceTable.begin()+ind1, sourceTable.begin()+ind2, isMore) ;
                    y_win= imageHeight- (maxYpoint.deriv-
                                        glMinY.deriv)*imageHeight/dY ;
                     Bitmap->Canvas->LineTo(i, y_win) ;
                    y_win= imageHeight- (minYpoint.deriv-
                                        glMinY.deriv)*imageHeight/dY ;
                     Bitmap->Canvas->LineTo(i, y_win) ;
                     ind1=ind2 ;
 
                }
         Image->Canvas->CopyRect(Rect(0,0,imageWidth,imageHeight), 
                                           Bitmap->Canvas, 
                Rect(0,0,Bitmap->Width, Bitmap->Height)) ;
          }
          else {  // отрисовка в лоб всех точек
 
                  double pixNum ;
                  pixNum = (float)imageWidth/abs(i_begin-i_end) ;
               
                   int num=1;
                   int x_win=0 ; int y_win=0 ;
                   Bitmap->Canvas->MoveTo(0,0) ;
                   Bitmap->Canvas->FillRect(Rect(0,0,imageWidth,imageHeight));
                  for(int i=i_begin; i<=i_end; i++)
                 {
                      
                     if(i==i_begin)
                     {
                         y_win= imageHeight-
                         (sourceTable[i].deriv-glMinY.deriv)*imageHeight/(glMaxY.deriv-
                                                                     glMinY.deriv) ;
                         Bitmap->Canvas->MoveTo(0, y_win) ;
 
                     }
 
                     y_win= imageHeight-
                    (sourceTable[i].deriv-glMinY.deriv)*imageHeight/(glMaxY.deriv-
                                                                     glMinY.deriv) ;
 
                      Bitmap->Canvas->LineTo(x_win, y_win);
                      x_win= num*pixNum ;
                       num++ ;
 
                 } // for
          Image->Canvas->CopyRect(Rect(0,0,imageWidth,imageHeight), 
                                           Bitmap->Canvas, 
                   Rect(0,0,Bitmap->Width, Bitmap->Height)) ;        
           }// else
 
   return 0;
}
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
14.07.2011, 15:41
Помогаю со студенческими работами здесь

Отрисовка графика в реальном времени
Необходимо отрисовывать график в процессе работы программы. Т.е. например, y=x на интервале , затем через 2 секунды y=x на интервале , ...

Графика - для чего нужен lineto(x1,y1)
Что она делае эта функция не знаю, может ктото обяснит? Это должен быть триугольник! uses graphABC; begin setpenwidth(20); ...

Графика. Объясните принцип работы Lineto(x,y)
Можете объяснить принцип работы Lineto(x,y)? Он сначала берёт текущую точку с координатами (0,0) в не зависимости от того проводил я линию...

Отрисовка графика
Доброго времени суток! Никак не могу нарисовать график функции. До этого рисовал (в моём понимании) более сложные графики,...

Отрисовка графика
Всем привет. Помогите пожалуйста разобраться. Имеется функция:s(t)=cos(2*Pi*13*t+(Pi/6)). Нашел функции для построения(на картинке...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США. Нашел на реддите интересную статью под названием «Кто-нибудь знает, где получить бесплатный компьютер или. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru