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

ADN Club => AutoCAD .NET API => Тема начата: Lemieux от 07-02-2020, 18:17:46

Название: Мульти вставка блоков
Отправлено: Lemieux от 07-02-2020, 18:17:46
Приветствую всех.
Я пытаюсь сделать так, чтобы в чертёж вставлялось несколько блоков, их можно было интерактивно перемещать, но при этом, в конце всех манипуляция с перемещением они так и остались отдельными блоками. Для этого я использую DrawJig. Сначала вставляю блоки в чертёж, составляю их список (list<>), потом этот список передаю в DrawJig. Всё нормально, но можно ли отключить показ старого положения объектов, во время перемещения объектов в чертеже?
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 07-02-2020, 18:19:55
Lemieux,
Теоретически, установив исходным вставкам свойство Visible в false можно скрыть оригиналы.
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 07-02-2020, 18:24:42
Lemieux,
Теоретически, установив исходным вставкам свойство Visible в false можно скрыть оригиналы.
Интересное решение, сейчас поэкспериментирую :)
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 07-02-2020, 18:26:05
Lemieux,
Теоретически, установив исходным вставкам свойство Visible в false можно скрыть оригиналы.
Интересное решение, сейчас поэкспериментирую :)
Но DrawJig нужно передавать, не сами вставки с Visiable == false, а их клоны с Visible == true
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 07-02-2020, 23:11:31
Lemieux,
Теоретически, установив исходным вставкам свойство Visible в false можно скрыть оригиналы.
Интересное решение, сейчас поэкспериментирую :)
Но DrawJig нужно передавать, не сами вставки с Visiable == false, а их клоны с Visible == true
Что-то не получается у меня. Что интересно, что в любом месте кода, когда делаю вставки блока visiable = false, то исчезают не изначальные объекты, а те, что перемещаются за курсором.
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 08-02-2020, 00:11:57
Что-то не получается у меня. Что интересно, что в любом месте кода, когда делаю вставки блока visiable = false, то исчезают не изначальные объекты, а те, что перемещаются за курсором.
Будем гадать на кофейной гуще или предоставишь нормальный тестовый проект?
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 08-02-2020, 10:07:15
Что-то не получается у меня. Что интересно, что в любом месте кода, когда делаю вставки блока visiable = false, то исчезают не изначальные объекты, а те, что перемещаются за курсором.
Будем гадать на кофейной гуще или предоставишь нормальный тестовый проект?
Не будем гадать :) Сразу скажу, что это не моё произведение, а части кода собраны из источников интернета и адаптированы друг для друга. И, иногда, возникает проблема, что атрибуты блоков, по координате Х, остаются в нуле. Но я так и не понял закономерность этого явления.

