Выбор точки вставки второго блока при объединение блоков

Автор Тема: Выбор точки вставки второго блока при объединение блоков  (Прочитано 4956 раз)

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

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

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
При объединение блоков я использовал эту статью - https://adn-cis.org/obedinenie-blokov-autocad-s-ispolzovaniem-.net-api.html
Подскажите пожалуйста, можно ли изменить координаты вставки второго блока.
Внизу блоки до объединения, вверху после




« Последнее редактирование: 18-06-2020, 20:38:31 от serhiy79 »

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
Там же простое копирование из блока в блок. Просто переставьте объекты которые копируются из нужных блоков в соответствии с матрицей вставки obj.TramsformBy(blockRef.BlockTransform). Можно использовать idMap чтоб понять какие объекты нужны.

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
И с учетом вашей проблемы, я бы использовал не DeepClone, а просто взрыв блока: BlockReference.Explode. Взорванные объекты уже будут на тех местах где был вставлен блок.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
И с учетом вашей проблемы, я бы использовал не DeepClone, а просто взрыв блока: BlockReference.Explode.
Хорошее решение для большинства случаев, кроме случая когда блок не расчленяется (разные масштабные коэффициенты и специфическое содержимое блоков). Надеюсь, что у serhiy79 не такой случай.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
На заметку тем, кто не взрывал блоки через API:
Исходный блок сохраняется без изменений, все объекты списка - это копии, которые еще надо сохранить в БД чертежа.
Метод Explode(DBObjectCollection) игнорирует метку Explodable - взрывает все. Если надо - проверяйте сами в коде.
Блоки с разными масштабными коэффициентами в большинстве случаев прекрасно взрываются именно так как и выглядят.
Но исключения все же могут быть вытолкнуты - стоит обработать.

А при сборке нового блока учтите внутреннюю систему координат блока. Если собирать как в том примере, то точка вставки блока окажется в нуле WCS. Как правило это не то, что хочется...

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
Просто переставьте объекты которые копируются из нужных блоков в соответствии с матрицей вставки obj.TramsformBy(blockRef.BlockTransform).
а можно пример какой нибудь пожалуйста

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

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

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

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

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
У тебя в обоих блоках одноимённые атрибуты. Что ты собираешься с ними делать? Удваивать их или одноимённые убирать?
одноименные нужно убирать
Забыл задать главный вопрос: "Зачем нужно объединять блоки?"
нужно оставить возможность редактирования атрибутов

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
serhiy79,
Попробуй сначала вариант с BlockReference.Explode для обеих вставок блоков. При этом ты получишь две коллекции примитивов и в том числе и определений атрибутов (AttributeDefinition). Те, у которых одинаковые AttributeDefinition.Tag, нужно будет исключить.
Если захочешь, чтобы точка начала блока (BlockTableRecord.Origin) отличалась от начала координат в МСК, тебе придётся выполнить преобразование в новую точку вставки (например в точку вставки одного из блоков).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение serhiy79 19-06-2020, 21:59:05

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
serhiy79,

