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

20/03/2018

Как получить пересечение прямой и твердого тела в NET?

По аналогии с тем, как это делается в ObjectARX, это можно сделать при помощи B-Rep API и в AutoCAD .NET API. Следующий код иллюстрирует как получить пересечение линейного примитива (ОТРЕЗОК, ЛУЧ, ПРЯМАЯ) с примитивом, который представляется в виде ACIS (т.е. твердое тело - SOLID, область - REGION, или тело BODY).

Код - C#: [Выделить]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7. using Autodesk.AutoCAD.BoundaryRepresentation;
  8.  
  9. using AcRx = Autodesk.AutoCAD.Runtime;
  10. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  11. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  12. using AcGe = Autodesk.AutoCAD.Geometry;
  13. using AcEd = Autodesk.AutoCAD.EditorInput;
  14. using AcBr = Autodesk.AutoCAD.BoundaryRepresentation;
  15.  
  16.  
  17. // This line is not mandatory, but improves loading performances
  18. [assembly: CommandClass(typeof(IntSolidNet.MyCommands))]
  19.  
  20. namespace IntSolidNet
  21. {
  22.   public class MyCommands
  23.   {
  24.     [CommandMethod("IntSolid", CommandFlags.Modal)]
  25.     public void MyCommand()
  26.     {
  27.       Document doc = Application.DocumentManager.MdiActiveDocument;
  28.       if (doc == null) return;
  29.       Editor ed = doc.Editor;
  30.       // Запрашиваем линию
  31.       PromptEntityOptions prLine = new PromptEntityOptions("\nВыберите линию: ");
  32.       prLine.SetRejectMessage("Это не линия - допустимы Отрезок, Луч, Прямая");
  33.       prLine.AddAllowedClass(typeof(Line), false);
  34.       prLine.AddAllowedClass(typeof(Ray), false);
  35.       prLine.AddAllowedClass(typeof(Xline), false);
  36.       PromptEntityResult rsLine = ed.GetEntity(prLine);
  37.       if (rsLine.Status != PromptStatus.OK) return;
  38.       // Запрашиваем 3DSolid
  39.       PromptEntityOptions prSolid = new PromptEntityOptions("\nВыберите твердое тело: ");
  40.       prSolid.SetRejectMessage("Это не твердое тело");
  41.       prSolid.AddAllowedClass(typeof(Solid3d), false);
  42.       prSolid.AddAllowedClass(typeof(Region), false);
  43.       prSolid.AddAllowedClass(typeof(Body), false);
  44.       PromptEntityResult rsSolid = ed.GetEntity(prSolid);
  45.       if (rsSolid.Status != PromptStatus.OK) return;
  46.       // Запрашиваем количество пересечений
  47.       PromptIntegerOptions prNumInt =
  48.         new PromptIntegerOptions("\nКоличество пересечений (0 - все): ");
  49.       prNumInt.AllowNegative = false;
  50.       prNumInt.AllowZero = true;
  51.       prNumInt.AllowNone = false;
  52.       PromptIntegerResult rsNumInt = ed.GetInteger(prNumInt);
  53.       if (rsNumInt.Status != PromptStatus.OK) return;
  54.       Point3dCollection hitPoints = new Point3dCollection();
  55. #pragma warning disable 0618
  56.       using (Entity line = rsLine.ObjectId.Open(OpenMode.ForRead) as Entity)
  57.       using (Entity solid = rsSolid.ObjectId.Open(OpenMode.ForRead) as Entity)
  58. #pragma warning restore 0618
  59.       {
  60.         if (getHits(line, solid, rsNumInt.Value, hitPoints) == AcRx.ErrorStatus.InvalidInput)
  61.         {
  62.           ed.WriteMessage("\nЧто-то пошло не так!");
  63.         }
  64.         else
  65.         {
  66.           if (hitPoints.Count == 0)
  67.           {
  68.             ed.WriteMessage("\nПересечения не найдены!");
  69.           }
  70.           else
  71.           {
  72.             ed.WriteMessage("\nНайдено {0} пересечений", hitPoints.Count);
  73.             for (int i = 0; i < hitPoints.Count; i++)
  74.             {
  75.               ed.WriteMessage("\nПересечение {0}: {1}", i + 1, hitPoints[i]);
  76.             }
  77.           }
  78.         }
  79.       }
  80.  
  81.     }
  82.     /// <summary>
  83.     /// Функция для получения точек пересечения твердого тела и прямой
  84.     /// </summary>
  85.     static AcRx.ErrorStatus getHits(Entity line, Entity solid, int nHitsWanted, Point3dCollection hitPoints)
  86.     {
  87.       Document doc = Application.DocumentManager.MdiActiveDocument;
  88.       Editor ed = doc.Editor;
  89.  
  90.       // Проверяем, что примитив правильного типа
  91.       if (!(solid is Solid3d || solid is Region || solid is Body))
  92.       {
  93.         ed.WriteMessage("\nВторой аргумент должен быть твердым телом, а не %0",
  94.           solid.GetRXClass().Name);
  95.         return AcRx.ErrorStatus.InvalidInput;
  96.       }
  97.       LinearEntity3d pGeLine = null;
  98.       if (line is Line)
  99.       {
  100.         Line ln = line as Line;
  101.         pGeLine = new LineSegment3d(ln.StartPoint, ln.EndPoint);
  102.       }
  103.       else if (line is Ray)
  104.       {
  105.         Ray ln = line as Ray;
  106.         pGeLine = new Ray3d(ln.BasePoint, ln.UnitDir);
  107.       }
  108.       else if (line is Xline)
  109.       {
  110.         Xline ln = line as Xline;
  111.         pGeLine = new Line3d(ln.BasePoint, ln.UnitDir);
  112.       }
  113.       else
  114.       {
  115.         ed.WriteMessage("\nПервый аргумент должен быть линией, а не %0",
  116.           line.GetRXClass().Name);
  117.         return AcRx.ErrorStatus.InvalidInput;
  118.       }
  119.  
  120.       // Находим количество пересечений при помощи B-Rep API
  121.       ObjectId solidId = solid.ObjectId;
  122.       FullSubentityPath subs = new FullSubentityPath(new ObjectId[] { solidId }, new SubentityId());
  123.       Brep pBrep = new Brep(subs);
  124.  
  125.       Hit[] pHits = pBrep.GetLineContainment(pGeLine, nHitsWanted);
  126.       if (pHits != null)
  127.       {
  128.         int nHitsFound = pHits.Length;
  129.         for (int i = 0; i < nHitsFound; i++)
  130.         {
  131.           BrepEntity pHitEntity = pHits[i].EntityHit as BrepEntity;
  132.  
  133.           if (pHitEntity == null)
  134.             continue;
  135.           if (pHitEntity is Brep)
  136.             continue;
  137.           Point3d hitPt = pHits[i].Point;
  138.           hitPoints.Add(hitPt);
  139.         }
  140.  
  141.         // Конвертируем точки из МСК в ПСК
  142.  
  143.         int nPts = hitPoints.Count;
  144.         Matrix3d mat = ed.CurrentUserCoordinateSystem.Inverse();
  145.         for (int i = 0; i < nPts; i++)
  146.         {
  147.           hitPoints[i] = hitPoints[i].TransformBy(mat);
  148.         }
  149.       }
  150.       return AcRx.ErrorStatus.OK;
  151.     }
  152.   }
  153. }

 

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

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

Опубликовано 20.03.2018