| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > На заметку программистам

На заметку программистам

Ответ
Поиск в этой теме
Непрочитано 05.06.2007, 07:28 #1
На заметку программистам
ShaggyDoc
 
Thượng Tá Quân Đội Nhân Dân Việt Nam
 
44d32'44"С, 33d26'51"В
Регистрация: 14.03.2005
Сообщений: 13,381

Сначала присказка.

В системе ruCAD очень часто используются блоки, расположенные как в отдельных файлах, так и в библиотеках блоков.

Значительная часть блоков используется для рисования масштабируемых символов - условных обозначений, таблиц и т.п.

Такие исходные блоки созданы, как правило, с единицей рисунка миллиметр, а размеры их такие, какие должны быть в миллиметрах на бумаге. Например, если блок, изображающий колодец, должен изображаться на бумаге в виде кружка (с какой-то внутренней начинкой) диаметром 2 мм, то он имеет размер 2 единицы.

Вставка блоков производится специальными программами с выбором из иллюстрированного дерева меню. Пользователь, собственно, и не знает о том, что вставляется блок. Ко вставке часто добавляется и дополнительное рисование. Блоки автоматически масштабируются и, при необходимости, поворачиваются.

Особенность ruCAD также в том, что возможен выбор между единицами рисунка (метры или миллиметры) и выбор масштаба печати модели. Как правило, здания рисуются с единицами миллиметр, а топография, генпланы, сети - с единицами метр.

Выбор масштаба и единиц осуществляется в специальном диалоговом окне и эти параметры сохраняются в собственном словаре рисунка. При выборе масштаба и единиц автоматически производится установка всех системных переменных в требуемые значения.

При работе с блоками (или другими масштабируемыми символами) происходит автоматическое масштабирование по следующему алгоритму:

1. Если блок вставляется в модель на вкладке Model, он масштабируется в соответствии с установленным масштабом печати модели
2. Если блок вставляется в модель на любом Layout через Vport, он масштабируется в соответствии с масштабом Vport
3. Если блок вставляется в пространство листа, он масштабируется с учетом собственного размера и единиц рисунка. Здесь учитывается, что в модели единицы могут быть миллиметры или метры, а в листе единицы всегда миллиметры.
4. Одни и те же блоки могут использоваться и в чертежах, сделанных в миллиметрах, и в чертежах, сделанных в метрах. Дюймы и прочие "попугаи" мы не используем из прынцыпа ("а че они негров линчуют"), хотя сделать это несложно.

Вот так работа выполнялась много лет, в версиях AutoCAD от 10 до 2007, созданы десятки тысяч чертежей как зданий, так и топографии, и все было нормально.

Теперь "сказка".

Вдруг, при работе с наружными сетями (единица рисунка "метр") обнаруживается, что блоки вставляются в неправильном масштабе - в 1000 раз меньше, чем нужно. Ни одна программа не менялась, но значительная часть стала работать неправильно. Вставка блоков, как правило, производится объектными методами, и лишь изредка, при интерактивной работе, используется (vl-cmdf "_.INSERT" ...)

Не столь давно пришлось возвращаться к "командной" технологии по двум причинам:
1. Необходимость работы в 3D, где, в хитрых ПСК, с объектами практически невозможно правильно работать.
2. Перспективное портирование в BricsCAD.

Расследование показало, что ошибка происходит при работе команды INSERT. Значение масштаба блока в нее передается правильное, а вот сама команда масштабирует блок по своему усмотрению. Но ранее этого никогда не было, или я этого не замечал.

Допрос 3-й степени выявил, что теперь команда INSERT работает с учетом системной переменной INSUNITS. AutoCAD сам пытается масштабировать блок, но делает это не всегда правильно. Такое поведение понятно и логично, когда блок перетаскивается вручную из DesignCenter или из палитры. Это действительно значительно облегчает ручную работу, но при автоматическом масштабировании происходят ошибки. Этот нюанс не документирован, или документирован намеком. Для режима "командной строки" правильнее было бы, чтобы переданные масштабы принимались безо всякой корректировки, а "вычисленные", в лучшем случае предлагались бы в качестве значения по умолчанию. Но это мое мнение, на которое Аутодеск наплевать.

Системную переменную INSUNITS ruCAD устанавливает при выборе единиц. Сделано это для того, чтобы чертеж, попавший в чужие руки (или в другую программу) был сделан "как надо". Если единицы рисунка - метр, то INSUNITS=6, а если единицы миллиметр, то INSUNITS=4. Это пригодится и на тот случай, если этот чертеж будет вставляться вручную.

В результате пришлось откорректировать несколько библиотечных функций вставки блоков - перед вызовом (vl-cmdf "_.INSERT" ...) устанавливать INSUNITS=4 (метр), а после завершения команды - восстанавливать прежнее значение. Так сделано потому, что все блоки созданы с единицами - миллиметр. Разумеется, после этого все программы заработали правильно.

"Вот такой гутен-морген, значить, получился с этим нюансом", как говаривал бессмертный капитан Фома Фомич Фомичев.

Надеюсь, эта заметка позволит программистам избежать таких "нюансов" в своих программах.
Просмотров: 17654
 
Непрочитано 05.06.2007, 08:25
#2
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,853


Заметка интересная, позвольте несколько встречных вопросов.
1. Вместо _-insert можно попробовать использовать ObjectDBX-доступ к библиотекам блоков и через vla-copyobjects копировать описания блоков (кстати, в CADWare я именно так и сделал). А собственно вставку выполнять старой незаменимой _change.
2. Возможно ли пройтись по всем блокам (я имею в виду библиотеки блоков) и установить блоки "unitless"? Если да, то, наверное, это будет более удобно. Правда, я не особо представляю себе, как быть с файлами-блоками...
Добавлено: Ай-яй-яй, моя вина, не посмотрел. Файлы-то тоже можно сделать unitless Так что часть вопроса 2 снимается
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 05.06.2007, 09:26
#3
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,381


