Особенности 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

Предлагаю Вам самостоятельно выполнить коды и проанализировать результат.
Я человек сильно ленивый, и постоянно держать в голове каким объектам надо задавать координаты в мировой системе, а каким - в текущей, мне было неинтересно. Намного проще показалось все время задавать координаты в мировой системе и только потом, если надо, выполнять их преобразование по текущим условиям.
Это мы пока работали только с графикой. Неграфическую информацию разберем немного позже - и так текста много получилось.

Размещено в Код LISP · Метки: ,



Комментарии

Есть 4 коммент. к “Особенности vla-функций и их применения”
  1. Do$ пишет:

    А если взять объект посложнее? Например, окружность?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     (entmakex '((0 . "CIRCLE")
                (10 100. 10. 100.)
                (40 . 60.)
                (210 -0.671718 -0.251372 0.696855)
                )
              ) ;_ end of entmakex


     (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

    Разными будут координаты центров окружностей.

    Они и в кодах тоже разные! Где entmakex - (10 100. 10. 100.), vla - (vlax-3d-point '(100. 0. 0.))

  2. Кулик Алексей aka kpblc пишет:

    Да, опечатался. Но дело в том, что замена центра на '(100. 10. 100.) ситуацию не изменит:

    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
    (defun test (/ center rad normal ent vla)

      (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.
    Или я где-то ошибся? Прошу поправить, если это не так.

  3. Do$ пишет:

    Конечно, просто опечатка! Не совпадают центры окружностей, полученных entmakex и vla. Долго пытался понять почему так, методом проб и ошибок выяснил, что в entget-списке окружности координаты центра хранятся в ситеме координат этой окружности.

  4. Кулик Алексей aka kpblc пишет:

    Это понятно :) Проблема в том, что для некоторых объектов координаты задаются в мировой системе; для некоторых - в системе объекта. А эту "некоторость" приходится постоянно держать в голове.

Поделитесь своим мнением


Я не робот.