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

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

Помогите начинающему разобраться с блоками

Ответ
Поиск в этой теме
Непрочитано 14.03.2007, 09:58 #1
Помогите начинающему разобраться с блоками
Diman111
 
промышл проектант
 
Изовсехщелей
Регистрация: 26.05.2005
Сообщений: 323

Вопрос. Есть желание написать свою програмку для работы с блоками, для чего нужно понять как с ними работать. С примитивами типа линий все ясно - entget entmake. с блоками неясно как добраться до атрибутов.

(setq prim (entget(cdr(entsel))))

в описании кодов нет прямой ссылки на атрибут. Разжуйте пожалуйстка как посредством Лиспа и dxf добраться до атрибутов и узнать их количество

все что написано в литературе - tblsearch next object - не совсем понятен принцип работы именно с блоками и атрибутами в блоках.
Просмотров: 9764
 
Непрочитано 14.03.2007, 10:27
#2
Кулик Алексей aka kpblc
Moderator

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


Тебе именно через dxf надо? Если через activex покатит, см. http://www.arcada.com.ua/forum/viewtopic.php?t=981
А так-то можно добираться примерно так, наверное:
Код:
[Выделить все]
(defun _kpblc-dxf-block-attr-get (block tag / att res)
				 ;|
*    Получение указателя на атрибут вхождения блока
*    Параметры вызова:
*	block	ename-указатель на вхождение блока
*	tag	маска тэга атрибута.
*    Возвращаемое значение:
*	список ename-указателей на атрибуты, если они есть, либо nil.
*    Внешние ссылки не обрабатываются!
|;
  (if (and (= (cdr (assoc 0 (entget block))) "INSERT")
	   (/= (cdr (assoc 66 (entget block))) 0)
	   ) ;_ end of and
    (progn
      (while (and (setq	att (entnext (if res
				       att
				       block
				       ) ;_ end of if
				     ) ;_ end of entnext
			) ;_ end of setq
		  (/= (cdr (assoc 0 (entget att))) "SEQEND")
		  ) ;_ end of and
	(setq res (append res (list att)))
	) ;_ end of while
      ) ;_ end of progn
    ) ;_ end of if
  (vl-remove-if
    '(lambda (x)
       (not (wcmatch (strcase (cdr (assoc 2 (entget x)))) (strcase tag)))
       ) ;_ end of lambda
    (vl-remove-if '(lambda (x) (/= (cdr (assoc 0 (entget x))) "ATTRIB")) res)
    ) ;_ end of vl-remove-if
  ) ;_ end of defun
