Особенности vla-функций и их применения
Если Вы (или Ваши клиенты) работаете только в мировой системе координат; если создаваемые Вами объекты никогда не будут иметь координату Z, отличную от 0; если Вы не хотите задумываться о трехмерном проектировании; если... Короче, если у Вас пляжные условия работы, то этот пост Вам неинтересен будет, скорее всего.
Если же Вы вынуждены работать (хотя бы иногда) не в мировой системе координат; если Ваши пользователи иногда (будем милосердными) устанавливают Elevation не 0 - то сейчас мы и будем говорить о проблемах работы в таких условиях и не всегда очевидными особенностями применения ActiveX.
Сначала немного теории.
Известно, что любой примитив AutoCAD (я не рассматриваю вертикальные решения типа AutoCAD Architecture и примитивы пользовательских типов - таких, например, как штампы и выноски люто любимого СПДС GraphiCS) можно представить как в виде списка, так и в виде объекта (первые "ласточки" были показаны в Стилях программирования и ссылках, указанных там).
Создадим, например, отрезок с разными установками систем координат:
1 2 3 4 5 6 | (entmakex '((0 . "LINE") (10 0. 0. 0.) (11 100. 10. 100.) (210 1. 0. 0.) ) ) ;_ end of entmakex |
1 2 3 4 5 6 | (entmakex '((0 . "LINE") (10 0. 0. 0.) (11 100. 10. 100.) (210 0. 0. 1.) ) ) ;_ end of entmakex |
1 2 3 4 5 6 7 8 9 10 | (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 '(1. 0. 0.)) ) ;_ end of vla-put-normal |
1 2 3 4 5 6 7 8 9 10 | (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.) в мировой системе координат (то, что будет показываться в окне свойств при немировой системе координат - вопрос отдельный).
А если взять объект посложнее? Например, окружность?
1 2 3 4 5 6 | (entmakex '((0 . "CIRCLE") (10 100. 10. 100.) (40 . 60.) (210 -0.671718 -0.251372 0.696855) ) ) ;_ end of entmakex |
1 2 3 4 5 6 7 8 9 10 11 12 | (vla-put-normal (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 - обычную плоскую полилинию и сравним коды ее создания. Для более полной иллюстрации будем работать внутри немировой системы координат.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | (defun lispru-entmake-pline () (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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | (defun lispru-vla-pline (/ pline coords) (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 |
Если запустить оба этих кода, результат будет одинаков. И координаты для полилиний задаются в системе координат создаваемого объекта (то есть полилинии).
Проведем немного другой эксперимент: создадим такую же полилинию, но без явного указания нормали, а просто построим пользовательскую систему координат (ну, например, как раз по созданной чуть ранее полилинии) через стандартую команду:
1 2 3 4 5 6 7 | Command: _.ucs 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 |
Поехали:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | (defun lispru-entmake-pline-no-normal () (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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | (defun lispru-vla-pline-no-normal (/ pline coords) (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 |
Предлагаю Вам самостоятельно выполнить коды и проанализировать результат.
Я человек сильно ленивый, и постоянно держать в голове каким объектам надо задавать координаты в мировой системе, а каким - в текущей, мне было неинтересно. Намного проще показалось все время задавать координаты в мировой системе и только потом, если надо, выполнять их преобразование по текущим условиям.
Это мы пока работали только с графикой. Неграфическую информацию разберем немного позже - и так текста много получилось.
Они и в кодах тоже разные! Где entmakex - (10 100. 10. 100.), vla - (vlax-3d-point '(100. 0. 0.))
Да, опечатался. Но дело в том, что замена центра на '(100. 10. 100.) ситуацию не изменит:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
(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-списке окружности координаты центра хранятся в ситеме координат этой окружности.
Это понятно Проблема в том, что для некоторых объектов координаты задаются в мировой системе; для некоторых - в системе объекта. А эту "некоторость" приходится постоянно держать в голове.