Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > отрисовка графиков на pictureBox


Автор: maxi91m 1.11.2009, 00:39
Написал программу распозвнования выражений, 
Строю графики различных функций, но для построения делаю много итераций из за чего график рисуется медленно, кто может подскажет как ускорить.

Вот так я вывожу
Код

    private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
                    int n=textBox1->TextLength;
                    int len;
                    Pen^ pen;
                    switch(cl++)
                    {
                        case 0:cr = Color::Black; break;
                        case 1: cr = Color::DarkGray;    break;
                        case 2: cr = Color::Blue;    break;
                        case 3: cr = Color::Brown;    break;
                        case 4: cr = Color::Red;    break;
                        case 5: cr = Color::Green;    break;
                        case 6: cr = Color::Pink;    break;
                        default: 
                            {
                                cl=0;
                                cr = Color::Black;
                            }
                    }
                    pen = gcnew Pen(cr, 1);

                    char* str = new char[n];
                    char* str1 = new char[2*n];
                    for(int i=0; i<n; i++)
                        str[i]=Convert::ToChar(textBox1->Text[i]);

                    if(check(str,n))
                    {
                    translate_str(str,str1,n,len);
                    for(double i=-10;i<10;i+=0.001)
                      try{
                          pictureBox1->CreateGraphics()->DrawRectangle(pen,30*i+290,-30*solution(str1,len,i)+200,1,1);
                      }
                      catch(...){
                          if(i==0.0) 
                            { //деление на ноль
                                i+=0.001;
                                 pictureBox1->CreateGraphics()->DrawRectangle(pen,30*i+290,-30*solution(str1,len,i)+200,1,1);
                            }
                            else if(i<0) {//обработка отрицательных чисел для корня
                                i=0.00000001;
                             pictureBox1->CreateGraphics()->DrawRectangle(pen,30*i+290,-30*solution(str1,len,i)+200,1,1);
                            }
                     }
                    }else
                        MessageBox::Show("Ошибка","Некоректно заанна выражение",MessageBoxButtons::OK);
                  
             }

Если мало итераций то пропуски
  for(double i=-10;i<10;i+=0.01)//вот при таких условиях
http://ipicture.ru/Gallery/Viewfull/25946761.html

Автор: GremlinProg 1.11.2009, 01:15
это обычная проблема при построении такого рода графиков,
статический шаг по одной оси в любом случае не дает полную картину,
это только увеличивает число "пустых расчетов", которые сливаются в одну точку,
можешь даже сам посчитать число таких повторов: оно будет быстро расти при уменьшении шага,
при том, что детализация будет по прежнему сильно отставать, а тормоза - увеличиваться

если у тебя строятся произвольные графики, то здесь расчет координат "простым проходом луча" не поможет,
смотри алгоритмы по растеризации,

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

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

Добавлено через 10 минут и 4 секунды
Цитата(GremlinProg @  1.11.2009,  03:15 Найти цитируемый пост)
если разница ординат между двумя последними итерациями меньше единицы

конечно, это с учетом шага = 1

Добавлено через 14 минут и 39 секунд
Цитата(GremlinProg @  1.11.2009,  03:15 Найти цитируемый пост)
меньше единицы

больше )

Автор: maxi91m 1.11.2009, 01:34
Это уже будет  увесистая программа посчет алгоритмов, да и при замени осей я так думаю придется переходить к обратной функции, ну или как- то еще измудряться.
А можно как нибуть строить ввиде прямых которые будут соеденять 2 точки, пред идущею и новую?
Как еще можно туда подкрутить что то вроде осей с цифирками?

Автор: GremlinProg 1.11.2009, 01:44
конечно можно,
просто замени DrawRectangle на DrawLine либо на LineTo и т.п.,
при использовании LineTo, поставь один вызов MoveTo на первую точку перед циклом

только пропуски от этого ни куда не исчезнут,
график на этих участках как был дырявым так и останется

Автор: maxi91m 1.11.2009, 01:48
А почему не исчезнут то, прямая тогда же станет целостной кривой?

Автор: GremlinProg 1.11.2009, 02:04
да, но крутые повороты эта прямая будет срезать точно так же, как и точечный вариант
только это будет нагляднее

Автор: maxi91m 1.11.2009, 02:12
А может где есть уже реализованные методы отрисовки таких функций? Где уже все утчтено.

Автор: GremlinProg 6.11.2009, 12:39
обрати внимание на эту тему: http://forum.vingrad.ru/forum/topic-278955/kw-график-массив-данных-окно.html
сплайны - как раз то, что подходит для таких непредсказуемых функций

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)