Как нарисовать эллипс на GDL? Просто!



Очередной экзерцисс посвящен эллипсу. 
Понадобился мне как то эллипс. И не простой, а золотой повернутый на заданный угол. Если с поворотом все было не сложно (ROT2), то искренне удивлен был я когда нифига с тэгом «эллипс» в рукве по GDL не обнаружилось.
Ну неужели инженер с 10 летним стажем не родит себе эллипс, подумал я. Даже формула всплыла в голове. Правда мутно. И полез я в онлайн хламовник уточнить воспоминания. Нашел каноническое уравнение, убедился что еще не все знания со школы пропил забыл, вспомянул добрым словом свою учительницу по алгебре-геометрии, а также ее последовательницу старую грымзу из универа…
Формула формулой, но двигаться в сторону метода функции подобных Flattern не хотелось. Точнее не сегодня. С недавних пор научился отбрасывать очевидное решение к-е лезет в голову с лозунгом – «да, че тут думать то!!!». Подумал-посмотрел и задача уже представлялась вот такой:
1.      Каноническая формула эллипса:  
, была приведена к «школьной»:

 






 , наличие квадратов и корня значило только то что для построения придется писать кучу условий по опр. знаков + и - ….
2.      В параметрическом виде эллипс описывается понятнее(имхо):        
X = a* cos A
Y = b* sin A
Это каноническое уравнение, а после поворота, на угол F

х1 = x*cos(F) + y*sin(F)
y1 = -x*sin(F) + y*cos(F)

А - угол (0-360)
a,b - полуоси эллипса
F - угол поворота эллипса
X,Y - координаты на эллипсе до поворота
x1,y1 - кординаты на эллипсе после поворота

Казалось бы аналитическое решение есть, осталось привести к школьной Y(X), дать шаг угла, через параметры задать оси и угол, и 2D в цикле отрисовать 360/Angle_step отрезков. Но окончательное решение оказалось более изощренным велосипедом. )))
Листая мануал, я обратил внимание на функцию Spline2, формат ее такой:





Чем удобна эта функция?
1. Тем что рисует.
2. Тем что принимает столько параметров сколько ей передашь.
3. Тем что избавляет от определения «знаков» при извлечении корней, и устранении других неопределенностей.
НО:
1.      Нужно уметь вычислить опорные точки и, что самое на сегодня интересное
2.      Угол касательной к нашей кривой в опорной точке (в градусах).
Вот у появилось то что лично я не знал – ур-е касательной к эллипсу, т.е. знал что касательная это первая производная, но вот взять ее самостоятельно уже вряд ли смог бы…Хламовник знал и эту формулу ))):



 ,
 здесь: х0, у0 – точка эллипса, в которой ищем производную (=уравнение прямой(касательной)), приведя его к школьному У(х):



Вот она! Искомая kx+b, арктангенс к-та k, которой и есть угол наклона касательной.
Дальше было дело техники:




            Параметры:
 NH - массив с координатами опорных точек, для опыта принял число точек восемь, т.е. ч/з каждые 45градусов.
ANS – массив углов касательных в опорных точках.
Конечно, можно было и в один массив,но тада надо было бы иметь проблемы с переводом типов «длина» «угол» друг в друга.

В основном скрипте 
вычисляем координаты оп.точек, и углы касаетльных, пишем их в массивы NH и ANS соотв.

as=45 ! angle step – шаг угла.
ang=0 ! start angle – начальный угол
eps=1e-12 ! точность представления(чтобы не фиксить деление на ноль, обычно катит)
FOR X=1 TO 8
            NH[X][1]=OA*cos(ang) :        NH[X][2]=OB*sin(ang) ! коорд. опорной точки
            x0=NH[X][1] : y0=NH[X][2]  ! покороче, чтобы формула с индексами не резала глаз
            ANS[X]=ATN(-(x0*OB^2)/(y0*OA^2+eps)) ! угол касания в опорной точке.
            a0=ANS[X] ! тоже запишем покороче
            ang=ang+as ! следующий угол
            PUT x0,y0,a0 ! пишем в стек данные для сплайна
NEXT X

В 2D скрипте снимаем пенки:
rot2 alpha ! алиллуйа GDL компилятору!!!
pen pen_Cont
spline2 8,        3,         ! 8 точек, статус 3=2+1, здесь 2 помогает «правильно» замкнуть кривую.
                        USE(NSP) ! используем use чтобы значения в стеке можно было использовать дальше.
                       
