Re: Обновить вхождение блока

2 Вильдар
Спасибо за замечания. Разбираться с ними буду в понедельник - сегодня себе устраиваю выходной.

(изменено: Hwd, 16 октября 2011г. 13:10:38)

Re: Обновить вхождение блока

2 All
Похоже, что сайт caduser.ru глючит: мне несколько раз подряд приходит сообщение о том, что в данном топике что-то написали и в качестве цитаты показывается то, что я уже читал ещё вчера. Открываю топик - новых сообщений нет.

Re: Обновить вхождение блока

Hwd,
Я правлю свои посты. Удалил лапшу кода, бесполезного. Поправил замечания к твоей тулзе (в пояснении написал). И первый пост поправил, обозначил точнее проблему.

(изменено: Вильдар, 17 октября 2011г. 10:14:16)

Re: Обновить вхождение блока

Я подумал, а как акад определяет соответствие атрибута во вхождении блока с атрибутом в описании блока.
И кажется понял. Он нумерует атрибуты и записывает это в 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 этому не соответствует.

...удалил бесполезный код.

Re: Обновить вхождение блока

Вильдар пишет:

И кажется понял. Он нумерует атрибуты и записывает это в Xdata.

Далеко не всегда. У меня, например, у определений атрибутов и атрибутов нет Xdata вообще. Они появляются (IMHO) только если блок динамический. Так что я бы не стал на это ориентироваться. Кроме того это всё не документировано. Так что делай выводы.

Re: Обновить вхождение блока

Александр Ривилис пишет:

Они появляются (IMHO) только если блок динамический.

Тестировал и для простого блока, и для динамического.
А тогда, как акад это делает? Ведь при синхронизации атрибутов (команда _attsync) он должен точно определять соответствие атрибутов во вхождении блока с атрибутами в описании блока.

Re: Обновить вхождение блока

Вильдар пишет:

А тогда, как акад это делает?

По порядку следования определений атрибутов и атрибутов.

Вильдар пишет:

Тестировал и для простого блока, и для динамического.

Посмотри: testblock.dwg

Re: Обновить вхождение блока

Александр Ривилис пишет:

По порядку следования определений атрибутов и атрибутов.

Буду пробовать.

Александр Ривилис пишет:

Посмотри: testblock.dwg

Надеюсь Вы не удаляли xdata :D
А как этот блок создан?
Зашел в редактор блока, создал еще один атрибут, сохранил, вышел из редактора. Теперь xdata появились.

Re: Обновить вхождение блока

Вильдар пишет:

Надеюсь Вы не удаляли xdata smile:D

Нет конечно.

Вильдар пишет:

А как этот блок создан?

Последовательно:
1) Команда _RECTANGLE - создаю прямоугольник
2) Команда _ATTDEF - последовательно создаю определения атрибутов
3) Команда _BLOCK - создаю блок, выбрав прямоугольник и определения атрибутов.
Всё. Проверял в AutoCAD 2008, 2011, 2012

(изменено: Вильдар, 16 октября 2011г. 17:48:57)

Re: Обновить вхождение блока

Александр Ривилис пишет:

Последовательно:

Значит дело в редакторе блоков. Он добавляет xdata.

Проверил свой рабочий блок (он создан из dwg (_insert выбрать файл)), у него тоже нет xdata  :cry:

(изменено: Hwd, 17 октября 2011г. 10:43:25)

Re: Обновить вхождение блока

2 Вильдар
Я, пожалуй, не буду ориентироваться на XData, поскольку, как заметил Александр Ривилис - они не всегда заполнены + это не документировано. ИМХО - в определении блока каждый тэг должен иметь своё уникальное значение. Два определения атрибутов с одинаковыми значениями тэгов - это 100% путанница. Я считаю, что возможность наличия в одном определении блока двух атрибутов с одинаковым значением тэга - это баг AutoCAD. Кстати, когда редактируешь такие атрибуты у вхождения блока, второе одинаковое имя тэга подсвечивается красным цветом - AutoCAD показывает тем самым, что это неправильно. Не знаю почему Autodesk не включил программный контроль этого момента.

(изменено: Вильдар, 17 октября 2011г. 10:53:37)

Re: Обновить вхождение блока

Hwd пишет:

Я, пожалуй, не буду ориентироваться на XData

Да, это не работает.

Одинаковые тэги, это очень неправильно, согласен. Блин, у нас вся библиотека блоков сделана с одинаковыми тэгами. Это было сделано очень давно, меня еще не было. И все завязано на лиспы, которые скомпилированы в фас, фиг что сделаешь.

Re: Обновить вхождение блока

Вильдар пишет:

Одинаковые тэги, это очень неправильно, согласен. Блин, у нас вся библиотека блоков сделана с одинаковыми тэгами.

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

Re: Обновить вхождение блока

Hwd пишет:

Не знаю почему Autodesk не включил программный контроль этого момента.

Потому что еще 20 лет назад такого запрета не было. Так что для преемственности. Правильный способ для получения соответствия AttribiteDefinition <-> Attribute - по порядку (с учётом того, что константные атрибуты не учитываются). НО (!!!) программно можно поменять порядок, так что будьте осторожны.

(изменено: Hwd, 17 октября 2011г. 11:29:38)

Re: Обновить вхождение блока

Александр Ривилис пишет:

НО (!!!) программно можно поменять порядок, так что будьте осторожны.

