Особенности vla-функций и их применения
Если Вы (или Ваши клиенты) работаете только в мировой системе координат; если создаваемые Вами объекты никогда не будут иметь координату Z, отличную от 0; если Вы не хотите задумываться о трехмерном проектировании; если… Короче, если у Вас пляжные условия работы, то этот пост Вам неинтересен будет, скорее всего.
Если же Вы вынуждены работать (хотя бы иногда) не в мировой системе координат; если Ваши пользователи иногда (будем милосердными) устанавливают Elevation не 0 – то сейчас мы и будем говорить о проблемах работы в таких условиях и не всегда очевидными особенностями применения ActiveX.
Сначала немного теории.
Известно, что любой примитив AutoCAD (я не рассматриваю вертикальные решения типа AutoCAD Architecture и примитивы пользовательских типов – таких, например, как штампы и выноски люто любимого СПДС GraphiCS) можно представить как в виде списка, так и в виде объекта (первые “ласточки” были показаны в Стилях программирования и ссылках, указанных там).
Создадим, например, отрезок с разными установками систем координат:
(10 0. 0. 0.)
(11 100. 10. 100.)
(210 1. 0. 0.)
)
) ;_ end of entmakex
(10 0. 0. 0.)
(11 100. 10. 100.)
(210 0. 0. 1.)
)
) ;_ end of entmakex
(vla-addline
(vla-get-modelspace
(vla-get-activedocument (vlax-get-acad-object))
) ;_ end of vla-get-modelspace
(vlax-3d-point '(0. 0. 0.))
(vlax-3d-point '(100. 10. 100.))
) ;_ end of vla-addline
(vlax-3d-point '(1. 0. 0.))
) ;_ end of vla-put-normal
(vla-addline
(vla-get-modelspace
(vla-get-activedocument (vlax-get-acad-object))
) ;_ end of vla-get-modelspace
(vlax-3d-point '(0. 0. 0.))
(vlax-3d-point '(100. 10. 100.))
) ;_ end of vla-addline
(vlax-3d-point '(-0.671718 -0.251372 0.696855))
) ;_ end of vla-put-normal
Как бы мы ни старались, что бы мы ни делали,- все равно создаваемый объект будет иметь координаты начала ‘(0. 0. 0.) и конца ‘(100. 10. 100.) в мировой системе координат (то, что будет показываться в окне свойств при немировой системе координат – вопрос отдельный).
А если взять объект посложнее? Например, окружность?
(10 100. 10. 100.)
(40 . 60.)
(210 -0.671718 -0.251372 0.696855)
)
) ;_ end of entmakex
(vla-addcircle
(vla-get-modelspace
(vla-get-activedocument
(vlax-get-acad-object)
) ;_ end of vla-get-ActiveDocument
) ;_ end of vla-get-ModelSpace
(vlax-3d-point '(100. 0. 0.))
60
) ;_ end of vla-AddCircle
(vlax-3d-point '(-0.671718 -0.251372 0.696855))
) ;_ end of vla-put-normal
Попробуйте запустить первый и второй коды по созданию окружности. Казалось бы (по крайней мере при первом рассмотрении) коды одинаковы. Ну, за исключением того, что через enamakex сразу еще и цвет задается. А вот результат будет совершенно различен.
Нет, нормали объектов будут одинаковыми. Разными будут координаты центров окружностей. И такое будет не только с окружностями, но и, например, с текстами. И еще с массой примитивов AutoCAD.
Обратите внимание: задаваемые координаты для ActiveX-представления (да и возвращаемые тоже), насколько я помню, всегда имеют значения для мировой системы координат независимо ни от чего. Для entmake- и entmakex-обработок необходимо координаты задавать уже в нужной системе координат (по крайней мере для объектов, для которых это критично).
Это все хорошо, только примитивы были элементарными. Возьмем, например, LWPOLYLINE – обычную плоскую полилинию и сравним коды ее создания. Для более полной иллюстрации будем работать внутри немировой системы координат.
(entmakex '((0 . "LWPOLYLINE")
(100 . "AcDbEntity")
(100 . "AcDbPolyline")
(90 . 12)
(70 . 1)
(43 . 0.0)
(38 . 0.0)
(39 . 0.0)
(10 1520.0 450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 620.0 0.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 620.0 900.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1520.0 450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1070.0 1350.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1970.0 1350.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1520.0 450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 2420.0 900.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 2420.0 0.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1520.0 450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1970.0 -450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1070.0 -450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(210 -0.671718 -0.251372 0.696855)
)
) ;_ end of entmakex
) ;_ end of defun
(vl-load-com)
(setq coords '((1520.0 450.0)
(620.0 0.0)
(620.0 900.0)
(1520.0 450.0)
(1070.0 1350.0)
(1970.0 1350.0)
(1520.0 450.0)
(2420.0 900.0)
(2420.0 0.0)
(1520.0 450.0)
(1970.0 -450.0)
(1070.0 -450.0)
)
coords (apply (function append) coords)
pline (vla-addlightweightpolyline
(vla-get-modelspace
(vla-get-activedocument
(vlax-get-acad-object)
) ;_ end of vla-get-activedocument
) ;_ end of vla-get-modelspace
(vlax-make-variant
(vlax-safearray-fill
(vlax-make-safearray
vlax-vbdouble
(cons 0 (1- (length coords)))
) ;_ end of vlax-make-safearray
coords
) ;_ end of vlax-safearray-fill
) ;_ end of vlax-make-variant
) ;_ end of vla-addlightweightpolyline
) ;_ end of setq
(vla-put-closed pline :vlax-true)
(vla-put-normal
pline
(vlax-3d-point '-0.671718 -0.251372 0.696855)
) ;_ end of vla-put-Normal
pline
) ;_ end of defun
Если запустить оба этих кода, результат будет одинаков. И координаты для полилиний задаются в системе координат создаваемого объекта (то есть полилинии).
Проведем немного другой эксперимент: создадим такую же полилинию, но без явного указания нормали, а просто построим пользовательскую систему координат (ну, например, как раз по созданной чуть ранее полилинии) через стандартую команду:
Current ucs name: *WORLD*
Specify origin of UCS or [Face/NAmed/OBject/Previous/View/World/X/Y/Z/ZAxis]
<World>: _ob
Select object to align UCS:
Command: _plan
Enter an option [Current ucs/Ucs/World] <Current>: _w
Поехали:
(entmakex '((0 . "LWPOLYLINE")
(100 . "AcDbEntity")
(100 . "AcDbPolyline")
(90 . 12)
(70 . 1)
(43 . 0.0)
(38 . 0.0)
(39 . 0.0)
(10 1520.0 450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 620.0 0.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 620.0 900.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1520.0 450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1070.0 1350.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1970.0 1350.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1520.0 450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 2420.0 900.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 2420.0 0.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1520.0 450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1970.0 -450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(10 1070.0 -450.0)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
)
) ;_ end of entmakex
) ;_ end of defun
(vl-load-com)
(setq coords '((1520.0 450.0)
(620.0 0.0)
(620.0 900.0)
(1520.0 450.0)
(1070.0 1350.0)
(1970.0 1350.0)
(1520.0 450.0)
(2420.0 900.0)
(2420.0 0.0)
(1520.0 450.0)
(1970.0 -450.0)
(1070.0 -450.0)
)
coords (apply (function append) coords)
pline (vla-addlightweightpolyline
(vla-get-modelspace
(vla-get-activedocument
(vlax-get-acad-object)
) ;_ end of vla-get-activedocument
) ;_ end of vla-get-modelspace
(vlax-make-variant
(vlax-safearray-fill
(vlax-make-safearray
vlax-vbdouble
(cons 0 (1- (length coords)))
) ;_ end of vlax-make-safearray
coords
) ;_ end of vlax-safearray-fill
) ;_ end of vlax-make-variant
) ;_ end of vla-addlightweightpolyline
) ;_ end of setq
(vla-put-closed pline :vlax-true)
pline
) ;_ end of defun
Предлагаю Вам самостоятельно выполнить коды и проанализировать результат.
Я человек сильно ленивый, и постоянно держать в голове каким объектам надо задавать координаты в мировой системе, а каким – в текущей, мне было неинтересно. Намного проще показалось все время задавать координаты в мировой системе и только потом, если надо, выполнять их преобразование по текущим условиям.
Это мы пока работали только с графикой. Неграфическую информацию разберем немного позже – и так текста много получилось.
Материалы для проектирования, работы и разработки (и не только в AutoCAD)
Они и в кодах тоже разные! Где entmakex – (10 100. 10. 100.), vla – (vlax-3d-point ‘(100. 0. 0.))
Да, опечатался. Но дело в том, что замена центра на ‘(100. 10. 100.) ситуацию не изменит:
(setq center '(100. 10. 100.)
rad 60.
normal '(-0.671718 -0.251372 0.696855)
ent (entmakex (list '(0 . "CIRCLE")
(cons 10 center)
(cons 40 rad)
'(62 . 1)
(cons 210 normal)
) ;_ end of list
) ;_ end of entmakex
vla (vla-addcircle
(vla-get-modelspace
(vla-get-activedocument
(vlax-get-acad-object)
) ;_ end of vla-get-ActiveDocument
) ;_ end of vla-get-ModelSpace
(vlax-3d-point center)
rad
) ;_ end of vla-addcircle
) ;_ end of setq
(vla-put-color vla 2)
(vla-put-normal vla (vlax-3d-point normal))
(foreach item (list (cons "entmakex" ent)
(cons "vla" (vlax-vla-object->ename vla))
) ;_ end of list
(princ
(strcat "\n ** "
(car item)
" : "
(vl-princ-to-string
(vl-remove-if
(function (lambda (x) (member (car x) '(-1 5 330))))
(entget (cdr item))
) ;_ end of vl-remove-if
) ;_ end of vl-princ-to-string
) ;_ end of strcat
) ;_ end of princ
) ;_ end of foreach
(princ)
) ;_ end of defun
И в ком.строке сравнить группу 10.
Или я где-то ошибся? Прошу поправить, если это не так.
Конечно, просто опечатка! Не совпадают центры окружностей, полученных entmakex и vla. Долго пытался понять почему так, методом проб и ошибок выяснил, что в entget-списке окружности координаты центра хранятся в ситеме координат этой окружности.
Это понятно
Проблема в том, что для некоторых объектов координаты задаются в мировой системе; для некоторых – в системе объекта. А эту “некоторость” приходится постоянно держать в голове.