Рисование Арки, не могу понять один момент?

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Рисование Арки, не могу понять один момент?

Сообщение xterro » 14.02.2015 01:20:09

Доброго времени суток, нашёл в инете код, для рисования арки. У простил его немного, убрав функции рисования, оставил только код вычисления точек(для последующей отрисовки). Сначала код:

Код: Выделить всё
procedure TArc.CalculateArc();
var
    Coef, Delta : Real;
    BAngle, EAngle : Real;
    Iterations, i : Integer;
begin
    { x = R * cos(A) + X
      y = R * sin(A) + Y }

    // Переводим в радианы
    BAngle := (FStartAngle / 180) * Pi;
    EAngle := (FEndAngle / 180) * Pi;

    // Определяем оптимальное количество итераций
    Coef := (Pi*2) / Abs(EAngle - BAngle);
    Iterations := Round((2 * FRadius ) / Coef);
    Delta := (EAngle - BAngle) / Iterations;

    SetLength(Points, Iterations);

    WriteLn('Iterations: ', Iterations);
    for i:=0 to Iterations-1 do begin
        Points[i].X := FRadius * Cos(-BAngle) + FX;
        Points[i].Y := FRadius * Sin(-BAngle) + FY;
        BAngle := BAngle + Delta;
        WriteLn(i, '. X: ', Points[i].X, ' Y: ', Points[i].Y);
    end;
end;                                                                         

Собственно проблема заключается в том, что в данном варианте, арка не дорисовывается, т.е например задаю угол от 0 до 90гр. на деле рисует от 0 до ~80-85 гр. но если увеличить количество точек в массиве на одну и соответсвенно увеличить количество итераций на 1,
Код: Выделить всё
SetLength(Points, Iterations+1);

    for i:=0 to Iterations do begin
        Points[i].X := FRadius * Cos(-BAngle) + FX;
        Points[i].Y := FRadius * Sin(-BAngle) + FY;
        BAngle := BAngle + Delta;
    end;

то всё становится красивенько и ровненько. Не могу понять почему так :( Так же не даёт покоя строчка вычисления количества итераций, не могу понять зачем это сделано, зачем делить диаметр на часть окружности(для угла в 90гр. Coef=4)?
Код: Выделить всё
Iterations := Round((2 * FRadius ) / Coef);

Вроде просто всё, а не въеду :?
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: Рисование Арки, не могу понять один момент?

Сообщение zub » 14.02.2015 02:08:31

ты забыл про последнюю точку. забей жестко колво итераций 1 - т.е. какбудьто дугу надо апроксимировать отрезком и прогони свой цикл, всё станет ясно

>>Так же не даёт покоя строчка вычисления количества итераций
не вникал, но зависеть должно не только от радиуса и угла а еще от масштаба на экране (т.е. от "фактического" радиуса, это ведь редактор насколько я понимаю). тут место для творчества - подбери формулу так, чтобы она давала приемлимую апроксимацию, с чего ты взял что нужно делать именно по этой формуле?
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Рисование Арки, не могу понять один момент?

Сообщение xterro » 14.02.2015 14:22:44

с чего ты взял что нужно делать именно по этой формуле?

Даже не знаю, просто нашёл пример и по нему начал делать. Пытался делать ещё по другому: количество итераций - это разница между конечным и начальным углами в градусах, шаг - 1 градус, но картинка получалась не айс:
т.е если вот так:
Код: Выделить всё
    // Coef := (Pi*2) / Abs(EAngle - BAngle);
    Iterations := Abs(FEndAngle - FStartAngle); //Round((2 * FRadius ) / Coef);
    Delta := (1/180)*Pi; //(EAngle - BAngle) / Iterations;

    SetLength(Points, Iterations);

    for i:=0 to Iterations-1 do begin           
         // ....
   end;                       

В таком варианте получалось что точки как-бы накладывались друг на друга, и получалось коряво:
2.png
2.png (283 байт) Просмотров: 26925
3.png
3.png (308 байт) Просмотров: 26925

Если следовать первноначальному коду, то картинка получалась вполне себе красивой:
1.png
1.png (269 байт) Просмотров: 26925

Вот и думал, может помогут разобраться, что за магия такая 8)
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: Рисование Арки, не могу понять один момент?

Сообщение zub » 14.02.2015 14:45:07

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