Примеры исползования:
Код:
[Выделить все]
(setq att (_kpblc-dxf-block-attr-get (car (entsel)) "*"))
; Получение тэгов атрибутов блока:
(mapcar '(LAMBDA(x) (cdr (assoc 2 (entget x)))) att)
; Получение значений атрибутов:
(mapcar '(LAMBDA(x) (cdr (assoc 1 (entget x)))) att)
Функция не обрабатывает постоянные, предустановленные и verify атрибуты.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 14.03.2007, 13:57
#3
Diman111

промышл проектант
 
Регистрация: 26.05.2005
Изовсехщелей
Сообщений: 323


Спасибо - буду разбираться дальше.

Через activex не покатит - так как не разобрался в простом а более сложное еще впереди.
А нельзя ли в 2-х словах описать принцип получения значений атрибутов? Т.е описать что механизм действия вашего примера?
Если не сложно конечно
Diman111 вне форума  
 
Непрочитано 14.03.2007, 15:37
#4
Кулик Алексей aka kpblc
Moderator

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


Ну в общем-то сначала проверяется, является ли block блоком с атрибутами:
Код:
[Выделить все]
(and (= (cdr (assoc 0 (entget block))) "INSERT")
      (/= (cdr (assoc 66 (entget block))) 0)
      )
Потом проходимся по всему составу блока:
Код:
[Выделить все]
(while (and (setq   att (entnext (if res
                   att
                   block
                   ) ;_ end of if
                 ) ;_ end of entnext
         ) ;_ end of setq
        (/= (cdr (assoc 0 (entget att))) "SEQEND")
        ) ;_ end of and
   (setq res (append res (list att)))
   ) ;_ end of while
На выходе получаем список ename-указателей на примитивы, входящие в состав блока. Затем "фильтруем" список, исключая "не-атрибуты":
Код:
[Выделить все]
(vl-remove-if '(lambda (x) (/= (cdr (assoc 0 (entget x))) "ATTRIB")) res)
И из этого дела уже отфильтровываем атрибуты, у которых тэги не похожи на tag
Код:
[Выделить все]
vl-remove-if
    '(lambda (x)
       (not (wcmatch (strcase (cdr (assoc 2 (entget x)))) (strcase tag)))
       ) ;_ end of lambda <...>
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 14.03.2007, 15:59
#5
Евгений А.

Армспорт
 
Регистрация: 18.07.2006
Ейск
Сообщений: 355


Можно и одним словом - команда (tblobjname "block" "<Имя блока>") - на выходе получаем имя примитива блока (ename), потом как обычно можно использовать (entnext ename) получая имена примитивов внутри блока, пока не вернёт nil.
А Крыс - молоток, именно эту команду и пропустил!!! Видать увлёкся атрибутами... (после ActiveX и мне охото забыть всё связанное с DXF как дурной сон!):
Нехватает перед (while... такой строки
Код:
[Выделить все]
(setq block (tblobjname "block" (cdr (assoc 2 (entget block)))))
Вообще код очень плохой - entget - наверное самая медленная команда (особенно для ACIS обектов), а разбираться с DXF кодами гораздо сложнее, чем изучать ActiveX возможности - намного(!!!) понятнее, а код короче и главное гораздо быстрее!!! DXF - фу!
(Кстати Крысу совет - append в таком варианте тоже будет сильно тормозить программу)
Евгений А. вне форума  
 
Автор темы   Непрочитано 14.03.2007, 16:08
#6
Diman111

промышл проектант
 
Регистрация: 26.05.2005
Изовсехщелей
Сообщений: 323


Хм - занятно - будем думать -
Спасибо за пояснения.
БОЛЬШОЕ
Diman111 вне форума  
 
Непрочитано 14.03.2007, 16:29
#7
Кулик Алексей aka kpblc
Moderator

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


> Евгений А.: Я не люблю dxf, кроме тех случаев, когда его использование удобно (в частности, получение наборов). Все остальное я настолько давно делаю через vla, что dxf вспоминается с трудом (особливо под BricsCAD).
В любом варианте сорри за хреновый код.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 14.03.2007, 17:05
#8
ытя


 
Регистрация: 23.09.2005
СПб
Сообщений: 428


Одна моя старая функция, может чем поможет
Код:
[Выделить все]
;-----------------------------------------------------------------------------------------;
;   функция : p_AttrEdit - изменяет зн-я атрибутов блока						;
;.........................................................................................;
; Вход. параметры -[<Entity name> (список <tag_1>...<tag_i>)(список <зн_1>...<зн_j>)]	;
;	<зн_>-я должны быть строковыми									;
;-----------------------------------------------------------------------------------------;
; Длины списков атрибутов и значений м.б. разными (определяется меньший из них)		;
; 1-му атрибуту присв-тся 1-е знач., 2-му - 2-е и т.д.						;
;-----------------------------------------------------------------------------------------;
(defun p_AttrEdit(ae_BlockName	;<Entity name>
		  ae_TagNames	;список названий атрибутов
		  ae_Values	;список новых значений
		/ n	   ;количество изменяемых атрибутов
		  Tag	   ;название атрибута
		  attrName ;имя DXF
		  attr_i   ;данные i-го атрибута
		  i
		  )
  (setq
    attr_i (entget (entnext ae_BlockName))
    n (min (length ae_TagNames)(length ae_Values))
   )
  (while (and (/=(cdr(assoc 0 attr_i))"SEQEND") (> n 0))
    ;;; прооверяем есть ли назв. текущ. эл-та во входном списке названий атрибутов
    (if (setq i (vl-position (cdr(assoc 2 attr_i)) ae_TagNames))
      (progn
	(setq attr_i (subst (cons 1 (nth i ae_Values)) (assoc 1 attr_i) attr_i)
	      n (1- n));setq
	(entmod attr_i)
       );progn
     );if
    (setq attrName (cdr(assoc -1 attr_i));имя текущего элемента блока
	  attrName (entnext attrName);имя следующего элемента
	  attr_i (entget attrName));считываем данные след. элемента
   );while
  (entupd ae_BlockName)  
 );_defun p_AttrReplace
ытя вне форума  
 
Непрочитано 20.12.2007, 14:19
1 | #9
Олег К.

Инженер-теплотехник
 
Регистрация: 17.08.2006
Смоленск
Сообщений: 308


Помогите начинающему разобраться с удалением блоков.
AutoCAD 2006, без довесков. В новом пустом файле создаем два простейших блока "а" и "b", невзрываемых, сохраняем этот файл под именем 1.dwg в любое удобное место. Получается файл-библиотека блоков.
Далее вставляем блоком эту библиотеку в другой новый файл, и удаляем блоки следующим методом:
Код:
[Выделить все]
(setq active_doc (vla-get-ActiveDocument (vlax-get-acad-object)))
(vla-Delete (vla-InsertBlock (vla-get-ModelSpace active_doc)
	                     (vlax-3D-point '(0.0 0.0 0.0))
	                     "D:\\1.dwg"
	                     1 1 1 0
	        )
)
(vla-Delete (vla-item (vla-get-Blocks active_doc) "1"))
(vla-Delete (vla-item (vla-get-Blocks active_doc) "a"))
Блок-библиотека "1" прекрасно удаляется и зачищается, а вот при попытке зачистки блока "а" пишет ошибку: "error: Automation Error. Object is referenced", хотя _PURGE его зачищает. Если сохранить этот файл, закрыть и снова открыть - блоки "а" и "b" спокойно убираются.
Что такое нужно сделать, чтобы все блоки убирались с первого захода?
Только не предлагайте использовать _PURGE, от него-то и пытаюсь избавиться.
Олег К. вне форума  
 
Непрочитано 20.12.2007, 14:40
#10
Alaspher


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


Цитата:
Сообщение от Олег К. Посмотреть сообщение
Только не предлагайте использовать _PURGE, от него-то и пытаюсь избавиться.
А vla-PurgeAll тоже не проходит?
Alaspher вне форума  
 
Непрочитано 20.12.2007, 16:13
#11
Олег К.

Инженер-теплотехник
 
Регистрация: 17.08.2006
Смоленск
Сообщений: 308


Цитата:
Сообщение от Alaspher Посмотреть сообщение
А vla-PurgeAll тоже не проходит?
У него фильтра нет. Мне нужно удалить из файла строго определенные блоки.
Олег К. вне форума  
 
Непрочитано 20.12.2007, 16:16
#12
Кулик Алексей aka kpblc
Moderator

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


А блок а случаем не входит в блок b (ну или наоборот)?
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 20.12.2007, 16:36
#13
Олег К.

Инженер-теплотехник
 
Регистрация: 17.08.2006
Смоленск
Сообщений: 308


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
А блок а случаем не входит в блок b (ну или наоборот)?
Еслибы.
А почему он тогда удаляется после закрытия-открытия файла? И пургенится?

Прицеплю тестовый файл заодно
Вложения
Тип файла: dwg
DWG 2004
1.dwg (32.7 Кб, 952 просмотров)
Олег К. вне форума  
 
Непрочитано 20.12.2007, 16:54
#14
Кулик Алексей aka kpblc
Moderator

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


У меня кад сошел с ума сегодня, поэтому без проверок:
Код:
[Выделить все]
(vl-load-com)
(defun test (lib blk / ref func_get-name adoc blocks)
  (defun func_get-name (blk)
    (if (vlax-property-available-p blk 'effectivename)
      (vla-get-effectivename blk)
      (vla-get-name blk)
      ) ;_ end of if
    ) ;_ end of defun

  (setq adoc   (vla-get-activedocument (vlax-get-acad-object))
        blocks (vla-get-blocks adoc)
        ref    (vla-insertblock
                 (vla-get-modelspace adoc)
                 lib
                 1.
                 1.
                 1.
                 0.
                 ) ;_ end of vla-insertblock
        ) ;_ end of setq
  (vla-erase ref)
  (vlax-for blk_def (vla-item blocks (vl-filename-base lib))
    (if (/= (strcase (func_get-name blk_def)) (strcase blk))
      (vl-catch-all-apply '(lambda () (vla-delete (vla-item blocks blk_def))))
      ) ;_ end of if
    ) ;_ end of vlax-for
  (vla-delete ref)
  (vla-item blocks blk)
  ) ;_ end of defun
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.

Последний раз редактировалось Кулик Алексей aka kpblc, 20.12.2007 в 17:00. Причина: Добавил (vl-load-com)
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 20.12.2007, 18:13
#15
VVA

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


Можно копировать блоки через objectDBX
Как пример DBXImportBlock Fatty
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Непрочитано 21.12.2007, 12:02
#16
Олег К.

Инженер-теплотехник
 
Регистрация: 17.08.2006
Смоленск
Сообщений: 308


Алексей, с небольшими поправками программа работает, вот только блоки не удаляет. При пошаговом выполнении выдает ошибку в строке (lambda () ....), все то же "Object is referenced".
Свойство effectivename стоит проверять для всех блоков или только для динамических или с атрибутами?

Пока пытался выяснить куда еще информация о вставленных блоках пишется, нашел решение проблемы. Самое идиотское, еслиб случайно не получилось, никогда не догадался бы.
В файле-библиотеке у меня есть не только записи о блоках, но и вхождения этих блоков (в модели, чтобы знать какие блоки есть в файле). Удалил один блок из библиотеки и забыл выполнить зачистку. Так после вставки файла-библиотеки в другой файл именно этот блок удалился без вопросов. В принципе решение найдено, только неудобно, что в библиотеке не видно входящих в неё блоков.
Да и вопрос, что куда пишется при вставке, остается открытым. И что происходит при закрытии-открытии файла, после чего ранее "неубиваемые" блоки спокойно удаляются?
Олег К. вне форума  
 
Непрочитано 21.12.2007, 12:08
#17
Кулик Алексей aka kpblc
Moderator

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


Чертовщина какая-то. Я ж удаляю вставку библиотеки... В качестве уточнения: "тестовый пример" в #13 это библиотека или "результат вставки"? Если второе - выложи саму библиотеку. Тогда смогу погонять код более какчественно )
effectivename требуется для дин.блоков (у них (vla-get-name) вернет нечто типа "*Uxxx").
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 21.12.2007, 12:20
#18
VVA

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


Вот еще ссылочка
Копирование блоков из чертежа в чертеж
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Непрочитано 21.12.2007, 13:02
#19
Кулик Алексей aka kpblc
Moderator

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


VVA, ObjectDBX очень удобен, но не гарантирует 100% работы
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 21.12.2007, 15:47
#20
Олег К.

Инженер-теплотехник
 
Регистрация: 17.08.2006
Смоленск
Сообщений: 308


>> Кулик Алексей aka kpblc
Вот и я о том же - фигня какая-то наблюдается
Файл "1.dwg"из №13 это именно библиотека. В нем два блока "а" и "b" находящиеся в модели. Также там присутствуют описания этих блоков в символьной таблице BLOCK, назовем их "a_i" и "b_i".
Вставляем этот файл-библиотеку как блок в другой файл (ну хоть в "Drawing1"):
Код:
[Выделить все]
(setq active_doc (vla-get-ActiveDocument (vlax-get-acad-object)))
(setq bibl_block (vla-InsertBlock (vla-get-ModelSpace active_doc)
	                     (vlax-3D-point '(0.0 0.0 0.0))
	                     "D:\\1.dwg"
	                     1 1 1 0
	        )
)
Получаем в новом файле блок с именем "1" и описания блоков "1_i", "a_i", "b_i" в таблице BLOCK.
Удаляем блок "1" и его описание "1_i" из "Drawing1":
Код:
[Выделить все]
(vla-Delete bibl_block)
(vla-Delete (vla-item (vla-get-Blocks active_doc) "1"))
По идее, сейчас в файле "Drawing1" находятся только описания "a_i" и "b_i". Вхождений этих блоков нет, значит их можно зачистить, что команда PURGE и делает. А вот если удалять через (vla-Delete (vla-item (vla-get-Blocks active_doc) "a")), ничего не получится - "error: Automation Error. Object is referenced". Где-то осталась запись, что эти блоки используются.
Действие №полтора: сохраняем "Drawing1", закрываем, открываем снова. Записи "a_i" и "b_i" спокойно удаляются vla-Delete'ом. Вот что, спрашивается, исправил автокад во время закрытия файла?

Действие №2. В исходном файле-библиотеке удаляем блоки "а" и "b" из модели, остаются только их описания "a_i" и "b_i". Пусть теперь этот файл зовется "2.dwg". Вставляем его в новый файл "Drawing2" - теперь в нем есть блок "2" и описания блоков "2_i", "a_i", "b_i". Так вот в этом случае функцией vla-Delete можно удалять "a_i" и "b_i", не удаляя перед этим "2" и "2_i"!

В принципе я разобрался что делать, код тестировать наверное больше не нужно. Вот если сможешь сказать какие еще записи остаются в первом случае...

>> VVA
Спасибо за ссылки. Программы пригодятся. Жаль только в ObjectDBX не разбираюсь, с ходу понять не получится
Олег К. вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Помогите начинающему разобраться с блоками