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

28/06/2016

Выполнение подрезки блока или внешней ссылки при помощи .NET

Вопрос: Как средствами AutoCAD .NET API можно выполнить подрезку блока или внешней ссылки (по аналогии с командой _XCLIP)

Ответ: Для этой цели используется пространственный фильтр (SpatialFilter). Следующий код показывает как выполнить подрезку блока/внешней ссылки при помощи произвольного замкнутого многоугольника:

Код - C#: [Выделить]
  1. using Autodesk.AutoCAD.DatabaseServices;
  2. using Autodesk.AutoCAD.EditorInput;
  3. using Autodesk.AutoCAD.Geometry;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices.Filters;
  6. using Autodesk.AutoCAD.Runtime;
  7. using System;
  8.  
  9.  
  10. namespace SpatialFiltering
  11. {
  12.   public class ClipBlock
  13.   {
  14.     const string filterDictName = "ACAD_FILTER";
  15.     const string spatialName = "SPATIAL";
  16.  
  17.     [CommandMethod("XCLIPBREF")]
  18.     public static void clipBlockTest()
  19.     {
  20.       Document doc = Application.DocumentManager.MdiActiveDocument;
  21.       Database db = doc.Database;
  22.       Editor ed = doc.Editor;
  23.  
  24.       // Выбираем блок для подрезки
  25.  
  26.       PromptEntityOptions peo =  
  27.         new PromptEntityOptions("\nВыберите вставку блока или внешнюю ссылку:");
  28.       peo.AllowNone = false;
  29.       peo.SetRejectMessage("\nЭто не вставка блока и не внешняя ссылка.");
  30.       peo.AddAllowedClass(typeof(BlockReference), false);
  31.  
  32.       PromptEntityResult per = ed.GetEntity(peo);
  33.  
  34.       if (per.Status != PromptStatus.OK)
  35.         return;
  36.       Point3dCollection pts3d = new Point3dCollection();
  37.  
  38.       // Выбираем точки для подрезки
  39.       while (true)
  40.       {
  41.         PromptPointOptions ppo;
  42.         if (pts3d.Count < 3) {
  43.           ppo = new PromptPointOptions("\nУкажите " + (pts3d.Count + 1).ToString() + "-ую точку контура");
  44.           ppo.AllowNone = false;
  45.         }  else  {
  46.           ppo = new PromptPointOptions("\nУкажите " + (pts3d.Count + 1).ToString() + "-ую точку контура (ENTER - завершение)");
  47.           ppo.AllowNone = true;
  48.         }
  49.  
  50.         if (pts3d.Count > 0)
  51.         {
  52.           ppo.BasePoint = pts3d[pts3d.Count-1];
  53.           ppo.UseBasePoint = true;
  54.         }
  55.  
  56.         PromptPointResult ppr = ed.GetPoint(ppo);
  57.  
  58.         if (ppr.Status != PromptStatus.OK)
  59.           break;
  60.  
  61.         if (pts3d.Count > 0)
  62.           ed.DrawVector(pts3d[pts3d.Count - 1], ppr.Value, 1, true);
  63.  
  64.         pts3d.Add(ppr.Value);
  65.       }
  66.  
  67.       Transaction tr = db.TransactionManager.StartTransaction();
  68.  
  69.       using (tr)
  70.       {
  71.         // Преобразуем точки в систему координат блока!!!
  72.         BlockReference br =  (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead);
  73.         Point2dCollection pts = new Point2dCollection(pts3d.Count);
  74.         Matrix3d mat = br.BlockTransform.Inverse();
  75.         foreach (Point3d p in pts3d)
  76.         {
  77.           Point3d pBlk  = p.TransformBy(mat);
  78.           pts.Add(new Point2d(pBlk.X, pBlk.Y));
  79.         }
  80.  
  81.  
  82.         // Создаем фильтр
  83.  
  84.         SpatialFilterDefinition sfd =
  85.           new SpatialFilterDefinition(
  86.             pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true
  87.           );
  88.  
  89.         SpatialFilter sf = new SpatialFilter();
  90.  
  91.         sf.Definition = sfd;
  92.  
  93.         // Создаем ExtDict если его еще не было
  94.  
  95.         if (br.ExtensionDictionary == ObjectId.Null)
  96.         {
  97.           br.UpgradeOpen();
  98.           br.CreateExtensionDictionary();
  99.           br.DowngradeOpen();
  100.         }
  101.  
  102.         // Добавляем фильтр
  103.  
  104.         DBDictionary xDict = (DBDictionary)tr.GetObject(br.ExtensionDictionary, OpenMode.ForWrite);
  105.  
  106.         if (xDict.Contains(filterDictName))
  107.         {
  108.           DBDictionary fDict =
  109.             (DBDictionary)tr.GetObject(
  110.               xDict.GetAt(filterDictName), OpenMode.ForWrite
  111.             );
  112.           if (fDict.Contains(spatialName))
  113.             fDict.Remove(spatialName);
  114.           fDict.SetAt(spatialName, sf);
  115.         }
  116.         else
  117.         {
  118.           DBDictionary fDict = new DBDictionary();
  119.           xDict.SetAt(filterDictName, fDict);
  120.           tr.AddNewlyCreatedDBObject(fDict, true);
  121.           fDict.SetAt(spatialName, sf);
  122.         }
  123.  
  124.         tr.AddNewlyCreatedDBObject(sf, true);
  125.         tr.Commit();
  126.       }
  127.       ed.Regen();
  128.     }
  129.   }
  130. }

Видео:

Автор: Александр Ривилис

Обсуждение: http://adn-cis.org/forum/index.php?topic=7181

Опубликовано 28.06.2016
Отредактировано 28.06.2016 в 17:06:47