Re: Обновить вхождение блока
2 Вильдар
Спасибо за замечания. Разбираться с ними буду в понедельник - сегодня себе устраиваю выходной.
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
2 Вильдар
Спасибо за замечания. Разбираться с ними буду в понедельник - сегодня себе устраиваю выходной.
2 All
Похоже, что сайт caduser.ru глючит: мне несколько раз подряд приходит сообщение о том, что в данном топике что-то написали и в качестве цитаты показывается то, что я уже читал ещё вчера. Открываю топик - новых сообщений нет.
Hwd,
Я правлю свои посты. Удалил лапшу кода, бесполезного. Поправил замечания к твоей тулзе (в пояснении написал). И первый пост поправил, обозначил точнее проблему.
Я подумал, а как акад определяет соответствие атрибута во вхождении блока с атрибутом в описании блока.
И кажется понял. Он нумерует атрибуты и записывает это в Xdata.
Вот как это выглядит:
1001 AcDbBlockRepETag; ; 1070 1; ; 1071 0; ; 1005 0; ;
Здесь код 1071 и есть номер атрибута.
Например, для второго атрибута в блоке эта запись будет такой:
1001 AcDbBlockRepETag; ; 1070 1; ; 1071 1; ; 1005 0; ;
Такая же запись есть и у атрибута во вхождении блока.
Осталось написать функцию по нахождению AttributeDefinition по AttributeReference, на основе такой записи в Xdata.
Возможно это уже сто раз обсуждалось, но я не знал об этом. Хотя, я и не уверен, а только предполагаю.
Еще вопрос, если находить таким способом описание атрибута для анонимного блока, то лучше искать в описании анонимного блока или динамического?
И еще, что означают другие два кода 1070 и 1005? 1005 вроде как хэндл (по справке dxf), но значение 0 этому не соответствует.
...удалил бесполезный код.
И кажется понял. Он нумерует атрибуты и записывает это в Xdata.
Далеко не всегда. У меня, например, у определений атрибутов и атрибутов нет Xdata вообще. Они появляются (IMHO) только если блок динамический. Так что я бы не стал на это ориентироваться. Кроме того это всё не документировано. Так что делай выводы.
Они появляются (IMHO) только если блок динамический.
Тестировал и для простого блока, и для динамического.
А тогда, как акад это делает? Ведь при синхронизации атрибутов (команда _attsync) он должен точно определять соответствие атрибутов во вхождении блока с атрибутами в описании блока.
А тогда, как акад это делает?
По порядку следования определений атрибутов и атрибутов.
Тестировал и для простого блока, и для динамического.
Посмотри: testblock.dwg
По порядку следования определений атрибутов и атрибутов.
Буду пробовать.
Посмотри: testblock.dwg
Надеюсь Вы не удаляли xdata :D
А как этот блок создан?
Зашел в редактор блока, создал еще один атрибут, сохранил, вышел из редактора. Теперь xdata появились.
Надеюсь Вы не удаляли xdata smile:D
Нет конечно.
А как этот блок создан?
Последовательно:
1) Команда _RECTANGLE - создаю прямоугольник
2) Команда _ATTDEF - последовательно создаю определения атрибутов
3) Команда _BLOCK - создаю блок, выбрав прямоугольник и определения атрибутов.
Всё. Проверял в AutoCAD 2008, 2011, 2012
Последовательно:
Значит дело в редакторе блоков. Он добавляет xdata.
Проверил свой рабочий блок (он создан из dwg (_insert выбрать файл)), у него тоже нет xdata :cry:
2 Вильдар
Я, пожалуй, не буду ориентироваться на XData, поскольку, как заметил Александр Ривилис - они не всегда заполнены + это не документировано. ИМХО - в определении блока каждый тэг должен иметь своё уникальное значение. Два определения атрибутов с одинаковыми значениями тэгов - это 100% путанница. Я считаю, что возможность наличия в одном определении блока двух атрибутов с одинаковым значением тэга - это баг AutoCAD. Кстати, когда редактируешь такие атрибуты у вхождения блока, второе одинаковое имя тэга подсвечивается красным цветом - AutoCAD показывает тем самым, что это неправильно. Не знаю почему Autodesk не включил программный контроль этого момента.
Я, пожалуй, не буду ориентироваться на XData
Да, это не работает.
Одинаковые тэги, это очень неправильно, согласен. Блин, у нас вся библиотека блоков сделана с одинаковыми тэгами. Это было сделано очень давно, меня еще не было. И все завязано на лиспы, которые скомпилированы в фас, фиг что сделаешь.
Одинаковые тэги, это очень неправильно, согласен. Блин, у нас вся библиотека блоков сделана с одинаковыми тэгами.
Ну... В данной ситуации я могу тебе только посочувствовать. Я вот думаю, может написать дополнительную команду, которая анализировала бы атрибуты определений блоков и убивала лишние, чтобы каждый тэг имел своё уникальное значение. Это заставит юзеров более ответственно подходить к вопросу проектирования блоков.
Не знаю почему Autodesk не включил программный контроль этого момента.
Потому что еще 20 лет назад такого запрета не было. Так что для преемственности. Правильный способ для получения соответствия AttribiteDefinition <-> Attribute - по порядку (с учётом того, что константные атрибуты не учитываются). НО (!!!) программно можно поменять порядок, так что будьте осторожны.
НО (!!!) программно можно поменять порядок, так что будьте осторожны.
С учётом этого мне кажется более надёжным способом - искать соответствие по значению тэга.
С учётом этого мне кажется более надёжным способом - искать соответствие по значению тэга.
Мне так не кажется. Изменить tag для атрибута еще проще, чем порядок следования атрибутов.
Мне так не кажется. Изменить tag для атрибута еще проще, чем порядок следования атрибутов.
Другая ситуация: изначально в определении блока были атрибуты А, Б, В, Г и Д. Пользователь создал новый файл, импортировал в него это определение и создал несколько вхождений.
Через некоторое время он открыл исходный файл с определением и удалил в определении атрибуты А и В, но добавил Е и Ж. Немного подумав, юзер понимает, что зря удалил определение атрибута А и восстанавливает его (т.о. ранее атрибут А был первым, а теперь он последний в коллекции, а следовательно и индекс у него др.).
Теперь ему нужно обновить определение в целевом файле и выполнить синхронизацию вхождений. Определения блоков между файлами он выполнит без проблем. А дальше, если ориентироваться на индексы (порядок следования в массиве), то выйдет, что индексация атрибутов во вхождении уже не соответствует индексам атрибутов в определении (например для атрибута А).
Т.о. опираться на индексацию - не является более надёжным выбором. Поправьте меня, если я не прав.
Родная команда _attsync корректно распознаёт эту ситуацию и во вхождениях блоков не удаляются атрибуты А с их значениями - они синхронизируются с настройками нового определения атрибута А, хотя это уже др. объект (прежний был удалён). Поэтому я предполагаю, что AutoCAD не ориентируется на соответствия индексов (т.е. не факт, что индекс атрибута в определении блока 100% равен индексу атрибута во вхождении блока, если определение блока подвергалось модификации после создания этих вхождений).
upd А синхронизация нам требуется именно потому, что определение блока было изменено. Т.о. полагаться на индекс - не лучший вариант.
Вот что у меня получилось. Синхронизация атрибутов по порядку следования (как я ее понял :D ). Смотрел на работу команды _AttSync.
Идея простая. Перебираем описания атрибутов и находим первый атрибут с таким тэгом. Далее по смыслу...
...обновил код. более рабочая версия.
public static void AttSync2(BlockReference br, Transaction tr) { Database db = br.Database; //Cписок атрибутов описания блока var btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead); List<AttributeDefinition> adList = new List<AttributeDefinition>(); foreach (ObjectId idAd in btr) { if (idAd.IsErased) continue; var ad = tr.GetObject(idAd, OpenMode.ForRead) as AttributeDefinition; if (ad == null) continue; if (ad.Constant) continue; adList.Add(ad); } //Cписок атрибутов вхождения блока List<AttributeReference> arList = new List<AttributeReference>(); foreach (ObjectId idAr in br.AttributeCollection) { if (idAr.IsErased) continue; var ar = (AttributeReference)tr.GetObject(idAr, OpenMode.ForWrite, false, true); arList.Add(ar); } //Синхронизация атрибутов List<AttributeReference> arSyncList = new List<AttributeReference>(); foreach (var ad in adList) { AttributeReference arSync; //Находим все атрибуты с таким тэгом List<AttributeReference> arFindList = arList.FindAll( arItem => arItem.Tag.Equals(ad.Tag, StringComparison.OrdinalIgnoreCase)); if (arFindList.Count == 0) { //Создаем недостающий атрибут arSync = new AttributeReference(); arSync.SetAttributeFromBlock(ad, br.BlockTransform); } else { //выбираем наиболее подходящий из них var ar = GetMostRelevantAttribut(arFindList, ad); arSync = new AttributeReference(); arSync.SetAttributeFromBlock(ad, br.BlockTransform); //сохранение некоторых параметров (текст, положение) TransferIndividualParam(arSync, ar); arList.Remove(ar); ar.Erase(true); } arSyncList.Add(arSync); } //Удаляем лишние атрибуты foreach (var ar in arList) { ar.Erase(true); } //Устанавливаем в блок синхронизированние атрибуты. using (UnlockLayer unlockLayer = new UnlockLayer(br.LayerId, tr)) { br.UpgradeOpen(); foreach (var ar in arSyncList) { br.AttributeCollection.AppendAttribute(ar); tr.AddNewlyCreatedDBObject(ar, true); } } }
Тестик
[CommandMethod("Test")] public void Test() { Database db = acad.DocumentManager.MdiActiveDocument.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { var cs = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead); foreach (ObjectId idEnt in cs) { var br = tr.GetObject(idEnt, OpenMode.ForRead) as BlockReference; if (br == null) continue; AttSync2(br, tr); } tr.Commit(); } }
Мои, гребаные, рабочие блоки у которых все атрибуты с одинаковыми тэгами, обрабатывает нормально.
Доступна новая версия BlockSync. На той же странице выложены:
Откомпилированная версия плагина для AutoCAD 2009 SP3 x86.
Полный исходный код проекта (MS Visual Studio 2010)
Что нового:
1.Добавлен конфигурационный файл PluginSettings.xml, содержимое которого подробно документировано в его комментариях (программа запоминает предыдущие варианты выборки и по умолчанию открывает те же каталоги (для каждой настройки - свой), а так же включает/отключает галочки в дополнительных опциях).
2. Сообщения об ошибках (не найден файл/нет доступа к файлу/не удалось прочесть настройки/и т.д.) будут выводиться с более понятным пользователям описанием.
3. Целевые файлы можно указать не только на локальной машине, но и в сети.
4. Все сообщения локализованы (en-US/ru-RU).
5. Нужную локализацию можно принудительно указать в файле настроек (по умолчанию она такая, какой её задаёт AutoCAD).
Исправленные ошибки:
1.Многострочные атрибуты после синхронизации не сохраняли значений
2.Для основного определения динамического блока (не его анонимные наследники) не обновлялись атрибуты во вхождениях
3. Не обновлялась геометрия в динамических блоках.
4. Во вхождениях динамических блоков позиционирование некоторых атрибутов сбрасывалось в точку 0,0.
5. Прочие мелкие ошибки.
Hwd, Замечания по BlockSync.
1. Ошибка eOnLockedLayer. Если или атрибут или блок на блокированном слое. Мне кажется лучше обрабатывать и такие блоки и атрибуты.
2. Не сохраняется положение и поворот атрибутов (не фиксированных).
3. Кнопочки выбора файлов уж больно маловаты )
Может позже еще потестирую.
1. Ошибка eOnLockedLayer. Если или атрибут или блок на блокированном слое. Мне кажется лучше обрабатывать и такие блоки и атрибуты.
Сделаю.
2. Не сохраняется положение и поворот атрибутов (не фиксированных).
Скинь файлы на которых тестировал. На тех файлах, что я тестировал, положения и повороты синхронизируются корректно - попробую на твоём примере воспроизвести проблему.
"Не фиксированные" - это ты так называешь атрибуты, у которых снята галочка "Lock Position"?
3. Кнопочки выбора файлов уж больно маловаты )
Это не принципиально :)
Привет Андрей.
В исходнике приклеен проект AnlTest он ссылается на компонент Stimulsoft. Правильно я понимаю, что AnlTest в работе Blocksync не участвует? А также хочу уточнить, а при подгрузке подшивки перечень чертежей в листбоксе появляется или нет? Нет возможности в 2009 версии проверить.
Привет Андрей.
В исходнике приклеен проект AnlTest он ссылается на компонент Stimulsoft. Правильно я понимаю, что AnlTest в работе Blocksync не участвует?
Привет. Да, AnlTest - это черновик для тестирования библиотеки AcadNetLib. Можешь смело удалитьAnlTest.
А также хочу уточнить, а при подгрузке подшивки перечень чертежей в листбоксе появляется или нет? Нет возможности в 2009 версии проверить.
Конечно появляется, программа ведь в конечном счёте обрабатывает целевые dwg-файлы, не важно что ты выбрал в качестве цели: подшивку, каталог или индивидуальный набор файлов. Снимая/устанавливая галочки возле имён файлов, ты сможешь управлять тем, какой из выбранных файлов следует обрабатывать, а какой нет.
Кстати на скрине как раз видно, что целевой объект - подшивка и отображаются её файлы.
Конечно появляется, программа ведь в конечном счёте обрабатывает целевые dwg-файлы, не важно что ты выбрал в качестве цели: подшивку, каталог или индивидуальный набор файлов.
Пока значит не заводится, приходится для 2011 код менять.
Форум работает на PunBB, при поддержке Informer Technologies, Inc