Создание блока с несколькими объектами внутри

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

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте!
Пытаюсь создать метод рисующий блок штампа основной надписи по гост с атрибутами. Проблема в том,что никак не могу сообразить как добавить все линии внутрь одной транзакции-автокад вылетает с ошибкой.


 
Код - C# [Выбрать]
  1. [CommandMethod("2title")]
  2.         public void DrawMainTitle()
  3.         {
  4.             Document acDoc = Application.DocumentManager.MdiActiveDocument;
  5.             Database acCurDb = acDoc.Database;
  6.             using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  7.             {
  8.                 BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  9.  
  10.                 ObjectId blkRecId = ObjectId.Null;
  11.  
  12.                 if (!acBlkTbl.Has("MainTitle"))
  13.                 {
  14.                     using (BlockTableRecord acBlkTblRec = new BlockTableRecord())
  15.                     {
  16.                         acBlkTblRec.Name = "MainTitle";
  17.  
  18.                         // Set the insertion point for the block
  19.                         acBlkTblRec.Origin = new Point3d(5, 5, 0);
  20.  
  21.  
  22.                         using (Polyline acPoly = new Polyline())
  23.                         {
  24.                             acPoly.AddVertexAt(0, new Point2d(0, 55), 0, 0, 0);
  25.                             acPoly.AddVertexAt(1, new Point2d(-185, 55), 0, 0, 0);
  26.                             acPoly.AddVertexAt(2, new Point2d(-185, 0), 0, 0, 0);
  27.                             acBlkTblRec.AppendEntity(acPoly);
  28.                         }
  29.  
  30.  
  31.                         using (Polyline acPoly1 = new Polyline())
  32.                         {
  33.                             acPoly1.AddVertexAt(0, new Point2d(5, 60), 0, 0, 0);
  34.                             acPoly1.AddVertexAt(1, new Point2d(-190, 60), 0, 0, 0);
  35.                             acPoly1.AddVertexAt(2, new Point2d(-190, 5), 0, 0, 0);
  36.                             acBlkTblRec.AppendEntity(acPoly1);
  37.  
  38.                         }
  39.  
  40.                         acBlkTbl.UpgradeOpen();
  41.                         acBlkTbl.Add(acBlkTblRec);
  42.                         acTrans.AddNewlyCreatedDBObject(acBlkTblRec, true);
  43.  
  44.  
  45.                         using (AttributeDefinition developer = new AttributeDefinition())
  46.                         {
  47.                             developer.Position = new Point3d(-167, 31, 0);
  48.                             developer.Prompt = "Developer";
  49.                             developer.Tag = "Developer";
  50.                             developer.TextString = "Сидоров";
  51.                             developer.Height = 3.5;
  52.                             developer.Justify = AttachmentPoint.BottomFit;
  53.                             acBlkTblRec.AppendEntity(developer);
  54.                         }
  55.                         blkRecId = acBlkTblRec.Id;
  56.                     }
  57.  
  58.                 }
  59.                 else
  60.                 {
  61.                     blkRecId = acBlkTbl["MainTitle"];
  62.                 }
  63.  
  64.  
  65.                 // Insert the block into the current space
  66.                 if (blkRecId != ObjectId.Null)
  67.                 {
  68.                     BlockTableRecord acBlkTblRec;
  69.                     acBlkTblRec = acTrans.GetObject(blkRecId, OpenMode.ForRead) as BlockTableRecord;
  70.  
  71.                     // Create and insert the new block reference
  72.                     using (BlockReference acBlkRef = new BlockReference(acBlkTblRec.Origin, blkRecId))
  73.                     {
  74.                         BlockTableRecord acCurSpaceBlkTblRec;
  75.                         acCurSpaceBlkTblRec = acTrans.GetObject(acCurDb.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  76.  
  77.                         acCurSpaceBlkTblRec.AppendEntity(acBlkRef);
  78.                         acTrans.AddNewlyCreatedDBObject(acBlkRef, true);
  79.  
  80.                         // Verify block table record has attribute definitions associated with it
  81.                         if (acBlkTblRec.HasAttributeDefinitions)
  82.                         {
  83.                             // Add attributes from the block table record
  84.                             foreach (ObjectId objID in acBlkTblRec)
  85.                             {
  86.                                 DBObject dbObj = acTrans.GetObject(objID, OpenMode.ForRead) as DBObject;
  87.  
  88.                                 if (dbObj is AttributeDefinition)
  89.                                 {
  90.                                     AttributeDefinition acAtt = dbObj as AttributeDefinition;
  91.  
  92.                                     if (!acAtt.Constant)
  93.                                     {
  94.                                         using (AttributeReference acAttRef = new AttributeReference())
  95.                                         {
  96.                                             acAttRef.SetAttributeFromBlock(acAtt, acBlkRef.BlockTransform);
  97.                                             acAttRef.Position = acAtt.Position.TransformBy(acBlkRef.BlockTransform);
  98.                                             acAttRef.TextString = acAtt.TextString;
  99.                                             acBlkRef.AttributeCollection.AppendAttribute(acAttRef);
  100.                                             acTrans.AddNewlyCreatedDBObject(acAttRef, true);
  101.                                         }
  102.                                     }
  103.                                 }
  104.                             }
  105.                         }
  106.                     }
  107.                 }
  108.  
  109.                 // Save the new object to the database
  110.                 acTrans.Commit();
  111.                
  112.             }
  113.  
  114.         }
  115.  
Как правильно обеспечить запись в блок всех линий штампа?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
автокад вылетает с ошибкой.
Fatal Error или просто Exception? И если Exception то какой?
И кстати бездумное использование using в выражениях типа
Код - C# [Выбрать]
  1. using (Polyline acPoly1 = new Polyline())
ни к чему хорошему не приведут.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1

Такая ошибка.


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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Такая ошибка.
Убери все лишние using'и.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Прошу пояснить - как определить лишние? Я только осваиваю программирование.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Прошу пояснить - как определить лишние? Я только осваиваю программирование.
Оставь только using у транзакции (Transaction). Остальные убери. Т.е. вместо:
Код - C# [Выбрать]
  1.                         using (Polyline acPoly = new Polyline())
  2.                         {
  3.                             acPoly.AddVertexAt(0, new Point2d(0, 55), 0, 0, 0);
  4.                             acPoly.AddVertexAt(1, new Point2d(-185, 55), 0, 0, 0);
  5.                             acPoly.AddVertexAt(2, new Point2d(-185, 0), 0, 0, 0);
  6.                             acBlkTblRec.AppendEntity(acPoly);
  7.                         }
должно быть:
Код - C# [Выбрать]
  1.                            Polyline acPoly = new Polyline();
  2.  
  3.                             acPoly.AddVertexAt(0, new Point2d(0, 55), 0, 0, 0);
  4.                             acPoly.AddVertexAt(1, new Point2d(-185, 55), 0, 0, 0);
  5.                             acPoly.AddVertexAt(2, new Point2d(-185, 0), 0, 0, 0);
  6.                             acBlkTblRec.AppendEntity(acPoly);
  7.  
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Понял. А в принципе ход моей мысли по построению штампа по линиям поштучно верный или есть более правильный метод?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А в принципе ход моей мысли по построению штампа по линиям поштучно верный или есть более правильный метод?
Правильный способ - иметь готовый блок (в dwg-файле) и вставлять его программно. Такой способ намного универсальнее.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Для блоков с атрибутами такой способ тоже подходит?

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
После удаления using чертеж перестал сохраняться.


Отмечено как Решение Александр Ривилис 13-05-2018, 21:42:43

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Вот исправленный твой код. Я просто заставил его работать не вдаваясь в то, что получается.

Код - C# [Выбрать]
  1. [CommandMethod("2title")]
  2. public void DrawMainTitle()
  3. {
  4.   Document acDoc = Application.DocumentManager.MdiActiveDocument;
  5.   Database acCurDb = acDoc.Database;
  6.   using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  7.   {
  8.     BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  9.  
  10.     ObjectId blkRecId = ObjectId.Null;
  11.  
  12.     if (!acBlkTbl.Has("MainTitle"))
  13.     {
  14.       BlockTableRecord acBlkTblRec = new BlockTableRecord();
  15.       acBlkTblRec.Name = "MainTitle";
  16.  
  17.       // Set the insertion point for the block
  18.       acBlkTblRec.Origin = new Point3d(5, 5, 0);
  19.       acBlkTbl.UpgradeOpen();
  20.       acBlkTbl.Add(acBlkTblRec);
  21.       acTrans.AddNewlyCreatedDBObject(acBlkTblRec, true);
  22.  
  23.       Polyline acPoly = new Polyline();
  24.       acPoly.SetDatabaseDefaults();
  25.       acPoly.AddVertexAt(0, new Point2d(0, 55), 0, 0, 0);
  26.       acPoly.AddVertexAt(1, new Point2d(-185, 55), 0, 0, 0);
  27.       acPoly.AddVertexAt(2, new Point2d(-185, 0), 0, 0, 0);
  28.       acBlkTblRec.AppendEntity(acPoly);
  29.       acTrans.AddNewlyCreatedDBObject(acPoly, true);
  30.  
  31.       Polyline acPoly1 = new Polyline();
  32.       acPoly1.SetDatabaseDefaults();
  33.       acPoly1.AddVertexAt(0, new Point2d(5, 60), 0, 0, 0);
  34.       acPoly1.AddVertexAt(1, new Point2d(-190, 60), 0, 0, 0);
  35.       acPoly1.AddVertexAt(2, new Point2d(-190, 5), 0, 0, 0);
  36.       acBlkTblRec.AppendEntity(acPoly1);
  37.       acTrans.AddNewlyCreatedDBObject(acPoly1, true);
  38.  
  39.       AttributeDefinition developer = new AttributeDefinition();
  40.       developer.Position = new Point3d(-167, 31, 0);
  41.       developer.Prompt = "Developer";
  42.       developer.Tag = "Developer";
  43.       developer.TextString = "Сидоров";
  44.       developer.Height = 3.5;
  45.       developer.Justify = AttachmentPoint.BottomFit;
  46.       acBlkTblRec.AppendEntity(developer);
  47.       acTrans.AddNewlyCreatedDBObject(developer, true);
  48.       blkRecId = acBlkTblRec.Id;
  49.  
  50.     }
  51.     else
  52.     {
  53.       blkRecId = acBlkTbl["MainTitle"];
  54.     }
  55.  
  56.     // Insert the block into the current space
  57.     if (blkRecId != ObjectId.Null)
  58.     {
  59.       BlockTableRecord acBlkTblRec;
  60.       acBlkTblRec = acTrans.GetObject(blkRecId, OpenMode.ForRead) as BlockTableRecord;
  61.  
  62.       // Create and insert the new block reference
  63.       BlockReference acBlkRef = new BlockReference(acBlkTblRec.Origin, blkRecId);
  64.       acBlkRef.SetDatabaseDefaults();
  65.  
  66.       BlockTableRecord acCurSpaceBlkTblRec;
  67.       acCurSpaceBlkTblRec = acTrans.GetObject(acCurDb.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  68.  
  69.       acCurSpaceBlkTblRec.AppendEntity(acBlkRef);
  70.       acTrans.AddNewlyCreatedDBObject(acBlkRef, true);
  71.  
  72.       // Verify block table record has attribute definitions associated with it
  73.       if (acBlkTblRec.HasAttributeDefinitions)
  74.       {
  75.         // Add attributes from the block table record
  76.         foreach (ObjectId objID in acBlkTblRec)
  77.         {
  78.           DBObject dbObj = acTrans.GetObject(objID, OpenMode.ForRead) as DBObject;
  79.  
  80.           if (dbObj is AttributeDefinition)
  81.           {
  82.             AttributeDefinition acAtt = dbObj as AttributeDefinition;
  83.  
  84.             if (!acAtt.Constant)
  85.             {
  86.               AttributeReference acAttRef = new AttributeReference();
  87.               acAttRef.SetAttributeFromBlock(acAtt, acBlkRef.BlockTransform);
  88.               acAttRef.Position = acAtt.Position.TransformBy(acBlkRef.BlockTransform);
  89.               acAttRef.TextString = acAtt.TextString;
  90.               acBlkRef.AttributeCollection.AppendAttribute(acAttRef);
  91.               acTrans.AddNewlyCreatedDBObject(acAttRef, true);
  92.             }
  93.           }
  94.         }
  95.       }
  96.     }
  97.  
  98.     // Save the new object to the database
  99.     acTrans.Commit();
  100.  
  101.   }
  102.  
  103. }
  104.  
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
После удаления using чертеж перестал сохраняться.


После моих исправлений сохраняется. У тебя не хватало нескольких вызовов acTrans.AddNewlyCreatedDBObject(...) и сначала следует добавлять BlockTableRecord в BlockTable, а уже потом добавлять примитивы в BlockTableRecord.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
и сначала следует добавлять BlockTableRecord в BlockTable, а уже потом добавлять примитивы в BlockTableRecord.

Каждая линия это отдельная BlockTableRecord? Или одна BlockTableRecord может быть для нескольких линий?

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

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