Добавлено спустя 3 часа 49 минут 15 секунд:
или я чето я непонял и ты точками рисуешь? будет будет тормозилка, рисуй линиями
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Рисование Арки, не могу понять один момент?

Сообщение xterro » 15.02.2015 10:47:18

Не, рисую как раз отрезками. В этой функции только расчитываю массив точек, по которому потом пробегаю, и соединяю эти точки последовательно отрезками.(1-2-3-4... и т.д) :)
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: Рисование Арки, не могу понять один момент?

Сообщение zub » 15.02.2015 13:51:17

Глянул че там у меня с дугой, всё печально лод не считается))
Код: Выделить всё
procedure GDBObjARC.createpoint;
var
  i: GDBInteger;
  v:GDBvertex;
  pv:GDBVertex;
begin
  angle := endangle - startangle;
  if angle < 0 then angle := 2 * pi + angle;

  Vertex3D_in_WCS_Array.clear;
  v.x:=cos(startangle);
  v.y:=sin(startangle);
  v.z:=0;
  pv:=VectorTransform3D(v,objmatrix);
  Vertex3D_in_WCS_Array.add(@pv);

  lod:=100;  { TODO : А кто лод считать будет? }

  for i:=1 to lod do
  begin
              v.x:=cos(startangle+i / lod * angle);
              v.y:=sin(startangle+i / lod * angle);
              v.z:=0;
              pv:=VectorTransform3D(v,objmatrix);
              Vertex3D_in_WCS_Array.add(@pv);
  end;
  Vertex3D_in_WCS_Array.Shrink;
end;

сейчас попробую ченить сваять с лодом

Добавлено спустя 32 минуты 7 секунд:
а ничего своять без тотальных переделок не получится, на момент генерации точек еще неизвестно с каким масштабом будет отображена дуга. т.е. в моем случае точки нужно генерировать с максимальной детализацией, оптимизации включаются в момент отрисовки - если масштаб маленький, дуга рисуется через точку, через две и т.д в зависимости от масштаба... Надо будет этот момент переделать
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Рисование Арки, не могу понять один момент?

Сообщение xterro » 15.02.2015 20:06:10

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

P.S. ради прикола, попробуй код, который у меня, глядишь получится чего ))
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: Рисование Арки, не могу понять один момент?

Сообщение zub » 15.02.2015 21:19:17

вообще у меня lod - абстрактный уровень детализации объекта, в данном случае совпадает с количеством сегментов апроксимирующих дугу.
>>И потом, как может быть не известен масштаб, или у тебя каждая фигура со своим масштабом рисуется? я думал, в такого рода программах, масштаб един для всей схемы
Крутишь колесико мышки - масштаб (отображения, но не примитивов) меняется, на этапе генерации примитивов в общем случае неизвесно с каким масштабом будет отображаться примитив (возможно дуга с радиусом 0.0001 будет занимать весь экран, а может будет видна в виде точки). Сейчас пока правлю чтоб вытащить масштаб на этап генерации, посгляжу что получится.

>>P.S. ради прикола, попробуй код, который у меня, глядишь получится чего ))
ничего хорошего не получится - будет лод зависеть от угла, а должен динамически подстраиваться под ситуацию на экране, чтобы экономить ресурсы не уменшая критически качество изображения
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Рисование Арки, не могу понять один момент?

Сообщение xterro » 15.02.2015 21:34:00

Всё равно не понимаю :? В начале ставишь коэф. масштабирования скажем 2, и рисуешь, например две дуги, одна с радиусом 0,00001 вторая с радиусом 10 (это всё условные единицы, никак не зависящие от координат), потом при выводе приводишь их в координаты экрана, в результате, дуга в 0,0001 будет точкой, дуга в 10 - нормальной дугой, вернее она будет значительно больше первой. Но коэф. масштабирования у обоих одинаковый - 2. крутишь колёсико и он меняется 2.1, 2,2, 2,3... 5... 10 соответственно меняется и картинка на экране. По крайней мере я так для себя думал )
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: Рисование Арки, не могу понять один момент?

Сообщение zub » 15.02.2015 23:25:43

Переделал, теперь это выглядит так:
Код: Выделить всё
procedure GDBObjARC.createpoints(var DC:TDrawContext);
var
  i: GDBInteger;
  l: GDBDouble;
  v:GDBvertex;
  pv:GDBVertex;
