GDL. Объект для моделей из "оцилиндрованного бревна"
В данной статье разобран пример
создания параметрического элемента моделирующего оцилиндрованное бревно. Начну свои GDL-экзерциссы, c довольно простого объекта. Тем не менее, отражающего
основные возможности GDL.
В частности то, что GDL поддерживает основные операции CSG(Constructive Solid Geometry –
логические операции над объемными формами) – вычитание, объединение и др.
Будем считать, что речь идет о версии объекта:
1.0 – Initial Version.
Планирую его переписать с учетом новой спецификации (морально устарел).
Ну что ж, в этом первом GDL-экзерциссе будут
некоторые «прыжки в сторону» -
поясняющие отвлечения от основной темы элемента. Думаю это будет полезно
тем, кто впервые решится на создание своего GDL-объекта. Кроме описаний интерфейса, буду по возможности
касаться некоторых моментов связанных с интересным поведением GDL-компилятора, это все-таки это не
полноценная IDE среда,
и в некоторых случаях лично я находил «ответы» именно в постах других людей,
споткнувшихся о теже «грабли» что и я. Эти вещи буду подчеркивать.
Основные функции, которыми мы
наделим элемент под названием «brevno»:
1.
Выбор количества пазов (для стыковки с бревнами
поперечного направления): от 0 до 3.
2.
Возможность задавать основную геометрию: радиус
бревна, радиус чашки, длина бревна.
3.
Возможность задать «получашку» вначале и (или) конце бревна.
4.
Возможность среза под заданный угол начала и (или)
конца бревна.
5.
Продольный паз (по длине бревна).
Итак, для всех этих целей нам потребуется задать
следующие параметры элемента:
Скрин 1 «Параметры»
По полю «имя» понятно назначение
параметров. Скажу лишь, что каждый параметр имеет следующие «атрибуты»:
- «Показ» - будет ли параметр виден
конечному пользователю в меню элемента.
- «Переменная» - имя переменной в
скрипте.
- «Тип» - стандартные типы
переменных показаны на скриншоте:
Скрин 2 «Типы параметров»
Здесь слева-направо, сверху-вниз,
пиктограммы типов: «Линейная величина», «угловая величина», «действительное
число», «целое число», «истина/ложь», «Текст», «Покрытие», «Тип линии»,
«Образец штриховки», «Цвет пера», «Разделитель», «Заголовок».
Судя по значкам у параметров на скрине 1 видим,
что: параметры Rb, Rc, L – линейные величины, опциональные
параметры Xb,Xe – истинностные
значения, что соответствует их логическому назначению – предоставить
пользователю выбор «Да/Нет».
«Синие» Параметры на
скрине 1 – это параметры соответствующие данному «подтипу» GDL- объекта, они создаются
автоматически при выборе подтипа. В этом примере нам требуется подтип
«Элемент модели» (без дальнейшей конкретизации). А вообще Арчик предлагает
весьма забавную иерархию библиотечных объектов (кто и на основании чего ее
составлял?!):
Скрин 3 «Подтипы объектов»
С основными исходными моментами
определились, теперь надо увязать работу параметров, задать им значения.
Рассмотрим скрипты объекта.
1. СКРИПТ ПАРАМЕТРОВ.
Скрин 4 «Скрипт параметров»
В первой строке мы задаем
параметру inn список возможных значений в соответствии с его
типом (целое число), после этого в меню появляется возможность выбора значения для inn из выпадающего списка. В случае, если скрипт параметров не
скомпилируется, т.е. будет содержать ошибки, эта возможность исчезнет, вплоть
до того момента пока ошибки не будут устранены. Таким образом если у вас
возникла подобная проблема, даже если при нажатии на «Проверить скрипт» ошибки
нет, знайте –решение такой ситуации следует искать в скрипте параметров.
Дальше в зависимости
от выбранного значения inn определяем
значения параметров х1,х2,х3, L.
Математика здесь элементарная, тем не менее, есть «хитрости» описания, которые
приходят с некоторым опытом, и которые достаточно выразительно позволяют
описать требуемое поведение связки параметров. В данном случае выразительность
заключается в следующем: L-длина
бревна, X1,X2,X3 координаты пазов в пределах этой
длины. Возьмем ситуацию когда пользователь задал 2 паза, указал их координаты
Х1,Х2, в каких пределах теперь можно изменять длину? Правильно – от Х2 до
требуемой. Таким образом строка:
values "L" range
[x2+0.001,)
описывает например случай когда
на плане был размещен объект с длиной
допустим 1,5м(L=1500),
затем без всяких предупреждений пользователь зашел в меню и выставил кол-во
пазов 2 и задал Х1=…, Х2=3500. Т.е. в случае отсутствия этой строки паз «2»
попал бы «в пустоту», а длина осталась бы равной L=1500. Т.е. это описание исключило
данную ситуацию и ситуацию «опечатки», невнимательного ввода – длина в данном
случае автоматически пересчитается и объект автоматически удлинится, что нельзя
будет не заметить в 3Д. Также скрипт параметров сыграет главную роль при
интерактивном редактировании нашего объекта в 3Д. Об этом дальше. Здесь же еще отметим роль скобок [ ] и
( ) в описании граничных условий на значения параметров – круглые скобки
описывают ситуацию когда значение перед/после скобки «не включается» в
диапазон. Квадратные -наоборот(включается). Когда нужно указать диапазон от «х»
до «бесконечности» используют круглую закрывающую скобку: values "L" range [x3+0.001,)
2. ОСНОВНОЙ СКРИПТ
Скрин 5 «Основной скрипт»
Здесь мы назначаем объекту материал в соответствии с выбранным в меню
параметром g_m, команда material будет иметь значение для всех 3д
команд создающих 3д тела, до момента пока не встретится очередное определение material. Стандартное поведение «команды-аттрибута».
Дальше в зависимости от кол-ва пазов указанных в меню (inn) будем инициализировать локальные переменные ix1,ix2,ix3 единицей при наличии соответствующего паза. Это нам нужно для
организации интерактивного редактирования через активные хотспоты ( 2д, 3д
скрипт). Назначение этих переменных будет понятно дальше.
3. 2D скрипт
Скрин 6 «2D скрипт»
По порядку:
project2 3,270,1
|
- мы хотим видеть на плане(2Д
скрипт отвечает за отрисовку объекта в плане) проекцию «сверху» 3D «содержимого»
(Подробности команды project2
можно найти в ркуоводстве по GDL).
|
hotspot2 0,0,12,L,128+1
hotspot2 L,0,13,L,2
hotspot2 0,0,14,L,3
|
- ставим «активный хотспот»(далее АС - активный спот), связанный с параметром L,
Который будет
использоваться при редактировании длины на плане, для редактирования в 3д
будет описан другой АС.
О синтаксисе описания АС расскажу в другой раз это отдельная тема.
Вообще АС – это ключевой момент интерактивности взаимодействия пользователя с
объектом в плане и 3д окне. Без АС GDL был бы убогим.
|
if ix1 then
hotspot2 0,0,1,x1,128+1
hotspot2 x1,0,2,x1,2
hotspot2 0,0,3,x1,3
endif
|
- при наличии паза 1 вешаем 2D АС на параметр Х1. Т.е. перетаскивая этот АС мы меняем
параметр X1.
Редактирование осуществляется: в плане, в соответствии со строками скрипта
параметров(в зависимости от inn):
0 пазов – хотспот на плане не будет отрисован (по условию if ix1 then..)
1 паз - values "x1" range
[0.001,L-0.001]
2,3 паза - values "x1" range
[0.001,x2-0.001]
|
Далее и до if is=1 then
|
- аналогичные действия и логика по пазу 2 и 3.
|
if is=1 then
text2 0,-0.5,"Привет Всем
кто живет с Архикадом!!!По поводу этого и других *.gsm обращайтесь - ICQ
195830974, sergstd@rambler.ru.Выкл это сообщение мона в менюхе
объекта."…
|
- иногда бывает полезно описать принцип того что делает скрипт,
простым человеческим языком. Особенно когда речь идет о «наколеночном»
программировании. Graphisoft не утруждает себя
мануалами по использованию GDL объектов из своих библиотек. При
достаточном опыте работы с GDL
объектами необходимость в мануале отпадает, все они реализуют конечный набор
функций. Тем не менее, когда у объекта есть особенности, неплохо бы уведомить
о них конечного пользователя. В нашем случае такая особенность описана в
строке:
text2 0,-2.5,”И последнее...когда
изменяете кол-во пазов в большую сторону(был 1 ставим 2) то хотспот 2-го паза
нужно искать рядом с первым пазом”
здесь описывается случай аналогичный рассмотренному выше - с
возможным вылетом паза за пределы бревна и автоматическим увеличением длины.
|
Скрин 7 «Вид элемента на плане – результат работы
2D скрипта»
4. 3D скрипт
Мысленно представим каким образом можно получить бревно с пазами. Очевидно что нужный результат - вычитание из объекта "бревно" объектов "паз".
Так как наш объект – результат выполнения операций CSG(см ссылки в конце) опишем группы объектов которые
будут операндами этих CSG-операций.
!
основная группа, бревно:
GROUP "brevno"
!
повернем СК на 90 градусов вокруг оси У, это нужно чтобы цилиндр
символизирующий бревно
располагался горизонтально (по умолчанию ось цилиндра совпадает с осью Z, см. синтаксис GDL - ссылки в конце)
ROTY 90
! Вот
он наш цилиндр-«заготовка»
CYLIND L,Rb
!
завершаем описание группы «brevno», из которой будем вычитать пазы, получашки, делать срезы концов…
ENDGROUP
! 3D АС вешаем на параметр-длину нашего бревна.
hotspot 0,0,0,12,L,128+1
hotspot L,0,0,13,L,2
hotspot 0,0,0,14,L,3
! если
есть паз 1 то вешаем 3D АС на
параметр-координату этого паза(Х1), вдоль нашего бревна.
if ix1 then
hotspot 0,0,0,1,x1,128+1
hotspot x1,0,0,2,x1,2
hotspot 0,0,0,3,x1,3
endif
! тоже
самое паз 2
if ix2 then
hotspot 0,0,0,4,x2,128+1
hotspot x2,0,0,5,x2,2
hotspot 0,0,0,6,x2,3
endif
! тоже
самое паз 3
if ix3 then
hotspot 0,0,0,7,x3,128+1
hotspot x3,0,0,8,x3,2
hotspot 0,0,0,9,x3,3
endif
! Пара
полезных ПС(пассивных спотов), удобно задавать при редактировании перемещения от
конкретных точек элемента, также нужно за что-то и зеркалить элемент. Это
немаловажный момент – дать конечному пользователю нужное количество ПС, для
удобной работы с элементом.
hotspot 0,0,0
hotspot L,0,Rb
!
Группа пазов которая формируется в зависимости от заданного количества пазов.
GROUP "paz"
!
смещаем СК в положение где должен быть расположен «цилиндр-операнд», который
будем вычитать из «brevno», по сути «стек трансформаций» содержит обычные афинные
преобразования 3D, которые применяются к координатам команд-объектов (в
нашем случае к «операндам-цилиндрам»).
ADDZ -2*Rb*cos(30)
ROTY 90
! если
задан продольный паз - формируем цилиндр-операнд для такого вычитания
if pazz then
CYLIND L,Rb
endif
!
удаляем из стека трансформаций последние две операции - ADDZ -2*Rb*cos(30) и ROTY 90
del 2
!
настраиваем СК для вычитания поперечных пазов и получашек.
ADDZ -Rb
ADDY 2*Rb
ROTX 90
!
создаем «цилиндр-операнд» результатом вычитания которого из бревна будет
получашка вначале.
if xb then
CYLIND 500,Rc
endif
! получашка
в конце
if xe then
addx L
CYLIND 500,Rc
del 1
endif
! поперечные
пазы
if ix1 then
ADDX X1
CYLIND 500,Rc
del 1
endif
if ix2 then
addx X2
CYLIND 500,Rc
del 1
endif
if ix3 then
addx X3
CYLIND 500,Rc
del 1
endif
!
очищаем стек преобразований.
DEL TOP
! закрываем
группу «пазы»
ENDGROUP
!
Вычитаем из бревна заданные пазы
result_=SUBGROUP("brevno","paz")
! если
«срезы» бревна не заданы – кидаем наш результат в модель и…
if B_A=0 & B_b=0 then
PLACEGROUP result_
! шагаем
к выходу
goto 1
endif
! Если
задан срез в начале, то выполняем его при помощи cutplane
if B_A=1 & B_b=0 then
hotspot Rb*tan(ab),0,Rb
rotz 90
cutplane -ab
del 1
! срезать будем
с результата вычитания, т.е. с «бревно-пазы», поэтому располагаем наш результат
м/у cutplane-cutend.
PLACEGROUP result_
cutend
! шагаем
к выходу
goto 1
endif
!
тоже, срез на конце бревна
if B_A=0 & B_b=1 then
addx L
hotspot -Rb*tan(ae),0,Rb
rotz 90
cutplane ae
del 2
PLACEGROUP result_
cutend
goto 1
endif
!
тоже, срез в начале и конце бревна
if B_A=1 & B_b=1 then
hotspot Rb*tan(ab),0,Rb
rotz 90
cutplane -ab
del 1
addx L
hotspot -Rb*tan(ae),0,Rb
rotz 90
cutplane ae
del 2
PLACEGROUP result_
cutend
cutend
goto 1
endif
! результат
вычитания и усечений уже размещен, необходимости в группах больше нет – удаляем
их.
1:
KILLGROUP "brevno"
KILLGROUP "paz"
!Очищаем
«стек преобразований»
del top
смотрим на результат.
Скрин 8 «Вид элемента в 3Д окне –
результат работы 3D скрипта»
А так может выглядеть
сруб «собранный из»:
Скрин 9 «На практике»
Ссылки по теме:
1.
http://en.wikipedia.org/wiki/Constructive_solid_geometry
- конструктивная геометрия это...интересно.
2.
http://compgraphics.info/3D/3d_affine_transformations.php
- об афинных преобразованиях (лучше один раз увидеть).
Желаю успехов в GDL!
Спасибо большое за такое подробное изложение. Было приятно ознакомиться, жду продолжения!
ОтветитьУдалить