Код - C# [Выбрать]
  1. using System.Collections.Generic;
  2.  
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Runtime;
  6. using Autodesk.AutoCAD.EditorInput;
  7. using Autodesk.AutoCAD.Geometry;
  8. using Autodesk.AutoCAD.GraphicsInterface;
  9.  
  10. namespace Multiply_Insert
  11. {
  12.     public class Commands
  13.     {
  14.         [CommandMethod("LMXMULTIPLYINSERT")]
  15.         public void lmxInsertBlock()
  16.         {
  17.             Document lxDocument = Application.DocumentManager.MdiActiveDocument;
  18.             Database lxDatabase = Application.DocumentManager.MdiActiveDocument.Database;
  19.             Editor lxEditor = Application.DocumentManager.MdiActiveDocument.Editor;
  20.             ObjectId lxBlockID;
  21.  
  22.             string FullPath = "D:\\test.dwg";
  23.             System.IO.FileInfo lxFile = new System.IO.FileInfo(FullPath);
  24.             string BlockName = lxFile.Name;
  25.             double lx = 0;
  26.             Point3d lxBlockInsertPoint = new Point3d(lx, 0, 0);
  27.             List<BlockReference> lxBlockReferenceCollect = new List<BlockReference>();
  28.  
  29.             int i = 0;
  30.             while(i < 6)
  31.             {
  32.                 using (Transaction lxTransaction = lxDatabase.TransactionManager.StartTransaction())
  33.                 {
  34.                     using (Database lxTempDatabase = new Database(false, true))
  35.                     {
  36.                         BlockTable lxBlockTable = lxTransaction.GetObject(lxDatabase.BlockTableId, OpenMode.ForWrite, false) as BlockTable;
  37.                         if (!lxBlockTable.Has(BlockName))
  38.                         {
  39.                             lxTempDatabase.ReadDwgFile(FullPath, System.IO.FileShare.Read, true, null);
  40.                             lxBlockID = lxDatabase.Insert(BlockName, lxTempDatabase, true);
  41.                         }
  42.                         else
  43.                         {
  44.                             lxBlockID = lxBlockTable[BlockName];
  45.                         }
  46.                     }
  47.  
  48.                     lxTransaction.Commit();
  49.                 }
  50.  
  51.                 using (Transaction lxTransaction = lxDatabase.TransactionManager.StartTransaction())
  52.                 {
  53.                     BlockTable lxBlockTable = lxTransaction.GetObject(lxDatabase.BlockTableId, OpenMode.ForRead) as BlockTable;
  54.                     BlockTableRecord lxBlock = lxBlockTable[BlockName].GetObject(OpenMode.ForRead) as BlockTableRecord;
  55.                     BlockReference lxBlockReference = new BlockReference(lxBlockInsertPoint, lxBlockID);
  56.                     BlockTableRecord lxBlockTableRecord = lxTransaction.GetObject(lxBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  57.                     lxBlockTableRecord.AppendEntity(lxBlockReference);
  58.                     lxTransaction.AddNewlyCreatedDBObject(lxBlockReference, true);
  59.  
  60.                     foreach (ObjectId lxID in lxBlock)
  61.                     {
  62.                         DBObject lxObject = lxID.GetObject(OpenMode.ForRead);
  63.                         AttributeDefinition lxAttributeDefenition = lxObject as AttributeDefinition;
  64.                         if ((lxAttributeDefenition != null) && (!lxAttributeDefenition.Constant))
  65.                         {
  66.                             using (AttributeReference lxAttributeReference = new AttributeReference())
  67.                             {
  68.                                 lxAttributeReference.SetAttributeFromBlock(lxAttributeDefenition, lxBlockReference.BlockTransform);
  69.                                 lxBlockReference.AttributeCollection.AppendAttribute(lxAttributeReference);
  70.                                 lxTransaction.AddNewlyCreatedDBObject(lxAttributeReference, true);
  71.                             }
  72.                         }
  73.                     }
  74.  
  75.                     lxBlockReferenceCollect.Add(lxBlockReference);
  76.                     lxTransaction.Commit();
  77.                 }
  78.                 lx = lx + 5;
  79.                 i++;
  80.                 lxBlockInsertPoint = new Point3d(lx, 0, 0);
  81.             }
  82.  
  83.             try
  84.             {
  85.                 lmxDrawJig lxJig = new lmxDrawJig(new Point3d(0, 0, 0));
  86.                 using (Transaction lxTrasaction = lxDatabase.TransactionManager.StartTransaction())
  87.                 {
  88.                     foreach (BlockReference lxObject in lxBlockReferenceCollect)
  89.                     {
  90.                         BlockReference lxBlockReference = lxTrasaction.GetObject(lxObject.ObjectId, OpenMode.ForWrite) as BlockReference;
  91.                         lxJig.AddEntity(lxBlockReference);
  92.                     }
  93.  
  94.                     PromptResult lxPromptResult = Application.DocumentManager.MdiActiveDocument.Editor.Drag(lxJig);
  95.                     if (lxPromptResult.Status == PromptStatus.OK)
  96.                     {
  97.                         lxJig.TransformEntities();
  98.                         lxTrasaction.Commit();
  99.                     }
  100.                     else
  101.                         lxTrasaction.Abort();
  102.                 }
  103.             }
  104.             catch (System.Exception ex)
  105.             {
  106.                 Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
  107.             }
  108.         }
  109.  
  110.         class lmxDrawJig : DrawJig
  111.         {
  112.             private Point3d lxOriginPoint;
  113.             private Point3d lxNewPoint;
  114.             List<BlockReference> lxReferenceCollect;
  115.  
  116.             public lmxDrawJig(Point3d basePt)
  117.             {
  118.                 lxOriginPoint = basePt.TransformBy(UCS);
  119.                 lxReferenceCollect = new List<BlockReference>();
  120.             }
  121.  
  122.             public Point3d Base
  123.             {
  124.                 get { return lxNewPoint; }
  125.                 set { lxNewPoint = value; }
  126.             }
  127.  
  128.             public Point3d Location
  129.             {
  130.                 get { return lxNewPoint; }
  131.                 set { lxNewPoint = value; }
  132.             }
  133.  
  134.             public Matrix3d UCS
  135.             {
  136.                 get
  137.                 {
  138.                     return Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem;
  139.                 }
  140.             }
  141.  
  142.             public void AddEntity(BlockReference lxRef)
  143.             {
  144.                 lxReferenceCollect.Add(lxRef);
  145.             }
  146.  
  147.             public void TransformEntities()
  148.             {
  149.                 Matrix3d lxMatrix = Matrix3d.Displacement(lxOriginPoint.GetVectorTo(lxNewPoint));
  150.  
  151.                 foreach (BlockReference lxObject in lxReferenceCollect)
  152.                 {
  153.                     lxObject.TransformBy(lxMatrix);
  154.                 }
  155.             }
  156.  
  157.             protected override bool WorldDraw(WorldDraw lxDraw)
  158.             {
  159.                 Matrix3d lxMatrix = Matrix3d.Displacement(lxOriginPoint.GetVectorTo(lxNewPoint));
  160.  
  161.                 WorldGeometry lxGeometry = lxDraw.Geometry;
  162.                 if (lxGeometry != null)
  163.                 {
  164.                     lxGeometry.PushModelTransform(lxMatrix);
  165.                     foreach (BlockReference ent in lxReferenceCollect)
  166.                     {
  167.                         ent.Visible = true;
  168.                         lxGeometry.Draw(ent);
  169.                     }
  170.                     lxGeometry.PopModelTransform();
  171.                 }
  172.                 return true;
  173.             }
  174.  
  175.             protected override SamplerStatus Sampler(JigPrompts lxPrompts)
  176.             {
  177.                 JigPromptPointOptions lxPPO = new JigPromptPointOptions("\nNew location:");
  178.                 lxPPO.UseBasePoint = false;
  179.  
  180.                 PromptPointResult lxPointResult = lxPrompts.AcquirePoint(lxPPO);
  181.                 if (lxPointResult.Status == PromptStatus.Cancel || lxPointResult.Status == PromptStatus.Error)
  182.                     return SamplerStatus.Cancel;
  183.  
  184.                 if (!lxNewPoint.IsEqualTo(lxPointResult.Value, new Tolerance(10e-10, 10e-10)))
  185.                 {
  186.                     lxNewPoint = lxPointResult.Value;
  187.                     return SamplerStatus.OK;
  188.                 }
  189.                 else return SamplerStatus.NoChange;
  190.             }
  191.         }
  192.     }
  193. }
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 08-02-2020, 13:36:02
Lemieux,
Я же сказал что нужно в Jig передавать не сами объекты, а их клоны. И еще ты пытаешься работать с объектами, открытыми в транзакции, после того как транзакция завершена. Это недопустимо. Fatal Error тебе обеспечено.
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 08-02-2020, 18:46:01
Я же сказал что нужно в Jig передавать не сами объекты, а их клоны.
Как это сделать?
И еще ты пытаешься работать с объектами, открытыми в транзакции, после того как транзакция завершена.
Работает код нормально, без фатала. А в каком месте я так работаю?
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 08-02-2020, 21:07:27
А в каком месте я так работаю?
Строка 75 кода. После lxTrasaction.Commit() все BlockReference в lxBlockReferenceCollect становятся недействительными. Поэтому используй не
List<BlockReference>, а List<ObjectId>.
Как это сделать?
Если с строке 91 заменить lxBlockReference на lxBlockReference.Clone() то будет то, что я имел в виду.
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 08-02-2020, 23:47:06
Строка 75 кода. После lxTrasaction.Commit() все BlockReference в lxBlockReferenceCollect становятся недействительными.
Понял. Но каким-то образом я беру их id в следующей транзакции.
Если с строке 91 заменить lxBlockReference на lxBlockReference.Clone() то будет то, что я имел в виду.
Всё сделал, но когда указываю точку вставки, то что двигалось за курсором исчезает.

Я решил так. После строки 75 добавил
Код - C# [Выбрать]
  1. lxBlockReference.Visible = false;
а после строки 166 добавил
Код - C# [Выбрать]
  1. ent.Visible = true;
клонировать не стал, оставил как есть
Код - C# [Выбрать]
  1. lxJig.AddEntity(lxBlockReference);
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 09-02-2020, 00:16:33
клонировать не стал, оставил как есть
Это очень плохо. Еще раз. Нельзя пользоваться объектами, открытыми в транзакции, вне этой транзакции. Это аксиома.
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 09-02-2020, 00:21:18
Это очень плохо. Еще раз. Нельзя пользоваться объектами, открытыми в транзакции, вне этой транзакции. Это аксиома.
Так если я клонирую, то не работает.
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 09-02-2020, 00:22:16
Всё сделал, но когда указываю точку вставки, то что двигалось за курсором исчезает.
Конечно исчезнет. Клоны не содержатся в чертеже. После указания точки вставки ты должен их вставить в чертеж, т.е.  lxBlockTableRecord.AppendEntity(lxBlockReference), а затем lxBlockReference.Close()), а оригиналы стереть (метод Erase)
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 09-02-2020, 09:58:19
lxBlockReference.Close()
VS studio пишет, что "Use transaction instead", хотя в хелпе я ничего не нашёл про эту фичу.

