Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Ошибка при масштабировании графики


Автор: seraffim 6.12.2012, 15:29
Здравствуйте ,написал программу для вывода точек в builder ,но допустил ошибку и 2 день её вылавливаю , был бы рад ,если бы указали на неё .
На форме есть GroupBox , по высоте он равен форме .
Пытаюсь вывести на свободное пространство точки и оси X,Y , предварительно отмаштабировав ,но большинство точек выходят за пределы видимой области формы.

maxx,minx,maxy,максимальные и минимальные координаты по х и у,
m - массив координат .

 
Код

k1=(Form1->Width - Form1->GroupBox1->Width)*1.0/(maxx-minx);// коэффициент преобразования по Х 
  k2=(Form1->Height)*1.0/(maxy-miny); //коэффициент преобразования по Y 
  x0=abs(minx*k1);  //положение начала координат по х
  y0=abs(maxy*k2); // и по у
  // вывод осей
  Form1->Canvas->MoveTo(0,int(y0));
  Form1->Canvas->LineTo(Form1->Width-Form1->GroupBox1->Width,int(y0));
  Form1->Canvas->MoveTo(int(x0),0);
  Form1->Canvas->LineTo(int(x0),Form1->Height);
 //вывод точек
   for (int i=0;i<n;i++)
 Form1->Canvas->Ellipse(int(m[i].x*k1+x0-4),int(y0-m[i].y*k2-4),int(m[i].x*k1+x0+4),int(y0-m[i].y*k2+4));


Добавление : После многократного разбора ошибка вроде бы была найдена (к1 и к2 нужно брать по модулю),но всё-равно ,иногда точки уходят за форму и при большой разнице между максимумом и минимумом по X или Y (порядка 300) всё точки кучкуются на осях, в чём же дело ?

Автор: artsb 6.12.2012, 21:42
Ничего не понятно. Вы можете привести скрины, как "должно быть" и как "получается".

Автор: seraffim 6.12.2012, 22:00
Должно быть как-то вот так http://s53.radikal.ru/i139/1212/33/558c1b3d1898.jpg, а частенько выходит так  -     http://s018.radikal.ru/i520/1212/ba/06c50e5d2448.jpg.

Автор: artsb 6.12.2012, 22:21
Ясно.
А что за переменные maxx,minx,maxy,miny? Как они рассчитываются?

Добавлено через 4 минуты и 26 секунд
По-моему, x0 и y0 проще рассчитать так:
Код

x0 = (this->ClientWindth - GroupBox1->Width) / 2;
y0 = this->ClientHeight / 2;

Автор: seraffim 6.12.2012, 22:26
Максимальные  и минимальные значения по X  и Y : 
Код

int t,i;
for(i=0;i<n;i++)
{
m[i].x=StrToInt(Form1->StringGrid1->Cells[1][i+1]);
m[i].y=StrToInt(Form1->StringGrid1->Cells[2][i+1]);
}
  t=StrToInt(Form1->StringGrid1->Cells[1][1]);
 minx=t;maxx=t;
  t=StrToInt(Form1->StringGrid1->Cells[2][1]);
  miny=t;maxy=t;
 for (i=2;i<=n;i++)
  {
  t=m[i].x;
  if (t>maxx) maxx=t;
  if (t<minx) minx=t;
  t=m[i].y;
  if (t>maxy) maxy=t;
  if (t<miny) miny=t;
  }
  

Автор: artsb 7.12.2012, 08:46
user posted image
Оно?
Код

    const int n = 3;
    const int PointR = 4;
    const int FieldSize = 5;
    int t, i;
    double k1, k2;
    int maxx, minx, maxy, miny;
    int x0, y0;

    TPoint m[n];