Попробуй такой код:

Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using Autodesk.AutoCAD.Runtime;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Geometry;
  7. using Autodesk.AutoCAD.EditorInput;
  8.  
  9. [assembly: CommandClass(typeof(CombineBlocks.MyCommands))]
  10.  
  11. namespace CombineBlocks
  12. {
  13.   public class MyCommands
  14.   {
  15.     [CommandMethod("CombineBlocks")]
  16.     public void CombineBlocksHandler() // This method can have any name
  17.     {
  18.       Document doc = Application.DocumentManager.MdiActiveDocument;
  19.       if (doc == null) return;
  20.       Editor ed = doc.Editor;
  21.       Database db = doc.Database;
  22.       PromptEntityOptions prOpt =
  23.         new PromptEntityOptions("\nВыберите первый блок: ");
  24.       prOpt.SetRejectMessage("Это не блок!");
  25.       prOpt.AddAllowedClass(typeof(BlockReference), true);
  26.       PromptEntityResult per1 = ed.GetEntity(prOpt);
  27.       if (per1.Status != PromptStatus.OK) return;
  28.       prOpt.Message = "\nВыберите второй блок: ";
  29.  
  30.       PromptEntityResult per2 = ed.GetEntity(prOpt);
  31.       if (per2.Status != PromptStatus.OK) return;
  32.  
  33.       PromptPointResult ppr =
  34.           ed.GetPoint("\nУкажите точку вставки нового блока: ");
  35.       if (ppr.Status != PromptStatus.OK) return;
  36.  
  37.       Point3d pBase =
  38.         ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);
  39.  
  40.       PromptPointResult pprNew = ed.GetPoint("\nУкажите куда вставить этот блок: ");
  41.       if (pprNew.Status != PromptStatus.OK) return;
  42.       Point3d pIns = pprNew.Value.TransformBy(ed.CurrentUserCoordinateSystem);
  43.  
  44.       PromptStringOptions prsOpt =
  45.         new PromptStringOptions("\nУкажите имя нового блока: ");
  46.       prsOpt.AllowSpaces = true;
  47.       PromptResult rss;
  48.       string blockName = "";
  49.       while ((rss = ed.GetString(prsOpt)) != null && rss.Status == PromptStatus.OK)
  50.       {
  51.         blockName = rss.StringResult;
  52.         if (SymbolUtilityServices.ValidateCompatibleSymbolName(blockName, true, false, false) != ErrorStatus.OK)
  53.         {
  54.           ed.WriteMessage("\nНедопустимое имя блока!");
  55.           continue;
  56.         }
  57.         else break;
  58.       }
  59.  
  60.       if (rss.Status != PromptStatus.OK) return;
  61.  
  62.       using (OpenCloseTransaction tr = new OpenCloseTransaction())
  63.       {
  64.         BlockTable bt =
  65.           tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
  66.         if (bt.Has(blockName))
  67.         {
  68.           ed.WriteMessage("\nБлок с таким именем уже есть!");
  69.           tr.Commit();
  70.           return;
  71.         }
  72.  
  73.         BlockReference br1 = tr.GetObject(per1.ObjectId, OpenMode.ForRead) as BlockReference;
  74.         BlockReference br2 = tr.GetObject(per2.ObjectId, OpenMode.ForRead) as BlockReference;
  75.         DBObjectCollection col1 = new DBObjectCollection();
  76.         DBObjectCollection col2 = new DBObjectCollection();
  77.         DBObjectCollection col = new DBObjectCollection();
  78.         br1.Explode(col1); br2.Explode(col2);
  79.         List<string> tags = new List<string>();
  80.         foreach (DBObject obj in col1)
  81.         {
  82.           AttributeDefinition att = obj as AttributeDefinition;
  83.           if (att != null)
  84.           {
  85.             tags.Add(att.Tag);
  86.           }
  87.           col.Add(obj);
  88.         }
  89.         foreach (DBObject obj in col2)
  90.         {
  91.           AttributeDefinition att = obj as AttributeDefinition;
  92.           // Пропускаем одноименные атрибуты
  93.           if (att != null && tags.Contains(att.Tag)) continue;
  94.           col.Add(obj);
  95.         }
  96.         BlockTableRecord btr = new BlockTableRecord();
  97.         btr.Origin = Point3d.Origin;
  98.         btr.Name = blockName;
  99.         ObjectId btrId = bt.Add(btr);
  100.         tr.AddNewlyCreatedDBObject(btr, true);
  101.         foreach (DBObject obj in col)
  102.         {
  103.           Entity ent = obj as Entity;
  104.           if (ent != null)
  105.           {
  106.             Matrix3d mat = Matrix3d.Displacement(Point3d.Origin - pBase);
  107.             ent.TransformBy(mat);
  108.             btr.AppendEntity(ent);
  109.             tr.AddNewlyCreatedDBObject(ent, true);
  110.           }
  111.         }
  112.         BlockTableRecord space =
  113.           tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  114.         BlockReference br = new BlockReference(pIns, btrId);
  115.         space.AppendEntity(br);
  116.         tr.AddNewlyCreatedDBObject(br, true);
  117.         foreach (ObjectId id in btr)
  118.         {
  119.           DBObject obj = tr.GetObject(id, OpenMode.ForRead);
  120.  
  121.           if (obj is AttributeDefinition)
  122.           {
  123.             AttributeDefinition attDef = obj as AttributeDefinition;
  124.             if (!attDef.Constant)
  125.             {
  126.               using (AttributeReference attRef = new AttributeReference())
  127.               {
  128.                 attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
  129.                 br.AttributeCollection.AppendAttribute(attRef);
  130.                 tr.AddNewlyCreatedDBObject(attRef, true);
  131.               }
  132.             }
  133.           }
  134.         }
  135.         tr.Commit();
  136.       }
  137.     }
  138.   }
  139. }
  140.  

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
Александр Ривилис
Да, это то что нужно, Спасибо огромное!!!
Теперь буду внедрять его под свои нужды.

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

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