lxBlockTableRecord.AppendEntity(lxBlockReference)
AutoCAD пишет, что объект уже существует.
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 09-02-2020, 15:57:13
Цитата: Александр Ривилис от 08-02-2020, 23:22:16

    lxBlockReference.Close()

VS studio пишет, что "Use transaction instead", хотя в хелпе я ничего не нашёл про эту фичу.
Не обращай внимание на это сообщение. Или вставь в начало файла, чтобы это сообщение не появлялось:
Код - C# [Выбрать]
  1. #pragma warning disable 0618

Цитата: Александр Ривилис от 08-02-2020, 23:22:16

    lxBlockTableRecord.AppendEntity(lxBlockReference)

AutoCAD пишет, что объект уже существует.
Это для клона нужно выполнять, а не для оригинала, который уже и так в базе.
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 10-02-2020, 00:26:57
Цитата: Александр Ривилис от 08-02-2020, 23:22:16

    lxBlockReference.Close()

VS studio пишет, что "Use transaction instead", хотя в хелпе я ничего не нашёл про эту фичу.
Не обращай внимание на это сообщение. Или вставь в начало файла, чтобы это сообщение не появлялось:
Код - C# [Выбрать]
  1. #pragma warning disable 0618

Цитата: Александр Ривилис от 08-02-2020, 23:22:16

    lxBlockTableRecord.AppendEntity(lxBlockReference)

