Учусь работать с динамическими блоками

Автор Тема: Учусь работать с динамическими блоками  (Прочитано 12125 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн OlchikАвтор темы

  • ADN OPEN
  • Сообщений: 17
  • Карма: 0
Приветствую Вас снова, разбираюсь с динамическими блоками, вставлять вхождение блока научилась, вот никак не могу понять как мне найти/изменить существующие атрибуты блока, урывками находила, что через BlockReference, но не пойму как мне добраться до существующих атрибутов, подскажите пожалуйста. (Мне нужно задавать длину динамического блока представляющего собой грубо говоря прямоугольник с отверстиями внутри него).

Вот код, каким образом добавляю вхождение блока:
Код - C# [Выбрать]
  1.    Transaction acTrans0 = acCurDb.TransactionManager.StartTransaction();
  2.    using (acTrans0)
  3.             {
  4.                 // открываю таблицу блоков документа
  5.                 BlockTable acBlkTbl0;
  6.                 acBlkTbl0 = acTrans0.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  7.  
  8.                 ObjectId btrId;
  9.  
  10.                 if (acBlkTbl0.Has("ГО2"))
  11.                 {
  12.                     btrId = acBlkTbl0["ГО2"];
  13.                 }
  14.                 else
  15.                 {
  16.                     // открываю таблицу блоков на запись
  17.                     acBlkTbl0.UpgradeOpen();
  18.                     // создаю новое определение блока, задаю ему имя
  19.                     BlockTableRecord btr = new BlockTableRecord();
  20.                     btr.Name = "ГО2";
  21.                     // добавляю созданное определение блока в таблицу блоков, сохраняя его ID
  22.                     btrId = acBlkTbl0.Add(btr);
  23.                     // добавляю созданное определение блока в транзакцию
  24.                     acTrans0.AddNewlyCreatedDBObject(btr, true);
  25.                 }
  26.                 // открываю пространство модели (Model View) - оно является одной из записей в таблице блоков документа
  27.                 BlockTableRecord acBlkTblRec0;
  28.                 acBlkTblRec0 = acTrans0.GetObject(acBlkTbl0[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  29.                 LayerTable acLyrTbl2 = acTrans0.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
  30.                 acCurDb.Clayer = acLyrTbl2["Слой1"];
  31.                 // создаю новое вхождение блока, используя ранее сохраненный ID определения блока
  32.                 BlockReference br = new BlockReference(Point3d.Origin, btrId);
  33.                 // добавляю вхождение блока на пространство модели и в транзакцию
  34.                 acBlkTblRec0.AppendEntity(br);
  35.                 acTrans0.AddNewlyCreatedDBObject(br, true);
  36.                 acTrans0.Commit();
  37.             }

Отмечено как Решение Olchik 10-09-2015, 10:36:43

Оффлайн Gul

  • ADN OPEN
  • Сообщений: 4
  • Карма: 1
Код - C# [Выбрать]
  1. var blockReferenceProperty = blockReference.DynamicBlockReferencePropertyCollection
  2. .Cast<DynamicBlockReferenceProperty>()
  3. .FirstOrDefault(o => o.PropertyName.Equals("Имя свойства"));
  4.  
  5. if (blockReferenceProperty != null)
  6. {
  7.        blockReferenceProperty.Value = "Значение";
  8. }
  9.  

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Olchik
1. Средствами AutoCAD .NET API (как и любыми другими публичными API) создать описание динамического блока нельзя. Его можно лишь скопировать (например из чертежа-шаблона).
2. Как работать со свойствами (не атрибутами - атрибуты у блоков это совершенно иное) динамических блоков: http://adndevblog.typepad.com/autocad/2012/08/how-to-access-and-modify-a-dynamicblockreference-property-in-arx-and-net.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн OlchikАвтор темы

  • ADN OPEN
  • Сообщений: 17
  • Карма: 0
Gul, Александр Ривилис,
Спасибо за разъяснения) Обязательно учту!

Оффлайн vermesser

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Код - C# [Выбрать]
  1.  
  2. .Cast<DynamicBlockReferenceProperty>()
  3. .FirstOrDefault(o => o.PropertyName.Equals("Имя свойства"));
  4.  
  5. if (blockReferenceProperty != null)
  6. {
  7.        blockReferenceProperty.Value = "Значение";
  8. }
  9.  
Подобный код очень медленно работает у меня почему-то (несколько минут) - особенно когда обрабатываю много блоков, например, 600:
Код - vb.net [Выбрать]
  1. For Each designID As ObjectId In designIDs
  2.  
  3.     Using blockRef As BlockReference = designID.Open(OpenMode.ForRead)
  4.  
  5.         Dim props As DynamicBlockReferencePropertyCollection = blockRef.DynamicBlockReferencePropertyCollection
  6.  
  7.         'Если указано, то берём смещение графики от проекта и допуски из блока анкера
  8.         For Each prop As DynamicBlockReferenceProperty In props
  9.             Select Case prop.PropertyName
  10.                 Case "Диаметр"
  11.                     If offsetFromDesignObject Then offset = prop.Value / 2
  12.                 Case "План"
  13.                     If toleranceFromDesignObject Then planeTolerance = prop.Value
  14.                 Case "Вверх"
  15.                     If toleranceFromDesignObject Then topTolerance = prop.Value
  16.                 Case "Вниз"
  17.                     If toleranceFromDesignObject Then bottomTolerance = prop.Value
  18.             End Select
  19.         Next
  20.  
  21.     End Using
  22.  
  23. Next
Может глупости какие-то делаю?
Подскажите, как сделать обработку свойств большого количества динамических блоков быстрее?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Странно. Код выглядит вполне нормально. Ты не модифицируешь свойства блока, так что всё должно работать достаточно быстро.
Разве что если свойств очень много, то после получения всех нужных можно прервать цикл.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн vermesser

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Если в чертеже оставить блоков десять, то всё происходит в одно мгновение.

Оффлайн vermesser

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Чем больше блоков в чертеже, тем медленнее.
Я пробовал даже так:
Код - vb.net [Выбрать]
  1. For Each designID As ObjectId In designIDs
  2.  
  3.     Using blockRef As BlockReference = designID.Open(OpenMode.ForRead)
  4.  
  5.         Dim props As DynamicBlockReferencePropertyCollection = blockRef.DynamicBlockReferencePropertyCollection
  6.  
  7.     End Using
  8.  
  9. Next
То есть даже не перебирал свойства.
Результат такой же.

Оффлайн vermesser

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
То есть дело в моём случае не в количестве свойства.
Причем проблемы начинаются именно при получении DynamicBlockReferencePropertyCollection для блока.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System;
  6.  
  7. namespace AcadTest
  8. {
  9.     public class DynBlockSpeedTest
  10.     {
  11.         [CommandMethod("DynBlockSpeedTest")]
  12.         public void RunTest()
  13.         {
  14.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  15.             if (adoc == null) return;
  16.             Database db = adoc.Database;
  17.             Editor ed = adoc.Editor;
  18.  
  19.             PromptSelectionOptions selOpts = new PromptSelectionOptions();
  20.             selOpts.MessageForAdding = "\nSelect dynamic blocks:";
  21.             selOpts.MessageForRemoval = "\nRemoved from selection:";
  22.  
  23.             SelectionFilter selFl = new SelectionFilter(new[]
  24.             {
  25.                 new TypedValue((int)DxfCode.Start, "INSERT")
  26.             });
  27.  
  28.             PromptSelectionResult selRes = ed.GetSelection(selOpts, selFl);
  29.             if (selRes.Status != PromptStatus.OK) return;
  30.             ObjectId[] blkRefIds = selRes.Value.GetObjectIds();
  31.  
  32.             DateTime start = DateTime.Now;
  33.  
  34.             foreach (ObjectId blkRefId in blkRefIds)
  35.             {
  36.                 using (BlockReference blkRef = blkRefId.Open(OpenMode.ForRead) as BlockReference)
  37.                 {
  38.                     if (blkRef.IsDynamicBlock)
  39.                     {
  40.                        var dynPropCol = blkRef.DynamicBlockReferencePropertyCollection;
  41.                     }
  42.                 }
  43.             }
  44.  
  45.             DateTime end = DateTime.Now;
  46.  
  47.             TimeSpan time = end - start;
  48.  
  49.             ed.WriteMessage
  50.                 ("\nBlocks: {0}. Processing time: {1} ms",
  51.                 blkRefIds.Length, time.TotalMilliseconds);
  52.         }
  53.     }
  54. }
Blocks: 600. Processing time: 165 ms

Оффлайн vermesser

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Ваш код, мой файл:
Blocks: 672. Processing time: 34636.0349 ms

Ваш код, ваш файл:
Blocks: 600. Processing time: 168.1115 ms

Чертовщина )))

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
О, так ведь дело не в коде, а в блоке. Штриховка в блоке + размерные зависимости. Нужно переделывать блок.

Оффлайн vermesser

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
О, так ведь дело не в коде, а в блоке. Штриховка в блоке + размерные зависимости. Нужно переделывать блок.
Подскажите, пожалуйста, что именно нужно переделать?

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Нужно максимально упростить динамический блок. В первую очередь - удалить размерные зависимости. Чтобы в итоге получилось что-то типа такого.
У меня обрабатывает за 70 миллисекунд.
P.S. По сути, тут динпараметр "радиус" тоже лишний, т.к. можно просто менять масштаб блока. Можно оставить только параметр видимости.

Оффлайн vermesser

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Нужно максимально упростить динамический блок. В первую очередь - удалить размерные зависимости. Чтобы в итоге получилось что-то типа такого.
У меня обрабатывает за 70 миллисекунд.
P.S. По сути, тут динпараметр "радиус" тоже лишний, т.к. можно просто менять масштаб блока. Можно оставить только параметр видимости.
Спасибо, сделаю.
А штриховку тоже рекомендуете убрать из блока?