Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Olchik от 10-09-2015, 02:42:14

Название: Учусь работать с динамическими блоками
Отправлено: Olchik от 10-09-2015, 02:42:14
Приветствую Вас снова, разбираюсь с динамическими блоками, вставлять вхождение блока научилась, вот никак не могу понять как мне найти/изменить существующие атрибуты блока, урывками находила, что через 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.             }
Название: Re: Учусь работать с динамическими блоками
Отправлено: Gul от 10-09-2015, 08:11:50
Код - 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.  
Название: Re: Учусь работать с динамическими блоками
Отправлено: Александр Ривилис от 10-09-2015, 08:46:17
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
Название: Re: Учусь работать с динамическими блоками
Отправлено: Olchik от 10-09-2015, 10:36:22
Gul, Александр Ривилис,
Спасибо за разъяснения) Обязательно учту!
Название: Re: Учусь работать с динамическими блоками
Отправлено: vermesser от 03-07-2017, 13:39:30
Код - 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
Может глупости какие-то делаю?
Подскажите, как сделать обработку свойств большого количества динамических блоков быстрее?
Название: Re: Учусь работать с динамическими блоками
Отправлено: Александр Ривилис от 03-07-2017, 14:04:39
Странно. Код выглядит вполне нормально. Ты не модифицируешь свойства блока, так что всё должно работать достаточно быстро.
Разве что если свойств очень много, то после получения всех нужных можно прервать цикл.
Название: Re: Учусь работать с динамическими блоками
Отправлено: vermesser от 03-07-2017, 14:07:23
Если в чертеже оставить блоков десять, то всё происходит в одно мгновение.
Название: Re: Учусь работать с динамическими блоками
Отправлено: vermesser от 03-07-2017, 14:08:14
Чем больше блоков в чертеже, тем медленнее.
Я пробовал даже так:
Код - 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
То есть даже не перебирал свойства.
Результат такой же.
Название: Re: Учусь работать с динамическими блоками
Отправлено: vermesser от 03-07-2017, 14:17:54
То есть дело в моём случае не в количестве свойства.
Причем проблемы начинаются именно при получении DynamicBlockReferencePropertyCollection для блока.
Название: Re: Учусь работать с динамическими блоками
Отправлено: Дмитрий Загорулькин от 03-07-2017, 14:45:45
Код - 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
Название: Re: Учусь работать с динамическими блоками
Отправлено: vermesser от 03-07-2017, 19:38:56
Ваш код, мой файл:
Blocks: 672. Processing time: 34636.0349 ms

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

Чертовщина )))
Название: Re: Учусь работать с динамическими блоками
Отправлено: Дмитрий Загорулькин от 03-07-2017, 20:03:31
О, так ведь дело не в коде, а в блоке. Штриховка в блоке + размерные зависимости. Нужно переделывать блок.
Название: Re: Учусь работать с динамическими блоками
Отправлено: vermesser от 03-07-2017, 20:09:13
О, так ведь дело не в коде, а в блоке. Штриховка в блоке + размерные зависимости. Нужно переделывать блок.
Подскажите, пожалуйста, что именно нужно переделать?
Название: Re: Учусь работать с динамическими блоками
Отправлено: Дмитрий Загорулькин от 03-07-2017, 20:39:21
Нужно максимально упростить динамический блок. В первую очередь - удалить размерные зависимости. Чтобы в итоге получилось что-то типа такого.
У меня обрабатывает за 70 миллисекунд.
P.S. По сути, тут динпараметр "радиус" тоже лишний, т.к. можно просто менять масштаб блока. Можно оставить только параметр видимости.
Название: Re: Учусь работать с динамическими блоками
Отправлено: vermesser от 03-07-2017, 21:01:28
Нужно максимально упростить динамический блок. В первую очередь - удалить размерные зависимости. Чтобы в итоге получилось что-то типа такого.
У меня обрабатывает за 70 миллисекунд.
P.S. По сути, тут динпараметр "радиус" тоже лишний, т.к. можно просто менять масштаб блока. Можно оставить только параметр видимости.
Спасибо, сделаю.
А штриховку тоже рекомендуете убрать из блока?
Название: Re: Учусь работать с динамическими блоками
Отправлено: Дмитрий Загорулькин от 03-07-2017, 21:08:26
Да вроде штриховка не тормозит. Можно оставить, я думаю. Возможно только нужно будет сделать её не ассоциативной, как в моем примере
Название: Re: Учусь работать с динамическими блоками
Отправлено: vermesser от 04-07-2017, 23:58:47
Да вроде штриховка не тормозит. Можно оставить, я думаю. Возможно только нужно будет сделать её не ассоциативной, как в моем примере
Последовал вашим советам, всё работает очень быстро.
Не знаю, что бы делал без Вашей помощи.