//    m[0].x = 27; m[0].y = 2;
//    m[1].x = 29; m[1].y = 31;
//    m[2].x = -29; m[2].y = -28;

    m[0].x = 10; m[0].y = -40;
    m[1].x = 27; m[1].y = 15;
    m[2].x = 7; m[2].y = 1;

    t = m[0].x;
    minx = t; maxx = t;
    t = m[0].y;
    miny = t; maxy = t;

    for(i = 1; i < n; i++)
    {
        if(m[i].x > maxx) maxx = m[i].x;
        else if(m[i].x < minx) minx = m[i].x;

        if(m[i].y > maxy) maxy = m[i].y;
        else if(m[i].y < miny) miny = m[i].y;
    }

    k1 = ((double)(this->ClientWidth - GroupBox1->Width) - (FieldSize * 2)) / abs(maxx - minx);
    k2 = ((double)this->ClientHeight - (FieldSize * 2)) / abs(maxy - miny);

    x0 = ((minx * k1) * -1) + FieldSize;
    y0 = (maxy * k2) + FieldSize;
    // вывод осей
    this->Canvas->MoveTo(0, y0);
    this->Canvas->LineTo(this->ClientWidth - GroupBox1->Width, y0);
    this->Canvas->MoveTo(x0, 0);
    this->Canvas->LineTo(x0, this->ClientHeight);
    // вывод линий
    for(i = 0; i < n; i++)
    {
        this->Canvas->MoveTo(
            m[i].x * k1 + x0,
            y0 - m[i].y * k2);

        if(i < (n - 1))
        {
            this->Canvas->LineTo(
                m[i + 1].x * k1 + x0,
                y0 - m[i + 1].y * k2);
        }
        else
        {
            this->Canvas->LineTo(
                m[0].x * k1 + x0,
                y0 - m[0].y * k2);
        }
    }
    // вывод точек
    for(i = 0; i < n; i++)
    {
        this->Canvas->Ellipse(
            int(m[i].x * k1) + x0 - PointR,
            y0 - int(m[i].y * k2) - PointR,
            int(m[i].x * k1) + x0 + PointR,
            y0 - int(m[i].y * k2) + PointR);
    }

Автор: seraffim 7.12.2012, 19:30
Код

x0 = ((minx * k1) * -1) + FieldSize; 

Уножение на -1  ??

Автор: artsb 7.12.2012, 21:25
Цитата(seraffim @  7.12.2012,  19:30 Найти цитируемый пост)
Уножение на -1  ??

Да. Чтобы правильно выставить ось Y.
Я так понял, что фигура должна занимать всё свободное место.

Автор: seraffim 7.12.2012, 21:50
Да ,всё  свободное место. 
Если я правильно понял основную мысль будет так :
Код

k1=abs((Form1->GroupBox1->Left-20)*1.0/(maxx-minx));
  k2=abs((Form1->Height-50)*1.0/(maxy-miny));
  if (minx<0)
  x0=abs(minx*k1)+10;
  else
  x0=Form1->GroupBox1->Left-maxx*k1-10;
  if (maxy>0)
  y0=maxy*k2+10; 
  else
  y0=Form1->Height-10+miny*k2;

Используем Heigh вместо  ClientHeight из-за того,что этот кусок будет использоваться в функции перирисовки .

Автор: artsb 7.12.2012, 22:13
Цитата(seraffim @  7.12.2012,  21:50 Найти цитируемый пост)
Если я правильно понял основную мысль будет так :

А я ничего не понял из того, что вы написали smile Я же написал рабочий код.

Цитата(seraffim @  7.12.2012,  21:50 Найти цитируемый пост)
Используем Heigh вместо  ClientHeight из-за того,что этот кусок будет использоваться в функции перирисовки .

Нужно использовать именно ClientHeight, чтобы исключить из расчётов шапку и бордюры.

Автор: seraffim 7.12.2012, 22:38
Цитата(artsb @  7.12.2012,  22:13 Найти цитируемый пост)
А я ничего не понял из того, что вы написали smile Я же написал рабочий код.

Тоже самое почти , но мне так понятнее  smile .
При  использовании ClientHeight  нельзя будет использовать для перерисовки эту же функцию.

Автор: artsb 7.12.2012, 22:51
Цитата(seraffim @  7.12.2012,  22:38 Найти цитируемый пост)
но мне так понятнее

Но так как я написал - работает smile Может я просто каменты напишу?

Цитата(seraffim @  7.12.2012,  22:38 Найти цитируемый пост)
При  использовании ClientHeight  нельзя будет использовать для перерисовки эту же функцию.

С чего вы взяли? Я использовал. Всё работало.

Автор: seraffim 7.12.2012, 23:04
Ну ClientHeight ,как я помню , размер доступной пользователю формы по Y ,а ,если ,например , форму опистить вниз до упора,то ClientHeight   ->0 и из рисунка получится невесть что.
Результаты эксперимента : до - http://s49.radikal.ru/i125/1212/57/d10872261e40.jpg , после выхода за пределы рабочего стола -  http://s017.radikal.ru/i417/1212/5b/bba20fcfb2d3.jpg   .

Автор: artsb 7.12.2012, 23:37
Цитата(seraffim @  7.12.2012,  23:04 Найти цитируемый пост)
Ну ClientHeight ,как я помню , размер доступной пользователю формы по Y ,а ,если ,например , форму опистить вниз до упора,то ClientHeight   ->0 и из рисунка получится невесть что.

Значит вы что-то не так делаете. Потому что, у меня всё чётко рисуется.

И кстати, разберитесь с осями. Почему они у вас всё время прыгают? Они должны либо находиться чётко по центру, либо так как у меня на скриншоте выше. А у вас то так, то сяк smile

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