begin
  angle := endangle - startangle;
  if angle < 0 then angle := 2 * pi + angle;

  Vertex3D_in_WCS_Array.clear;

  v.x:=cos(startangle);
  v.y:=sin(startangle);
  v.z:=0;
  pv:=VectorTransform3D(v,objmatrix);
  Vertex3D_in_WCS_Array.add(@pv);

  l:=r*angle/(dc.zoom*3);
  if l>255 then lod:=255
           else
               begin
                    lod:=round(l);
                    if lod<4 then lod:=4;
               end;

  for i:=1 to lod do
  begin
              v.x:=cos(startangle+i / lod * angle);
              v.y:=sin(startangle+i / lod * angle);
              v.z:=0;
              pv:=VectorTransform3D(v,objmatrix);
              Vertex3D_in_WCS_Array.add(@pv);
  end;
  Vertex3D_in_WCS_Array.Shrink;
end;

В процедуру приходит структура данных содержащая некоторые данные используемые при отрисовке, в 2D случае важен только dc.zoom - чем он больше, тем изображение на экране меньше и деталей требуется меньше. на основе его и длины дуги считаю lod, формула "экспериментальная", кофф. три взят от балды, но проде результаты нормальные)). lod ограничен 255 - потому что под него выделен байт))
Вот 3 картинки с одной и тойже дугой в разных масштабах, дуга радиусом ~145 едениц.
На первой она маленькая, lod=5, на таком масштабе больше и ненадо, зато экономия и памяти и проца, в случае если на чертеже несколько тысяч таких дуг.
На второй масштаб увеличен, lod не пересчитан, = 5, просто чтоб понимать что рисуется заместо такой дуги.
На третьей масштаб увеличен, lod пересчитан =231.
Вложения
lod_231.PNG
lod_231.PNG (10.13 КБ) Просмотров: 26835
lod_5_scale.PNG
lod_5_min.PNG
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Рисование Арки, не могу понять один момент?

Сообщение xterro » 15.02.2015 23:45:48

Всё, теперь понял, просто для повышения производительности. Интересно, а экономия большая получается, если скажем масштаб как на 3-й картинке, а lod так и останется например 100, мол, ну подумаешь лишние 90-95 итераций прокрутим, для камня это семечки. Не сравнивал?
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: Рисование Арки, не могу понять один момент?

Сообщение zub » 16.02.2015 01:14:34

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

фиксированный lod=100
загрузка файла ~7.3сек (включает время первичной регенерации, от старта загрузки до появления картинки)
отъел памяти после загрузки ~639мб
время на отрисовку кадра ~200мсек\17мсек (в кадре видимы все 60000 дуг)
повторная регенерация ~1.5сек

lod "динамический"
загрузка файла ~1.5сек (включает время первичной регенерации, от старта загрузки до появления картинки)
отъел памяти после загрузки ~359мб
время на отрисовку кадра ~21мсек\17мсек (в кадре видимы все 60000 дуг)
повторная регенерация ~0.2сек

голая программа после старта перед загрузкой файла отъедает 154мб, цифры о памяти из диспетчера задач - графа "выделенная память"
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Рисование Арки, не могу понять один момент?

Сообщение xterro » 16.02.2015 08:18:20

Мда, существенно, походу мне в будущем придётся с этим же вопросом столкнуться... в далёком будущем :D
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: Рисование Арки, не могу понять один момент?

Сообщение zub » 16.02.2015 10:36:52

дополнительно ограничил lod сверху - максимум 20 сегментов, для работы на экране потянет, но для печати этого мало
>>в далёком будущем
Вообще лучше сразу стресстестики гонять чтобы изначально закладывать разные "оптимизации", пусть даже не реализовывать, но понимать что рано или поздно это понадобится. Файл из теста выше в автокаде и грузится быстрее, и память не жрет, и рисуется быстрее. Например можно вообще не генерировать массив точек на каждую арку а использовать заранее расчитаный общий на все окружности\арки - рисовать крайние точки фактической арки, а между ними брать выборку с нужным шагом из предрасчитанного массива со сдвигом и масштабированием - рости есть куда))
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Рисование Арки, не могу понять один момент?

Сообщение Снег Север » 16.02.2015 14:52:46

Может я не в теме, но если нужна качественная масштабируемая графика, то, может, стоит посмотреть в сторону векторной графики?
Например http://wiki.lazarus.freepascal.org/fpvectorial
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 3038
Зарегистрирован: 27.11.2007 16:14:47

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18

Рейтинг@Mail.ru