Цитата:
Сообщение от Кулик Алексей aka kpblc
... А собственно вставку выполнять старой незаменимой _change.
Мультивставку визуальную мы с Alaspher-ом десять лет уже "улучшаем". Функция давно уже сплошной сборник "особенностей" различных версий AutoCAD. Там такой винегрет из объектных методов, enmake и команд.... При работе на плоскости все работает. Но вот при переходе в 3D появилось еще больше сложностей. А работать надо, причем в любой ПСК. Пока пришлось вернуться к INSERT. Причем, очень примитивно - вместо цикла вставки с визуальным "висением" смасштабированного изображения блока на курсоре, сделал тупой запрос о повторении вставки. Очень неэстетично, "зато дешево, надежно и практично". Просто не было времени на эксперименты. Можешь включиться, возможно придет в голову свежая идея.

Кроме того - впереди Brics. Какие там особенности встретятся - еще не знаю.

Цитата:
2. Возможно ли пройтись по всем блокам (я имею в виду библиотеки блоков) и установить блоки "unitless"?
По своим библиотекам пройтись-то не проблема. Ну и что? Для них ведь будет установлен INSUNITS как для "мм". А вставлять надо то в чертеж с "мм", то с "м". Команда при этом будет все равно самодеятельно перемасштабировать.

Кроме того, моих-то библиотек уже меньше, чем пользовательских. А в них может быть что угодно. Берут библиотеки из всех версий, от фирм. Так что решение должно быть независимым от свойств файла с блоками.
ShaggyDoc вне форума  
 
Непрочитано 05.06.2007, 10:50
#4
Zouss


 
Регистрация: 14.03.2006
Сообщений: 863


Цитата:
вместо цикла вставки с визуальным "висением" смасштабированного изображения блока на курсоре, сделал тупой запрос о повторении вставки.
а что помешало перед циклой вставки изменить INSUNITS в нужное значение, а потом восстановить обратно - по моему этот рецепт снимет все ваши проблемы одним махом??
Zouss вне форума  
 
Автор темы   Непрочитано 05.06.2007, 11:06
#5
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,381


Цитата:
Сообщение от Zouss
Цитата:
вместо цикла вставки с визуальным "висением" смасштабированного изображения блока на курсоре, сделал тупой запрос о повторении вставки.
а что помешало перед циклой вставки изменить INSUNITS в нужное значение, а потом восстановить обратно - по моему этот рецепт снимет все ваши проблемы одним махом??
Ну, для команды я так и сделал. Об этом написано в первом посте. Здесь речь была о другом - о мультивставке блока. Это большой и сложный код, команда INSERT в нем не использовалась. Ее пришлось применить из-за перехода к 3D.
ShaggyDoc вне форума  
 
Непрочитано 05.06.2007, 11:21
#6
Zouss


 
Регистрация: 14.03.2006
Сообщений: 863


прошу прощения - слишком бегло читал и то, что проблему вы решили попросту пропустил...
интересная у вас работа, аж завидно
Zouss вне форума  
 
Непрочитано 05.06.2007, 11:36
#7
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,992


У себя в своих блоках после всех эих непонятных перемасштабирований устанвил Insunits в безразмерный.
как-то писал код для перемасштабирования
так вот смутно оттуда помню, для того, чтобы Автокад не перемасштабировал блок, нужно при Insunits=0 менять свойства
XEffectiveScaleFactor XScaleFactor
YEffectiveScaleFactor YScaleFactor
ZEffectiveScaleFactor ZScaleFactor
именно в таком порядке, сначала XEffectiveScaleFactor=1 потом XScaleFactor=1 потом XScaleFactor=нужное
Код:
[Выделить все]
;Запоминаем свойства
(setq prop (mapcar
             '(lambda (x)
                (if (vlax-property-available-p item x)
                  (vlax-get-property item x)
                  1
                ) ;_ end of if
              ) ;_ end of LAMBDA
             '(XEffectiveScaleFactor
               YEffectiveScaleFactor
               ZEffectiveScaleFactor
              )
           ) ;_ end of mapcar
) ;_ end of setq
;Восстанавливаем
    (setvar "INSUNITS" 0)
;Сначала устанавливаем XEffectiveScaleFactor XScaleFactor и т.д в 1 ИМЕННО в ТАКОМ ПОРЯДКЕ
    (mapcar '(lambda (x)
               (if (vlax-property-available-p item x)
                 (vlax-put-property item x 1)
               ) ;_ end of if
             ) ;_ end of lambda
            '(XEffectiveScaleFactor     XScaleFactor
              YEffectiveScaleFactor     YScaleFactor
              ZEffectiveScaleFactor     ZScaleFactor
             )
    ) ;_ end of mapcar
;Затем устанавливаем XScaleFactor в нужное
        (mapcar '(lambda (x y)
                   (if (vlax-property-available-p item x)
                     (vlax-put-property item x y)
                   ) ;_ end of if
                 ) ;_ end of lambda
                '(XScaleFactor YScaleFactor ZScaleFactor)
                prop
        ) ;_ end of mapcar
Хотя давно это было, мог чего-то и забыть

Последний раз редактировалось VVA, 19.09.2015 в 12:05.
VVA вне форума  
 
Автор темы   Непрочитано 05.06.2007, 14:03
#8
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,381


>VVA
Это не тот случай. Надо не свойства вставленного блока менять, а иметь визуально видимый, предварительно смасштабированный блок "на курсоре", в момент запроса точки вставки, но до ее указания. Чтобы юзер видел, что и куда он вставляет. При этом еще у блока, возможно, есть атрибуты. Возможно, его еще придется повернуть. И все это в любой ПСК, в том числе в 3D.