С учётом этого мне кажется более надёжным способом - искать соответствие по значению тэга.

Re: Обновить вхождение блока

Hwd пишет:

С учётом этого мне кажется более надёжным способом - искать соответствие по значению тэга.

Мне так не кажется. Изменить tag для атрибута еще проще, чем порядок следования атрибутов.

(изменено: Hwd, 17 октября 2011г. 12:17:23)

Re: Обновить вхождение блока

Александр Ривилис пишет:

Мне так не кажется. Изменить tag для атрибута еще проще, чем порядок следования атрибутов.

Другая ситуация: изначально в определении блока были атрибуты А, Б, В, Г и Д. Пользователь создал новый файл, импортировал в него это определение и создал несколько вхождений.

Через некоторое время он открыл исходный файл с определением и удалил в определении атрибуты А и В, но добавил Е и Ж. Немного подумав, юзер понимает, что зря удалил определение атрибута А и восстанавливает его (т.о. ранее атрибут А был первым, а теперь он последний в коллекции, а следовательно и индекс у него др.).

Теперь ему нужно обновить определение в целевом файле и выполнить синхронизацию вхождений. Определения блоков между файлами он выполнит без проблем. А дальше, если ориентироваться на индексы (порядок следования в массиве), то выйдет, что индексация атрибутов во вхождении уже не соответствует индексам атрибутов в определении (например для атрибута А).

Т.о. опираться на индексацию - не является более надёжным выбором. Поправьте меня, если я не прав.

(изменено: Hwd, 17 октября 2011г. 12:41:49)

Re: Обновить вхождение блока

Родная команда _attsync корректно распознаёт эту ситуацию и во вхождениях блоков не удаляются атрибуты А с их значениями - они синхронизируются с настройками нового определения атрибута А, хотя это уже др. объект (прежний был удалён). Поэтому я предполагаю, что AutoCAD не ориентируется на соответствия индексов (т.е. не факт, что индекс атрибута в определении блока 100% равен индексу атрибута во вхождении блока, если определение блока подвергалось модификации после создания этих вхождений).

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

(изменено: Вильдар, 18 октября 2011г. 17:26:16)

Re: Обновить вхождение блока

Вот что у меня получилось. Синхронизация атрибутов по порядку следования (как я ее понял :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();
         }
      }

Мои, гребаные, рабочие блоки у которых все атрибуты с одинаковыми тэгами, обрабатывает нормально.

(изменено: Hwd, 18 октября 2011г. 15:39:34)

Re: Обновить вхождение блока

Доступна новая версия 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. Прочие мелкие ошибки.

Re: Обновить вхождение блока

Hwd, Замечания по BlockSync.
1. Ошибка eOnLockedLayer. Если или атрибут или блок на блокированном слое. Мне кажется лучше обрабатывать и такие блоки и атрибуты.
2. Не сохраняется положение и поворот атрибутов (не фиксированных).
3. Кнопочки выбора файлов уж больно маловаты )
Может позже еще потестирую.

(изменено: Hwd, 18 октября 2011г. 18:16:12)

Re: Обновить вхождение блока

1. Ошибка eOnLockedLayer. Если или атрибут или блок на блокированном слое. Мне кажется лучше обрабатывать и такие блоки и атрибуты.

Сделаю.

2. Не сохраняется положение и поворот атрибутов (не фиксированных).

Скинь файлы на которых тестировал. На тех файлах, что я тестировал, положения и повороты синхронизируются корректно - попробую на твоём примере воспроизвести проблему.
"Не фиксированные" - это ты так называешь атрибуты, у которых снята галочка "Lock Position"?

3. Кнопочки выбора файлов уж больно маловаты )

Это не принципиально :)

Re: Обновить вхождение блока

Привет Андрей.
В исходнике приклеен проект AnlTest он ссылается на компонент Stimulsoft. Правильно я понимаю, что AnlTest в работе Blocksync не участвует? А также хочу уточнить, а при подгрузке подшивки перечень чертежей в листбоксе появляется или нет? Нет возможности в 2009 версии проверить.

(изменено: Hwd, 18 октября 2011г. 18:28:26)

Re: Обновить вхождение блока

Владимир Петров пишет:

Привет Андрей.

В исходнике приклеен проект AnlTest он ссылается на компонент Stimulsoft. Правильно я понимаю, что AnlTest в работе Blocksync не участвует?

Привет. Да, AnlTest - это черновик для тестирования библиотеки AcadNetLib. Можешь смело удалитьAnlTest.

Владимир Петров пишет:

А также хочу уточнить, а при подгрузке подшивки перечень чертежей в листбоксе появляется или нет? Нет возможности в 2009 версии проверить.

Конечно появляется, программа ведь в конечном счёте обрабатывает целевые dwg-файлы, не важно что ты выбрал в качестве цели: подшивку, каталог или индивидуальный набор файлов. Снимая/устанавливая галочки возле имён файлов, ты сможешь управлять тем, какой из выбранных файлов следует обрабатывать, а какой нет.
Кстати на скрине как раз видно, что целевой объект - подшивка и отображаются её файлы.

Re: Обновить вхождение блока

Hwd пишет:

Конечно появляется, программа ведь в конечном счёте обрабатывает целевые dwg-файлы, не важно что ты выбрал в качестве цели: подшивку, каталог или индивидуальный набор файлов.

Пока значит не заводится, приходится для 2011 код менять.