AutoCAD пишет, что объект уже существует.
Это для клона нужно выполнять, а не для оригинала, который уже и так в базе.
Спасибо Александр, завтра буду экспериментировать. Прям какая-то битва с этой вставкой.
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 12-02-2020, 01:32:53
Провёл я эксперименты, вроде вставить клон получилось и удалить оригиналы, но закрыть объект не получилось, AutoCAD вылетает с ошибкой доступа к памяти. Вот новый вариант кода.

Код - C# [Выбрать]
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Runtime;
  7. using Autodesk.AutoCAD.EditorInput;
  8. using Autodesk.AutoCAD.Geometry;
  9. using Autodesk.AutoCAD.GraphicsInterface;
  10.  
  11. namespace Multiply_Insert
  12. {
  13.     public class Commands
  14.     {
  15.         [CommandMethod("LMXMULTIPLYINSERT")]
  16.         public void lmxMultiplyInsert()
  17.         {
  18.             List<string> lxCollection = new List<string>();
  19.             lxCollection.Add("D:\\Test_1.dwg");
  20.             for (int i=0; i<4; i++)
  21.             {
  22.                 lxCollection.Add("D:\\Test_2.dwg");
  23.                 lxCollection.Add("D:\\Test_3.dwg");
  24.                 lxCollection.Add("D:\\Test_4.dwg");
  25.                 lxCollection.Add("D:\\Test_5.dwg");
  26.             }
  27.             lmxInsertBlock(lxCollection, "A1", "00");
  28.         }
  29.            
  30.  
  31.         private void lmxInsertBlock(List<string> lCollection, string lPosition, string lSlot)
  32.         {
  33.             Database lxDatabase = Application.DocumentManager.MdiActiveDocument.Database;
  34.             Editor lxEditor = Application.DocumentManager.MdiActiveDocument.Editor;
  35.             ObjectId lxBlockID;
  36.             Point3d lxBlockInsertPoint = new Point3d(0, 0, 0);
  37.             List<ObjectId> lxIDCollect = new List<ObjectId>();
  38.             double lx = (-8*3)+1.5;
  39.  
  40.             int lxCountChar = lSlot.Length;
  41.  
  42.             foreach (string lxPath in lCollection)
  43.             {
  44.                 string BlockName = Path.GetFileNameWithoutExtension(lxPath);
  45.  
  46.                 using (Transaction lxTransaction = lxDatabase.TransactionManager.StartTransaction())
  47.                 {
  48.                     BlockTable lxBlockTable = lxTransaction.GetObject(lxDatabase.BlockTableId, OpenMode.ForWrite, false) as BlockTable;
  49.                     if (!lxBlockTable.Has(BlockName))
  50.                     {
  51.                         Database lxTempDatabaseChassis = new Database(false, true);
  52.                         lxTempDatabaseChassis.ReadDwgFile(lxPath, FileShare.Read, true, null);
  53.                         lxBlockID = lxDatabase.Insert(BlockName, lxTempDatabaseChassis, true);
  54.                     }
  55.                     else { lxBlockID = lxBlockTable[BlockName]; }
  56.  
  57.                     lxTransaction.Commit();
  58.                 }
  59.  
  60.                 using (Transaction lxTransaction = lxDatabase.TransactionManager.StartTransaction())
  61.                 {
  62.                     BlockTable lxBlockTable = lxTransaction.GetObject(lxDatabase.BlockTableId, OpenMode.ForWrite, false) as BlockTable;
  63.                     BlockTableRecord lxBlock = lxBlockTable[BlockName].GetObject(OpenMode.ForRead) as BlockTableRecord;
  64.                     BlockTableRecord lxModelSpace = lxTransaction.GetObject(lxBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  65.                     BlockReference lxBlockReference = new BlockReference(lxBlockInsertPoint, lxBlockID);
  66.                     lxModelSpace.AppendEntity(lxBlockReference);
  67.                     lxTransaction.AddNewlyCreatedDBObject(lxBlockReference, true);
  68.                     lxIDCollect.Add(lxBlockReference.ObjectId);
  69.                     foreach (ObjectId lxID in lxBlock)
  70.                     {
  71.                         DBObject lxObject = lxID.GetObject(OpenMode.ForRead);
  72.                         AttributeDefinition lxAttributeDefenition = lxObject as AttributeDefinition;
  73.                         if ((lxAttributeDefenition != null) && (!lxAttributeDefenition.Constant))
  74.                         {
  75.                             using (AttributeReference lxAttributeReference = new AttributeReference())
  76.                             {
  77.                                 lxAttributeReference.SetAttributeFromBlock(lxAttributeDefenition, lxBlockReference.BlockTransform);
  78.                                 lxBlockReference.AttributeCollection.AppendAttribute(lxAttributeReference);
  79.                                 lxTransaction.AddNewlyCreatedDBObject(lxAttributeReference, true);
  80.                             }
  81.                         }
  82.                     }
  83.                     AttributeCollection lxAttributeCollection = lxBlockReference.AttributeCollection;
  84.                     ObjectId lxAttrRef = lxAttributeCollection[0];
  85.                     AttributeReference lxAttr = lxAttrRef.GetObject(OpenMode.ForRead) as AttributeReference;
  86.                     string lxTextString = lxAttr.TextString;
  87.                     if (lxTextString.Contains("-"))
  88.                     {
  89.                         lxAttr = lxAttrRef.GetObject(OpenMode.ForWrite) as AttributeReference;
  90.                         lxAttr.TextString = $"{lPosition}-{lSlot}";
  91.                         lSlot = (Convert.ToInt32(lSlot) + 1).ToString($"D{lxCountChar}");
  92.                     }
  93.                     else
  94.                     {
  95.                         lxAttr = lxAttrRef.GetObject(OpenMode.ForWrite) as AttributeReference;
  96.                         lxAttr.TextString = $"{lPosition}";
  97.                     }
  98.                     lxBlockReference.Visible = false;
  99.  
  100.                     lxTransaction.Commit();
  101.                 }
  102.                 if(lx == -22.5) { lx = -22.5; }
  103.                 lxBlockInsertPoint = new Point3d(lx, 16.615, 0);
  104.                 lx = lx + 3;
  105.             }
  106.  
  107.             using (Transaction lxTransaction = lxDatabase.TransactionManager.StartTransaction())
  108.             {
  109.                 lmxDrawJig lxJig = new lmxDrawJig(new Point3d(0, 0, 0));
  110.  
  111.                 foreach (ObjectId lxID in lxIDCollect)
  112.                 {
  113.                     BlockReference lxBlockReference = lxTransaction.GetObject(lxID, OpenMode.ForWrite) as BlockReference;
  114.                     lxJig.AddEntity(lxBlockReference.Clone());
  115.                 }
  116.  
  117.                 PromptResult lxPromptResult = Application.DocumentManager.MdiActiveDocument.Editor.Drag(lxJig);
  118.                 if (lxPromptResult.Status == PromptStatus.OK)
  119.                 {
  120.                     foreach (ObjectId lxID in lxIDCollect)
  121.                     {
  122.                         BlockReference lxBlockReference = lxTransaction.GetObject(lxID, OpenMode.ForWrite) as BlockReference;
  123.                         lxBlockReference.Erase();
  124.                     }
  125.                     lxJig.TransformEntities();
  126.                     lxTransaction.Commit();
  127.                 }
  128.                 else lxTransaction.Abort();
  129.             }
  130.         }
  131.  
  132.         class lmxDrawJig : DrawJig
  133.         {
  134.             private Point3d lxOriginPoint;
  135.             private Point3d lxNewPoint;
  136.             List<object> lxReferenceCollect;
  137.  
  138.             public lmxDrawJig(Point3d basePt)
  139.             {
  140.                 lxOriginPoint = basePt.TransformBy(UCS);
  141.                 lxReferenceCollect = new List<object>();
  142.             }
  143.  
  144.             public Point3d Base
  145.             {
  146.                 get { return lxNewPoint; }
  147.                 set { lxNewPoint = value; }
  148.             }
  149.  
  150.             public Point3d Location
  151.             {
  152.                 get { return lxNewPoint; }
  153.                 set { lxNewPoint = value; }
  154.             }
  155.  
  156.             public Matrix3d UCS
  157.             {
  158.                 get
  159.                 {
  160.                     return Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem;
  161.                 }
  162.             }
  163.  
  164.             public void AddEntity(object lxRef)
  165.             {
  166.                 lxReferenceCollect.Add(lxRef);
  167.             }
  168.  
  169.             public void TransformEntities()
  170.             {
  171.                 Matrix3d lxMatrix = Matrix3d.Displacement(lxOriginPoint.GetVectorTo(lxNewPoint));
  172.                 Database lxDatabase = Application.DocumentManager.MdiActiveDocument.Database;
  173.  
  174.                 using (Transaction lxTransaction = lxDatabase.TransactionManager.StartTransaction())
  175.                 {
  176.                     BlockTable lxBlockTable = lxTransaction.GetObject(lxDatabase.BlockTableId, OpenMode.ForWrite, false) as BlockTable;
  177.                     BlockTableRecord lxModelSpace = lxTransaction.GetObject(lxBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  178.                     foreach (BlockReference lxObject in lxReferenceCollect)
  179.                     {
  180.                         lxModelSpace.AppendEntity(lxObject);
  181.                         lxObject.TransformBy(lxMatrix);
  182.                     }
  183.  
  184.                     lxTransaction.Commit();
  185.                 }
  186.             }
  187.  
  188.             protected override bool WorldDraw(WorldDraw lxDraw)
  189.             {
  190.                 Matrix3d lxMatrix = Matrix3d.Displacement(lxOriginPoint.GetVectorTo(lxNewPoint));
  191.  
  192.                 WorldGeometry lxGeometry = lxDraw.Geometry;
  193.                 if (lxGeometry != null)
  194.                 {
  195.                     lxGeometry.PushModelTransform(lxMatrix);
  196.                     foreach (BlockReference lxObject in lxReferenceCollect)
  197.                     {
  198.                         lxObject.Visible = true;
  199.                         lxGeometry.Draw(lxObject);
  200.                     }
  201.                     lxGeometry.PopModelTransform();
  202.                 }
  203.                 return true;
  204.             }
  205.  
  206.             protected override SamplerStatus Sampler(JigPrompts lxPrompts)
  207.             {
  208.                 JigPromptPointOptions lxPPO = new JigPromptPointOptions("\nNew location:");
  209.                 lxPPO.UseBasePoint = false;
  210.  
  211.                 PromptPointResult lxPointResult = lxPrompts.AcquirePoint(lxPPO);
  212.                 if (lxPointResult.Status == PromptStatus.Cancel || lxPointResult.Status == PromptStatus.Error)
  213.                     return SamplerStatus.Cancel;
  214.  
  215.                 if (!lxNewPoint.IsEqualTo(lxPointResult.Value, new Tolerance(10e-10, 10e-10)))
  216.                 {
  217.                     lxNewPoint = lxPointResult.Value;
  218.                     return SamplerStatus.OK;
  219.                 }
  220.                 else return SamplerStatus.NoChange;
  221.             }
  222.         }
  223.     }
  224. }
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 12-02-2020, 01:43:26
Для начала подумай что не так в методе TransformEntities.
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 12-02-2020, 01:48:14
Для начала подумай что не так в методе TransformEntities.
Александр, я даже не могу предположить, так как этот код работает. Я из этого метода как раз убрал lxObject.Close(), чтобы AutoCAD не вылетал с критом. Или надо lxObject открыть для записи?
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 12-02-2020, 01:50:15
Александр, я даже не могу предположить, так как этот код работает.
Так предположи. Не надо гадать. Нужно понять что происходит, иначе ничему не начишься.
Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 12-02-2020, 08:50:01
Нужно понять что происходит, иначе ничему не начишься.
Я пытаюсь понять как всё это работает, но как-то плохо получается. Я предположил, что надо открыть lxObject для записи.
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 12-02-2020, 11:41:22
Я предположил, что надо открыть lxObject для записи.
Предположение неправильное. Открывать для записи нужно объекты, которые уже в базе, а его там еще нет.
1. Зачем ты открываешь BlockTable для записи если не модифицируешь его?
2. У тебя не хватает lxTransaction.AddNewlyCreatedDBObject(lxObject, true) после lxModelSpace.AppendEntity(lxObject); и соответственно транзакция не закроет lxObject, так как не знает о нём. Знает она только объектах, которые открыты через Transaction.GetObject или добавлены к транзакции через Transaction.AddNewlyCreatedDBObject и соответственно закрывает их при Transaction.Commit.
3. С атрибутами блоков у тебя совсем плохо - нет никакого понимания. Ты хоть примеры готовые поищи и посмотри.
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 12-02-2020, 13:43:50
Вот тебе заготовка. Я переименовывал многие переменные и методы, так как стиль имён, которые у тебя, я не могу воспринимать.
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.GraphicsInterface;
  6. using Autodesk.AutoCAD.Runtime;
  7. using System.Collections.Generic;
  8. using System.IO;
  9.  
  10. namespace MultiInsert
  11. {
  12.   public class Commands
  13.   {
  14.     [CommandMethod("LMXMULTIPLYINSERT")]
  15.     public void LmxMultiplyInsert()
  16.     {
  17.       List<string> files = new List<string>()
  18.       {
  19.       "D:\\Test_1.dwg", "D:\\Test_2.dwg",
  20.       "D:\\Test_3.dwg", "D:\\Test_4.dwg",
  21.       "D:\\Test_5.dwg"
  22.       };
  23.       LmxInsertBlock(files, "A1", "00");
  24.     }
  25.  
  26.  
  27.     private void LmxInsertBlock(List<string> files, string lPosition, string lSlot)
  28.     {
  29.       Database db = Application.DocumentManager.MdiActiveDocument.Database;
  30.       Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  31.       ObjectId idBtr;
  32.       Point3d pInsert = new Point3d(0, 0, 0);
  33.       List<ObjectId> ids = new List<ObjectId>();
  34.       double lx = 0; // (-8 * 3) + 1.5; // <- не знаю к чему это
  35.       double ly = 0; // 16.615;
  36.  
  37.       int lxCountChar = lSlot.Length;
  38.  
  39.       foreach (string file in files)
  40.       {
  41.         pInsert = new Point3d(lx, ly, 0);
  42.         string blkName = SymbolUtilityServices.RepairSymbolName(
  43.           Path.GetFileNameWithoutExtension(file), false);
  44.         using (Transaction tr = db.TransactionManager.StartTransaction())
  45.         {
  46.           BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead, false) as BlockTable;
  47.           if (!bt.Has(blkName))
  48.           {
  49.             using (Database dbTmp = new Database(false, true))
  50.             {
  51.               dbTmp.ReadDwgFile(file, FileShare.Read, true, null);
  52.               idBtr = db.Insert(blkName, dbTmp, true);
  53.             }
  54.           }
  55.           else { idBtr = bt[blkName]; }
  56.  
  57.           tr.Commit();
  58.         }
  59.  
  60.         using (Transaction tr = db.TransactionManager.StartTransaction())
  61.         {
  62.           BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead, false) as BlockTable;
  63.           BlockTableRecord btr = bt[blkName].GetObject(OpenMode.ForRead) as BlockTableRecord;
  64.           BlockTableRecord btrMS = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  65.           BlockReference br = new BlockReference(pInsert, idBtr);
  66.           btrMS.AppendEntity(br);
  67.           tr.AddNewlyCreatedDBObject(br, true);
  68.           ids.Add(br.ObjectId);
  69.           foreach (ObjectId id in btr)
  70.           {
  71.             DBObject obj = tr.GetObject(id, OpenMode.ForRead);
  72.             AttributeDefinition attDef = obj as AttributeDefinition;
  73.             if ((attDef != null) && (!attDef.Constant))
  74.             {
  75.               AttributeReference attRef = new AttributeReference();
  76.               attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
  77.               br.AttributeCollection.AppendAttribute(attRef);
  78.               tr.AddNewlyCreatedDBObject(attRef, true);
  79.             }
  80.           }
  81.           //
  82.           // Тут полная ерунда - даже разбираться не стал.
  83.           // Просто убрал весь этот код
  84.           //
  85.           //AttributeCollection lxAttributeCollection = br.AttributeCollection;
  86.           //ObjectId lxAttrRef = lxAttributeCollection[0];
  87.           //AttributeReference lxAttr = lxAttrRef.GetObject(OpenMode.ForRead) as AttributeReference;
  88.           //string lxTextString = lxAttr.TextString;
  89.           //if (lxTextString.Contains("-"))
  90.           //{
  91.           //  lxAttr = lxAttrRef.GetObject(OpenMode.ForWrite) as AttributeReference;
  92.           //  lxAttr.TextString = $"{lPosition}-{lSlot}";
  93.           //  lSlot = (Convert.ToInt32(lSlot) + 1).ToString($"D{lxCountChar}");
  94.           //}
  95.           //else
  96.           //{
  97.           //  lxAttr = lxAttrRef.GetObject(OpenMode.ForWrite) as AttributeReference;
  98.           //  lxAttr.TextString = $"{lPosition}";
  99.           //}
  100.  
  101.           br.Visible = false;
  102.           tr.Commit();
  103.         }
  104.         lx = lx + 10; // Каждый блок смещен на 10 по X относительно предыдущего
  105.       }
  106.  
  107.       using (Transaction tr = db.TransactionManager.StartTransaction())
  108.       {
  109.         lmxDrawJig lxJig = new lmxDrawJig(Point3d.Origin);
  110.  
  111.         foreach (ObjectId id in ids)
  112.         {
  113.           BlockReference br =
  114.             tr.GetObject(id, OpenMode.ForWrite) as BlockReference;
  115.           BlockReference brClone = br.Clone() as BlockReference;
  116.           brClone.Visible = true;
  117.           lxJig.AddEntity(brClone);
  118.         }
  119.  
  120.         PromptResult prRes = Application.DocumentManager.MdiActiveDocument.Editor.Drag(lxJig);
  121.         if (prRes.Status == PromptStatus.OK)
  122.         {
  123.           foreach (ObjectId id in ids)
  124.           {
  125.             BlockReference lxBlockReference =
  126.               tr.GetObject(id, OpenMode.ForWrite) as BlockReference;
  127.             lxBlockReference.Erase();
  128.           }
  129.           lxJig.TransformEntities();
  130.           tr.Commit();
  131.         }
  132.         else
  133.         {
  134.           // Нужно освободить память клонов,
  135.           // если они не добавлены в базу
  136.           lxJig.DisposeEntities();
  137.           tr.Abort();
  138.         }
  139.       }
  140.     }
  141.  
  142.     class lmxDrawJig : DrawJig
  143.     {
  144.       private Point3d pOrig;
  145.       private Point3d pNewPt;
  146.       List<Entity> ents;
  147.  
  148.       public lmxDrawJig(Point3d basePt)
  149.       {
  150.         pOrig = basePt.TransformBy(UCS);
  151.         ents = new List<Entity>();
  152.       }
  153.  
  154.       public Point3d Base
  155.       {
  156.         get { return pNewPt; }
  157.         set { pNewPt = value; }
  158.       }
  159.  
  160.       public Point3d Location
  161.       {
  162.         get { return pNewPt; }
  163.         set { pNewPt = value; }
  164.       }
  165.  
  166.       public Matrix3d UCS
  167.       {
  168.         get
  169.         {
  170.           return Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem;
  171.         }
  172.       }
  173.  
  174.       public void AddEntity(Entity ent)
  175.       {
  176.         ents.Add(ent);
  177.       }
  178.  
  179.       public void TransformEntities()
  180.       {
  181.         Matrix3d mat = Matrix3d.Displacement(pOrig.GetVectorTo(pNewPt));
  182.         Database db = Application.DocumentManager.MdiActiveDocument.Database;
  183.  
  184.         using (Transaction tr = db.TransactionManager.StartTransaction())
  185.         {
  186.           BlockTable bt =
  187.               tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  188.           BlockTableRecord btrMS =
  189.               tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  190.           foreach (Entity ent in ents)
  191.           {
  192.             btrMS.AppendEntity(ent);
  193.             ent.TransformBy(mat);
  194.             tr.AddNewlyCreatedDBObject(ent, true);
  195.           }
  196.           tr.Commit();
  197.         }
  198.       }
  199.  
  200.       public void DisposeEntities()
  201.       {
  202.         foreach (Entity ent in ents)
  203.         {
  204.           ent.Dispose();
  205.         }
  206.       }
  207.  
  208.       protected override bool WorldDraw(WorldDraw wd)
  209.       {
  210.         Matrix3d mat = Matrix3d.Displacement(pOrig.GetVectorTo(pNewPt));
  211.  
  212.         WorldGeometry wg = wd.Geometry;
  213.         if (wg != null)
  214.         {
  215.           wg.PushModelTransform(mat);
  216.           foreach (Entity ent in ents)
  217.           {
  218.             ent.Visible = true;
  219.             wg.Draw(ent);
  220.           }
  221.           wg.PopModelTransform();
  222.         }
  223.         return true;
  224.       }
  225.  
  226.       protected override SamplerStatus Sampler(JigPrompts lxPrompts)
  227.       {
  228.         JigPromptPointOptions ppo =
  229.           new JigPromptPointOptions("\nNew location:");
  230.  
  231.         ppo.UseBasePoint = false;
  232.  
  233.         PromptPointResult ppr = lxPrompts.AcquirePoint(ppo);
  234.         if (ppr.Status == PromptStatus.Cancel || ppr.Status == PromptStatus.Error)
  235.           return SamplerStatus.Cancel;
  236.  
  237.         if (!pNewPt.IsEqualTo(ppr.Value, new Tolerance(1e-9, 1e-9)))
  238.         {
  239.           pNewPt = ppr.Value;
  240.           return SamplerStatus.OK;
  241.         }
  242.         else return SamplerStatus.NoChange;
  243.       }
  244.     }
  245.   }
  246. }

По хорошему нужно было весь код выкинуть и написать с чистого листа, но на это у меня уже нет ни сил, ни времени. Вот результат работы команды:

Название: Re: Мульти вставка блоков
Отправлено: Lemieux от 12-02-2020, 15:32:47
Александр, спасибо! А где Вы используете метод Close()? Вы написали про полную ерунду, а как правильно получать доступ к атрибутам блока и менять их значения? И почему Вы делаете клон 2 раза видимым (строки 116, 218)?
Название: Re: Мульти вставка блоков
Отправлено: Александр Ривилис от 12-02-2020, 15:39:32
А где Вы используете метод Close()?
Нигде. Я переписал алгоритм с транзакцией вместо Open/Close, чтобы меньше править твой код.
Вы написали про полную ерунду, а как правильно получать доступ к атрибутам блока и менять их значения?
Чтобы понять как работает твой код мне нужно было иметь твои тестовые файлы. Попробуй раскомментировать этот код - если будет работать, то и слава Богу!
И почему Вы делаете клон 2 раза видимым (строки 116, 218)?
Второй раз лишний, но это не принципиально.