Сделать это можно только через command. С объектными методами проблем нет - какой масштаб задали, тот и будет. Но для объекта надо сначала запросить и передать точку, и в момент запроса точки блок не виден.
ShaggyDoc вне форума  
 
Непрочитано 05.06.2007, 14:05
#9
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,853


Ээээ... Уважаемые, ShaggyDoc & VVA, я считаю вас своими учителями, но позвольте и ученику высказаться. Почему забыли про INSUNITSDEFSOURCE и INSUNITSDEFTARGET? Я, конечно, понимаю, что у меня вставка блока сейчас отработана только на 2D, но (обнаглею) посмотрите мой вариант вставки блока:
Код:
[Выделить все]
(defun _kpblc-block-insert-low-level (block-name  lst         /
                                      res         x           y
                                      z           ang         msg_pt
                                      msg_ang     do_insert   ins_point
                                      tmp_angle   tmp_block   unnamed_block
                                      cur_layer   is_attr     loc:subst
                                      exp_block   put_point
                                      )

                                     ;|
*    Универсальная вставка блока по указанным параметрам. Описание блока уже
* должно быть определено в файле.
*    Параметры вызова:
*	block-name	имя блока
*	lst		список вызова вида:
      '(("pt" . <ТочкаВставки>)		; точка вставки блока. nil ->
      		; определяется пользователем
	("normal" . '(0. 0. 1.))	; Устанавливаемая normal блока. Не
		; используется, пока не решена проблема со вставкой не в мировой
		; системе координат
		; nil -> текущая
	("msg_pt" . "Точка вставки")	; приглашение для определения точки вставки.
		; Не используется, если точка определена заранее.
		; nil -> "Укажите точку вставки <Отмена> : "
	("msg_ang" . "Угол поворота")	; приглашение для определения угла наклона
		; nil -> "Укажите угол поворота <0.0> : "
	("x" . 1.)			; масштаб по оси Х. nil -> текущий
	("y" . 1.)			; масштаб по оси Y. nil -> брать с x
	("z" . 1.)			; масштаб по Z. nil -> брать с x
	("ang" . 0.)			; угол поворота блока. nil -> определяется
		; пользователем после вставки.
	("multi" . t)			; Вставлять один раз (nil либо опущено)
		; или несколько (t). Учитывается только при неопределенном
		; параметре "pt".
	("where" . <Куда вставлять>)	; vla-указатель на пространство, куда
		; вставлять. nil -> активное пространство
	("layer" . <ИмяСлоя>)		; имя слоя, в который вставляется блок.
		; nil -> текущий. Слой при необходимости создается.
	("attrot" . t)			; поворачивать или нет следом за блоком
					; атрибуты. nil -> не поворачивать
					; t -> устанавливать углы поворотов
					; атрибутов как в описании блока
	)
*    Параметры msg_pt, msg_ang учитываются только если "where" = активное пространство
*    Параметр msg_pt не учитывается, если задан pt
* В противном случае ang = 0. и изменение угла поворота блока не выполняется.

* примеры вызова:
(_kpblc-block-insert-low-level "ВГП32-16" (list (cons "multi" t) (cons "x" 1.)))
|;
  (defun loc:subst (lst-new lst-old)
    ;; lst-new - список новых точечных пар
    ;; lst-old - модифицируемый список
    (vl-remove-if-not
      '(lambda (a) (cdr a))
      (append (vl-remove-if '(lambda (x) (cdr (assoc (car x) lst-new))) lst-old)
              lst-new
              ) ;_ end of append
      ) ;_ end of vl-remove-if-not
    ) ;_ end of defun


  (setq lst     (_kpblc-conv-list-to-pointlist (_kpblc-conv-list-to-lowcase lst))
        x       (cond ((cdr (assoc "x" lst)))
                      (t (_kpblc-scale-get-by-ent (cdr (assoc "where" lst))))
                      ) ;_ end of cond
        y       (cond ((cdr (assoc "y" lst)))
                      (t x)
                      ) ;_ end of cond
        z       (cond ((cdr (assoc "z" lst)))
                      (t x)
                      ) ;_ end of cond
        ang     (cond ((cdr (assoc "ang" lst)))
                      (t 0.)
                      ;; Вот здесь надо устанавливать не 0 наверное - при
                      ;; повернутой СК результат неверен.
                      ) ;_ end of cond
        msg_pt  (cond ((cdr (assoc "msg_pt" lst)))
                      (t "Укажите точку вставки <Отмена> : ")
                      ) ;_ end of cond
        msg_ang (cond ((cdr (assoc "msg_ang" lst)))
                      (t "Укажите угол поворота <0.0> : ")
                      ) ;_ end of cond
        ) ;_ end of setq
  (if (cdr (assoc "layer" lst))
    (_kpblc-error-sysvar-save
      (list
        (list
          "clayer"
          (if (tblobjname "layer" (cdr (assoc "layer" lst)))
            (cdr (assoc "layer" lst))
            (vla-get-name (_kpblc-layer-create (cdr (assoc "layer" lst))))
            ) ;_ end of if
          ) ;_ end of list
        ) ;_ end of list
      ) ;_ end of _kpblc-error-sysvar-save
    ) ;_ end of if
  (if (cdr (assoc "pt" lst))
    (progn
      (_kpblc-error-catch
        (function
          (lambda ()
            (setq res (vla-insertblock
                        (cond
                          ((cdr (assoc "where" lst)))
                          (t (_kpblc-get-active-space-obj))
                          ) ;_ end of cond
                        (vlax-3d-point (cdr (assoc "pt" lst)))
                        block-name
                        x
                        y
                        z
                        ang
                        ) ;_ end of vla-InsertBlock
                  ) ;_ end of setq
            (if (cdr (assoc "layer" lst))
              (vla-put-layer
                res
                (cond
                  ((cdr (assoc "layer" lst)))
                  (t
                   (vla-get-name
                     (_kpblc-layer-create (cdr (assoc "layer" lst)))
                     ) ;_ end of vla-get-name
                   )
                  ) ;_ end of cond
                ) ;_ end of vla-put-layer
              ) ;_ end of if
            (if (cdr (assoc "normal" lst))
              (vla-put-normal res (vlax-3d-point (cdr (assoc "normal" lst))))
              ) ;_ end of if
            (if (and (not (cdr (assoc "where" lst)))
                     (not (cdr (assoc "ang" lst)))
                     ) ;_ end of and
              (progn
                (princ msg_ang)
                (vl-cmdf "_.change"
                         (vlax-vla-object->ename res)
                         ""
                         ""
                         ""
                         pause
                         ) ;_ end of vl-cmdf
                ) ;_ end of progn
              ) ;_ end of if
            (setq res (list res))
            ) ;_ end of lambda
          ) ;_ end of function
        '(lambda (x)
           (_kpblc-error-print "_kpblc-block-insert-low-level" x)
          ) ;_ end of lambda
        ) ;_ end of _kpblc-error-catch
      ) ;_ end of progn
    (progn
      ;; Точка вставки не задана. Фактически повтор ruCAD'овской функции
      (setq do_insert t
            ins_point (_kpblc-get-point-offscreen)
            ) ;_ end of setq
      (if (setq
            tmp_block (car (_kpblc-block-insert-low-level
                             block-name
                             (loc:subst
                               (list (cons "pt" ins_point)
                                     (cons "ang"
                                           (cond ((cdr (assoc "ang" lst)))
                                                 (t 0.0)
                                                 ) ;_ end of cond
                                           ) ;_ end of cons
                                     (cons "where" nil)
                                     (cons "normal" '(0. 0. 1.))
                                     ) ;_ end of list
                               lst
                               ) ;_ end of loc:subst
                             ) ;_ end of setq
                           ) ;_ end of car
            ) ;_ end of setq
        (progn
          (setq unnamed_block
                 (vla-add (vla-get-blocks *kpblc-activedoc*)
                          (vlax-3d-point '(0. 0. 0.))
                          "*U"
                          ) ;_ end of vla-add
                ) ;_ end of setq
          (_kpblc-block-insert-low-level
            block-name
            (loc:subst
              (list (cons "pt" '(0. 0. 0.))
                    (cons "ang"
                          (cond ((cdr (assoc "ang" lst)))
                                (t 0.0)
                                ) ;_ end of cond
                          ) ;_ end of cons
                    (cons "where" unnamed_block)
                    (cons "normal" '(0. 0. 1.))
                    ) ;_ end of list
              lst
              ) ;_ end of loc:subst
            ) ;_ end of _kpblc-block-insert-low-level
          (setq is_attr (_kpblc-conv-value-to-bool
                          (vla-get-hasattributes tmp_block)
                          ) ;_ end of _kpblc-conv-value-to-bool
                ) ;_ end of setq
          (vla-erase tmp_block)
          ) ;_ end of progn
        (setq do_insert nil)
        ) ;_ end of if
      (while do_insert
        (setq tmp_block
               (handent
                 (vla-get-handle
                   (car (_kpblc-block-insert-low-level
                          (vla-get-name unnamed_block)
                          (loc:subst
                            (list (cons "pt" ins_point)
                                  (cons "x" 1.)
                                  (cons "y" 1.)
                                  (cons "z" 1.)
                                  ;;(cons "ang" 0.)
                                  ;; Строка вбита по рекомендации уважаемого
                                  ;; VVA
                                  ;; http://www.arcada.com.ua/forum/viewtopic.php?p=5989
                                  (cons "ang" (angle '(0 0 0) (getvar "UCSXDIR")))
                                  (cons "where" nil)
                                  ) ;_ end of list
                            lst
                            ) ;_ end of loc:subst
                          ) ;_ end of _kpblc-block-insert-low-level
                        ) ;_ end of car
                   ) ;_ end of vla-get-Handle
                 ) ;_ end of handent
              ) ;_ end of setq
        (princ msg_pt)
        (vl-cmdf "_.change" tmp_block "" "" pause "")
        (vl-catch-all-apply
          '(lambda ()
             (vla-put-insertionpoint
               (vla-item
                 (vla-item (vla-get-blocks
                             (vla-get-activedocument (vlax-get-acad-object))
                             ) ;_ end of vla-get-blocks
                           block-name
                           ) ;_ end of vla-item
                 0
                 ) ;_ end of vla-item
               (vlax-3d-point '(0 0 0))
               ) ;_ end of vla-put-InsertionPoint
             (mapcar
               'vla-update
               (_kpblc-conv-selset-to-vla (ssget "_X" '((0 . "INSERT"))))
               ) ;_ end of mapcar
             ) ;_ end of lambda
          ) ;_ end of vl-catch-all-apply
        (if (setq do_insert
                   (not (equal (setq
                                 put_point (trans (cdr (assoc 10 (entget tmp_block)))
                                                  tmp_block
                                                  0
                                                  ) ;_ end of trans
                                 ) ;_ end of setq
                               ins_point
                               1e-3
                               ) ;_ end of EQUAL
                        ) ;_ end of not
                  ) ;_ end of setq
          (progn
            (if (not (cdr (assoc "ang" lst)))
              (progn
                (princ msg_ang)
                (vl-cmdf "_.change" tmp_block "" "" "" pause)
                ) ;_ end of progn
              ) ;_ end of if
            (if do_insert
              (progn
                (setq exp_block (car (vlax-safearray->list
                                       (vlax-variant-value
                                         (vla-explode
                                           (vlax-ename->vla-object
                                             tmp_block
                                             ) ; _ end of
                                           ) ;_ end of vla-explode
                                         ) ;_ end of vlax-variant-value
                                       ) ;_ end of vlax-safearray->list
                                     ) ;_ end of car
                      ) ;_ end of setq
                (if (and (= (getvar "attreq") 1)
                         is_attr
                         ) ;_ end of and
                  (command "_.ddatte" (entlast))
                  ) ;_ end of if
                (vla-put-insertionpoint exp_block (vlax-3d-point put_point))
                (setq
                  res (append res
                              (list (vlax-ename->vla-object (entlast)))
                              ) ;_ end of append
                  ) ;_ end of setq
                ) ;_ end of progn
              ) ;_ end of if
            ) ;_ end of progn
          ) ;_ end of if
        (entdel tmp_block)
        (setq do_insert (and do_insert (cdr (assoc "multi" lst))))
        ) ;_ end of while
      ) ;_ end of progn
    ) ;_ end of if
  (foreach item res
    (mapcar
      '(lambda (att)
         ;; Конвертируем точки вставки
         (mapcar
           '(lambda (prop)
              (vl-catch-all-apply
                '(lambda (/ attdef)
                   (vlax-put-property
                     att
                     prop
                     (vlax-3d-point
                       (trans (vlax-safearray->list
                                (vlax-variant-value (vlax-get-property att))
                                ) ;_ end of vlax-safearray->list
                              (vlax-safearray->list
                                (vlax-variant-value
                                  (vla-get-normal
                                    (setq attdef
                                           ((lambda (lst_att)
                                              (vlax-for sub_ent
                                                        (vla-item (vla-get-blocks
                                                                    *kpblc-activedoc*
                                                                    ) ;_ end of vla-get-blocks
          ; _ end of
          ; vla-get-blocks
          ; _ end of
          ; vla-get-blocks
                                                                  (vla-get-name item)
                                                                  ) ; _ end of
          ; vla-item
                                                (if
                                                  (and
                                                    (= (strcase
                                                         (vla-get-objectname sub_ent)
                                                         t
                                                         ) ;_ end of strcase
                                                       "acdbattributedefinition"
                                                       ) ;_ end of =
                                                    (= (strcase
                                                         (vla-get-tagstring sub_ent)
                                                         t
                                                         ) ;_ end of strcase
                                                       (strcase
                                                         (vla-get-tagstring att)
                                                         ) ;_ end of strcase
                                                       ) ;_ end of =
                                                    ) ;_ end of and
                                                   (setq
                                                     lst_att (append lst_att
                                                                     (list sub_ent)
                                                                     ) ;_ end of append
          ; _ end of
          ; append
          ; _ end of
          ; append
                                                     ) ;_ end of setq
                                                   ) ;_ end of if
                                                ) ;_ end of vlax-for
                                              ) ;_ end of LAMBDA
                                            )
                                          ) ;_ end of setq
                                    ) ;_ end of vla-get-normal
                                  ) ;_ end of vlax-variant-value
                                ) ;_ end of vlax-safearray->list
                              (vlax-safearray->list
                                (vlax-variant-value (vla-get-normal item))
                                ) ;_ end of vlax-safearray->list
                              ) ;_ end of trans
                       ) ;_ end of vlax-3d-point
                     ) ;_ end of vlax-put-property
                   ) ;_ end of lambda
                ) ;_ end of vl-catch-all-apply
              ) ;_ end of lambda
           '("insertionpoint" "textalignmentpoint")
           ) ;_ end of mapcar
         (vla-put-normal att (vla-get-normal item))
         ) ;_ end of lambda
      (_kpblc-block-attr-get-pointer-mask item "*")
      ) ;_ end of mapcar
    ) ;_ end of foreach
  res
  ) ;_ end of defun
Пока проблем не вызывало. Может, для 3D и будет, хотя я не нашел. Библиотечные функции не знаю, показывать или нет?
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 05.06.2007, 15:11
#10
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от Кулик Алексей aka kpblc
Пока проблем не вызывало. Может, для 3D и будет, хотя я не нашел. Библиотечные функции не знаю, показывать или нет?
Ого, как я отстал от жизни...
Я пошел другим путем, на сервере есть база данных, в ней лежат списки для entmakex...
Короче, если блока нет в файле, то я его быстренько создаю.
Чтение идет из единой базы данных - это мне нравится.
Елпанов Евгений вне форума  
 
Непрочитано 05.06.2007, 17:09
#11
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,853


Все-таки выходной посередине рабочей недели расхолаживает У меня _-insert используется только в том случае, если библиотеку блоков никаким другим способом "не вскрыть" objdbx'ом. Вставка описания блока из библиотеки у меня происходит так (пока багов не встречал):
Код:
[Выделить все]
(defun _kpblc-block-insert-lib (block-lib-name block-name / odbx res blocks)
                               ;|
*    Вставка блока из указанного файла библиотеки в текущий файл. Если
* имя блока не указано, вставляется целиком *model-space* файла библиотеки
* Если файл библиотеки не найден либо в нем нет блока с таким именем,
* выдается соответствующее предупреждение.
*    Возвращает vla-указатель на вставленный блок. Если блок с таким именем
* в текущем файле уже есть, то возвращает vla-указатель на него
*    Параметры вызова:
*	block-lib-name	имя файла библиотеки блоков. Если путь не указан,
*			то берется из (_kpblc-dir-get-block-library)
*	block-name	имя блока. nil -> вставляется целиком
*    Примеры вызова:
(_kpblc-block-insert-lib "общие" "_обозначотметки")
|;

  (_kpblc-error-catch
    (function
      (lambda ()
        (setq block-lib-name (_kpblc-conv-value-to-string block-lib-name)
              block-lib-name (strcat
                               (if (= (vl-filename-directory block-lib-name) "")
                                 (_kpblc-dir-get-block-library)
                                 (_kpblc-dir-path-and-splash
                                   (vl-filename-directory block-lib-name)
                                   ) ;_ end of _kpblc-dir-path-and-splash
                                 ) ;_ end of if
                               (_kpblc-string-ext
                                 (vl-string-trim
                                   (if
                                     (= (vl-filename-directory block-lib-name) "")
                                      " "
                                      ""
                                      ) ;_ end of if
                                   (vl-filename-base block-lib-name)
                                   ) ;_ end of vl-string-trim
                                 "dwg"
                                 ) ;_ end of _kpblc-string-ext
                               ) ;_ end of strcat
              blocks         (vla-get-blocks *kpblc-activedoc*)
              ) ;_ end of setq
        (if (tblsearch "block"
                       (cond
                         (block-name)
                         (vl-filename-base block-lib-name)
                         ) ;_ end of cond
                       ) ;_ end of tblsearch
          (setq res (vla-item (vla-get-blocks
                                *kpblc-activedoc*
                                ) ;_ end of vla-get-blocks
                              (cond
                                (block-name)
                                (vl-filename-base block-lib-name)
                                ) ;_ end of cond
                              ) ;_ end of vla-item
                ) ;_ end of setq
          (progn
            (_kpblc-error-sysvar-save '(("sdi" 0)))
            (if (findfile block-lib-name)
              (progn
                (if (_kpblc-is-file-read-only block-lib-name)
                  (progn
                    (if (= (strcase
                             (_kpblc-dir-path-and-splash
                               (_kpblc-dir-get-root-temp)
                               ) ;_ end of _kpblc-dir-path-and-splash
                             ) ;_ end of strcase
                           (strcase (_kpblc-dir-path-and-splash
                                      (vl-filename-directory block-lib-name)
                                      ) ;_ end of _kpblc-dir-path-and-splash
                                    ) ;_ end of strcase
                           ) ;_ end of =
                      (progn
                        (kpblc-msg-alert
                          "Файл библиотеки открыт в этой или другой сессии AutoCAD!"
                          ) ;_ end of kpblc-msg-alert
                        (setq res nil)
                        ) ;_ end of progn
                      ) ;_ end of if
                    (vl-file-copy
                      block-lib-name
                      (strcat (_kpblc-dir-get-root-temp)
                              (vl-filename-base block-lib-name)
                              (vl-filename-extension block-lib-name)
                              ) ;_ end of strcat
                      ) ;_ end of vl-file-copy
                    (setq res (_kpblc-block-insert-lib
                                (strcat (_kpblc-dir-get-root-temp)
                                        (vl-filename-base block-lib-name)
                                        (vl-filename-extension block-lib-name)
                                        ) ;_ end of strcat
                                block-name
                                ) ;_ end of _kpblc-block-insert-lib
                          ) ;_ end of setq
                    (_kpblc-error-catch
                      '(lambda ()
                         (vl-file-delete
                           (strcat (_kpblc-dir-get-root-temp)
                                   (vl-filename-base block-lib-name)
                                   (vl-filename-extension block-lib-name)
                                   ) ;_ end of strcat
                           ) ;_ end of VL-FILE-DELETE
                         ) ;_ end of lambda
                      nil
                      ) ;_ end of _kpblc-error-catch
                    ) ;_ end of progn
                  (progn
                    ;; Файл не в режиме "readonly"
                    (if block-name
                      (progn
                        (setq odbx (_kpblc-odbx))
                        (vla-open odbx block-lib-name :vlax-true)
                        (if
                          (vl-catch-all-error-p
                            (vl-catch-all-apply
                              '(lambda ()
                                 (vla-item (vla-get-blocks odbx) block-name)
                                 ) ;_ end of lambda
                              ) ;_ end of VL-CATCH-ALL-APPLY
                            ) ;_ end of VL-CATCH-ALL-ERROR-P
                           (kpblc-msg-alert
                             (strcat "В файле "
                                     block-lib-name
                                     " отсутствует описание блока "
                                     block-name
                                     ) ;_ end of strcat
                             ) ;_ end of kpblc-msg-alert
                           (progn
                             ;;(setq blocks (vla-get-blocks *KPBLC-ACTIVEDOC*))
                             (_kpblc-dwg-wipeout)
                             (vla-copyobjects
                               odbx
                               (vlax-safearray-fill
                                 (vlax-make-safearray
                                   vlax-vbobject
                                   '(0 . 0)
                                   ) ;_ end of vlax-make-safearray
                                 (list (vla-item (vla-get-blocks odbx) block-name)
                                       ) ;_ end of list
                                 ) ;_ end of vlax-safearray-fill
                               blocks
                               ;;(vla-get-blocks *kpblc-activedoc*)
                               ) ;_ end of vla-CopyObjects
                             (vlax-release-object odbx)
                             (setq
                               res (vla-item (vla-get-blocks *kpblc-activedoc*)
                                             block-name
                                             ) ;_ end of vla-item
                               ) ;_ end of setq
                             ) ;_ end of progn
                           ) ;_ end of if
                        ) ;_ end of progn
                      (progn
                        (command "_.-insert" block-lib-name)
                        (command)
                        (setq res (vla-item (vla-get-blocks *kpblc-activedoc*)
                                            (vl-filename-base block-lib-name)
                                            ) ;_ end of vla-item
                              ) ;_ end of setq
                        ) ;_ end of progn
                      ) ;_ end of if
                    ) ;_ end of progn
                  ) ;_ end of if
                ) ;_ end of progn
              (kpblc-msg-alert
                (strcat "Файл библиотеки " block-lib-name " не найден")
                ) ;_ end of kpblc-msg-alert
              ) ;_ end of if
            ) ;_ end of progn
          ) ;_ end of if
        ) ;_ end of lambda
      ) ;_ end of function
    '(lambda (x) (_kpblc-error-print "_kpblc-block-insert-lib" x))
    ) ;_ end of _KPBLC-ERROR-CATCH
  (_kpblc-error-catch '(lambda () (vlax-release-object odbx)) nil)
  (_kpblc-error-sysvar-restore '("sdi"))
  res
  ) ;_ end of defun
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 05.06.2007, 23:14
#12
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,381


>Кулик Алексей aka kpblc

Все эти функции вполне нормальные. Но есть "нюансы, значить".

1. 3D и произвольная ПСК обязательны для мультивставки. Проверь, это не больно.

2. Впреди BricsCAD. Что там и как с объектами - не исследовано. Судя по глюкам в самом Автокаде, там будет не лучше.

3. DBX хорош, если есть он. А если нет (Brics со товарищи), то стратегическая функция выпадает.

Цитата:
Я пошел другим путем, на сервере есть база данных, в ней лежат списки для entmakex...
Короче, если блока нет в файле, то я его быстренько создаю.
Чтение идет из единой базы данных - это мне нравится.
Вполне нормальное решение. Например, чтобы намертво привязать все лично на себя. Для конкретной организации (штучная работа). Как же загонять в базу списки? Эта работа "теткам" не по зубам. А вот файловые блоки или библиотеки блоков могут делать все. Плюс возможность очень легко делать иллюстрированные меню путем копирования и корректировки текстовых строк, в которых все понятно.

В базе данных мы, например, храним координаты объектов в ГИС. Практически это немногим отличается от блоков. В БД можно, и это проще, просто запихать блоки. Это удобнее для централизации - хоть через Интернет вставляй.

Но это уже другая тема, не про вставку...
ShaggyDoc вне форума  
 
Непрочитано 06.06.2007, 00:52
#13
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,853


Цитата:
3D и произвольная ПСК обязательны для мультивставки. Проверь, это не больно.
Запасся вазелином. Проверил. Почти понадобилось
Суть в том, что для атрибутов в блоке, имеющих "немировую систему координат" она преобразовывается в текущую. Мой баг, не спорю. Но в остальном пока нормально работает. Может, я не полностью тестирование выполняю?
Цитата:
Впреди BricsCAD. Что там и как с объектами - не исследовано. Судя по глюкам в самом Автокаде, там будет не лучше.
На данный момент не поддерживается расширение visual lisp и activex, вроде как обещают в следующей версии выдать. Тем не менее в комплекте с основной программой поставляются .h-файлы, используя которые, можно писать аналоги arx-приложений, но уже для bricscada. Сам я этим не занимался, сужу по результатам сабитовского форума.
Цитата:
DBX хорош, если есть он. А если нет (Brics со товарищи), то стратегическая функция выпадает.
Это да... Но с другой стороны, надежда умирает последней, будем терроризировать разработчиков
Цитата:
Как же загонять в базу списки? Эта работа "теткам" не по зубам.
Ну ета... Если в блоке нет солидов или иных объектов, имеющих зашифрованное представление, либо пользовательских объектов, для которых DXF не сделан, то не думаю, что будет нереально написать функцию вида: указать на блок, прочитать его представление и, последовательно проходя по всем его подпримитивам, получить список. И засунуть его в БД. Имея заветную кнопку с названием "Фас!", любая "тетка" будет заполнять базу, особо не заморачиваясь сама и заморачивая других
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 06.06.2007, 08:47
#14
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,381


Здесь мы начали обсуждать детали про "мультивставку", непонятные многим.

Приведу постановку задачи, может быть кто-то решит собственным методом.
Итак, надо написать функцию с условным именем dwgru-multi-insert

Вызов:

Код:
[Выделить все]
(dwgru-multi-insert block_name  x_scale y_scale  block_angle msg_insert  msg_angle)
Аргументы:

block_name - имя блока, который уже определен
x_scale - масштаб блока по Х, в том числе и отрицательный
y_scale - масштаб блока по Y, в том числе и отрицательный и отличный от X
block_angle - угол поворота блока в радианах или NIL для запроса угла
msg_insert - приглашение для указания точки вставки
msg_angle - приглашение для указания угла поворота

Результат: примитив вставки или NIL при отказе.

Что должна делать:

1. Предлагать в цикле, до пустого ввода, вставлять блок block_name. Блок должен при этом визуально висеть на курсоре, предварительно отмасштабированный до x_scale и y_scale. Пользователь должен видеть изображение блока до указания точки вставки (включая первую вставку) и приглашение msg_insert. Указывать точку вставки можно любым стандартным методом (мышкой, с клавиатуры, с использованием объектной привязки и прозрачных команд).

2. После указания точки вставки, если block_angle NIL (исправлено по замечанию Alaspher) выдается приглашение msg_angle для указания угла поворота вставленного блока (визуального или с клавиатуры, или любым стандартным методом) относительно точки вставки с углом 0 по умолчанию.
В момент указания поворота прерывание работы должно блокироваться.
Если block_angle NIL, угол поворота остается 0.

3.Примерный диалог:

Command:
Точка вставки <Хватит>: 100, 100, 100
Угол поворота <0>: 45
Точка вставки <Хватит>: 100, 1000, 100
Угол поворота <0>: 0
Точка вставки <Хватит>: Пустой ввод и выход

Дополнительные обязательные требования:

4. Вставка должна корректно производиться в любой ПСК в плоскости XY. Координаты точки вставки при любом способе ввода должны быть в ПСК.

5. Блок может иметь атрибуты любых типов. При наличии редактируемых атрибутов после вставки должен выводиться стандартный диалог редактирования атрибутов.

6. Функция должна работать «чисто» — во время работы за курсором не должны тянуться «резиновые» нити, а при любом, в том числе аварийном завершении, не должны оставаться «трупы» временных объектов и прочий мусор.

7. Работа функции не должна завершаться нажатием клавиши <Esc> в качестве основного средства прерывания вставки (хотя возможно в качестве дополнения к штатному выходу при пустом вводе; при этом не должна прерываться основная программа);

Все условия являются обязательными!

Предлагаю желающим потренировать свои мозги. Наш старый вариант имеется в книге "САПР на базе AutoCAD - как это делается", глава 22, листинг 22.25. Он уже подвергался корректировке. А можно и не смотреть, чтобы сделать на свежую голову.

"Забьем Мике баки?" (c)
ShaggyDoc вне форума  
 
Непрочитано 06.06.2007, 09:04
#15
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,853


Маленькое дополнение: при использовании отрицательных масштабов вставки блока поведение атрибутов, мягко говоря, вызывает серьезные нарекания. Желающим предлагаю попробовать
P.S. Я проворачивал на 2005 и 2006, там ситуация не менялась. Может, в 2008 и решена эта проблема, не знаю. Но прога-то должна работать в любой версии от 2002, так?
P.P.S. ShaggyDoc, тут (ИМХО, конечно) будет явно не одна функция
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 06.06.2007, 09:59
#16
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от Кулик Алексей aka kpblc
Цитата:
Сообщение от ShaggyDoc
Как же загонять в базу списки? Эта работа "теткам" не по зубам.
Ну ета... Если в блоке нет солидов или иных объектов, имеющих зашифрованное представление, либо пользовательских объектов, для которых DXF не сделан, то не думаю, что будет нереально написать функцию вида: указать на блок, прочитать его представление и, последовательно проходя по всем его подпримитивам, получить список. И засунуть его в БД. Имея заветную кнопку с названием "Фас!", любая "тетка" будет заполнять базу, особо не заморачиваясь сама и заморачивая других
Вроде, все очень просто - конструкция
Код:
[Выделить все]
(entmakex(entget <ename>))
нормально работает с любыми объектами, включая солиды и.т.д... Это я к тому, что совершенно не обязательно разбираться, что за примитивы внутри блока.
По поводу теток, я вообще им не доверяю работу с базой данных - все делается за кадром - если создается блок для дальнейшей работы, значит отправляем его в базу...
Елпанов Евгений вне форума  
 
Непрочитано 06.06.2007, 10:53
#17
AY

webcad.pro
 
Регистрация: 06.01.2005
Московская обл.
Сообщений: 501


Цитата:
Предлагаю желающим потренировать свои мозги
А собственно зачем, если все уже 10 лет как написано и отлично работает?
AY вне форума  
 
Автор темы   Непрочитано 06.06.2007, 11:39
#18
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,381


Цитата:
Сообщение от Елпанов Евгений
Вроде, все очень просто - конструкция
Код:
[Выделить все]
(entmakex(entget <ename>))
нормально работает с любыми объектами, включая солиды и.т.д... Это я к тому, что совершенно не обязательно разбираться, что за примитивы внутри блока.
По поводу теток, я вообще им не доверяю работу с базой данных - все делается за кадром - если создается блок для дальнейшей работы, значит отправляем его в базу...
Все "очень просто", пока не столкнетесь со сложным. Вполне возможно, что для ваших объектов пока все просто. Но если позарез надо будет, например, загнать в БД блок оборудования в 3D, скачанный с фирменного сайта с сотнями разнообразных примитивов, то проблемы будут.

А вот насчет "я вообще им не доверяю работу с базой данных" как раз самое опасное - привязка к конкретному "я". Все мы люди живые, а некоторые даже и смертные. Нет человека - нет технологии.

Впрочем, это побочная тема, не собираюсь переубеждать. Это не мое собачье дело.

Цитата:
А собственно зачем, если все уже 10 лет как написано и отлично работает?
Работает уже 17 лет, но хорошо - в 2D. А надо " Вставка должна корректно производиться в любой ПСК в плоскости XY. " То есть и в 3D.

Цитата:
ShaggyDoc, тут (ИМХО, конечно) будет явно не одна функция
Наверняка. Всякие вспомогательные могу дать, чтобы не отвлекаться на них.

Цитата:
при использовании отрицательных масштабов вставки блока поведение атрибутов, мягко говоря, вызывает серьезные нарекания
Здесь можно упростить - считать, что при отрицательных масштабах атрибутов нет. Во всяком случае, отрицательные масштабы применяются редко и для таких блоков, в которых видимых атрибутов не бывает.
ShaggyDoc вне форума  
 
Непрочитано 06.06.2007, 12:52
#19
Alaspher


 
Регистрация: 11.10.2004
e•burg
Сообщений: 755


Цитата:
Сообщение от ShaggyDoc
2. После указания точки вставки, если block_angle не NIL выдается приглашение msg_angle для указания угла поворота вставленного блока (визуального или с клавиатуры, или любым стандартным методом) относительно точки вставки с углом 0 по умолчанию.
Если мне не изменяет мой склероз, то как раз, когда NIL, тогда и должен быть интерактивный запрос поворота.
Alaspher вне форума  
 
Непрочитано 06.06.2007, 13:12
#20
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,853


Еще раз прочитал тему, в связи с этим вопрос: так проблема во вставке имеющегося описания блока или во вставке описания блока из другого файла, с, возможно, "нестандартными" insunits? Чего-то я торможу...
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > На заметку программистам

Размещение рекламы