FOR x=1 to 8
            hotspot2 GET(1), GET(1) ! используем == хотспоты в опорных точках, hotspline2 не було )))
            get(1) !  достаем значение угла, оно нам не нужно, просто его «пропускаем»
NEXT X

Hotspot2 0,0 ! ну и по центру.
if axes then
            pen pen_Axes
            line2 -1.2*OA, 0, 1.2*OA, 0
            line2 0,-1.2*OB, 0, 1.2*OB
endif
del 1 ! поворот.

Вот и все. Запускаем и смотрим на наш свежеиспеченный эээ контур! (еще не факт что эллипс, точек всего 8 а вот как построены участки м/у опорными есть тайна зашитая в одной из dll арчика ). В том что это эллипс предстоит убедиться.


Вот они два красавца. Один с поворотом на 25гр. Чтобы была возможность привязываться по габаритам, я установил птичку – точки по углам вокруг 2D символа. Чтобы ловить габариты эллипса(нужно выключить оси). Теперь пробуем построить «родной» эллипс с осями равными…кароче такой же по размеру.



Была поставлена точность вычисления площадей до долей мм, по габаритным точкам объекта была построена рамка габарит(зеленая). ПО ней был построен «равный» эллипс средствами арчикада(инструмент окружность). После чего самопальный эллипс был жестоко подорван декомпозирован. Результаты сравнения площади ясны из скрина.
И казалось бы что еще…площади не совпали, хоть и весьма копеечно, можно было вспомнить про eps, подумать о большем количестве точек…скрин совмещения контуров, ниже, видно(не очень конечно) что отклонения были и «в плюс» и «в минус»



Отклонения прослеживались на максимальном увеличении. Разумеется в dll не может быть и речи ни о каком eps. И цель была в общем то достигнута – программно был построен эллипс, повернутый эллипс, с заданными параметрами. Планирую использовать этот код для отрисовки круглых отверстий в аксонометрии, к-ю буду получать с MSF. Конечно код будет доведен до ума, необходимо будет строить и аксонометрические проекции дуги, а не всей окружности, не помешал бы и активный спот…и.т.п. Это уже другие заморочки. Здесь же хочу сделать два замечательных вывода:
1.      Внутренний механизм построения эллипса в арчикад использует практически идентичный код, и в связи с этим в арсенале GDL отсутствует команда построения эллипса.
2.      Техника построения графика функции при помощи объекта архикад:
- есть уравнение функции
- есть уравнение производной, для непрерывных функций это прямая, арктангенс к-та к к-й есть угол наклона касательной в градусах.
- используя необходимый шаг аргумента формируем два массива – координат и углов касательной
- при помощи Spline2 строим график.

Что еще…а пофантазирую на тему альтернативы.

 Как только объект заработал «как требуется» в голову пришло еще одно решение, не менее а более «изящное» ))) (Хорошая мысля приходит апосля):
Удаляем все из основного скрипта и в 2D пишем так:
rot2 alpha
pen pen_Cont
mul2 1,OB/OA
circle2 0,0, OA
Hotspot2 0,0
if axes then
            pen pen_Axes
            line2 -1.2*OA, 0, 1.2*OA, 0
            line2 0,-1.2*OA, 0, 1.2*OA
endif
del 2
В 2 раза меньше кода и тот же результат на скрине, причем!!! Что весьма удивительно и подтверждает вывод 1 – после декомпозиции площади повернутого и неповернутого эллипса отличаются!!!  В неповернутом виде площадь равна родному эллипсу, а вот почему она отличается в повернутом варианте – вопрос к разрабам.



И вот что еще было мной замечено.
Рисуем дугу эллипса инструментом окружность. А затем вызываем редактирование угла дуги:



И замечаем что Активный спот(обвел зеленым) движется не по эллипсу, а! по окружности с радиусом, равным меньшей из осей(экспериментально проверено) . Что происходит – работает GDL скрипт, активный спот в котором выполняет редактирование угла, по которому в последствии определяются требуемые параметры Spline кривой.

Для дальнейших экспериментов - собсно объекты Ellipse-Spline и Ellipse-Mul2.

Комментарии

Популярные сообщения из этого блога

GDL. Объект для моделей из "оцилиндрованного бревна"

График функции в полярных координатах?! Легко!

Объект "Plan Marker"