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

07/09/2016

Получение точек пересечения кривой и плоскости

Для получения пересечения кривой и плоскости можно пользоваться различными методами. Один из методов, который предложен в этой статье, это аппроксимация кривой с получением точек аппроксимации, а затем получение пересечения отрезков, образованных этими точками и плоскостью. Ниже пример кода, который реализует этот алгоритм:

Код - 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.  
  8. [assembly: CommandClass(typeof(Rivilis.CurvePlaneIntersection))]
  9.  
  10. namespace Rivilis
  11. {
  12.   public class CurvePlaneIntersection
  13.   {
  14.     /// <summary>
  15.     /// Функция находит все точки пересечения кривой и плоскости.
  16.     /// </summary>
  17.     /// <param name="curve">кривая</param>
  18.     /// <param name="plane">плоскость</param>
  19.     /// <returns></returns>
  20.     static public Point3dCollection GetIntersectCurvePlane(Curve curve, Plane plane)
  21.     {
  22.       Point3dCollection pts = new Point3dCollection();
  23.       using (Curve3d curve3d = curve.GetGeCurve())
  24.       {
  25.         Interval intr = curve3d.GetInterval();
  26.         BoundBlock3d blk = curve3d.BoundBlock;
  27.         // Максимальная величина хорды для аппроксимации кривой
  28.         // С этим значением можно играться
  29.         double fuzz = blk.GetMinimumPoint().DistanceTo(blk.GetMaximumPoint()) * 1e-6;
  30.         PointOnCurve3d[] ptsApprox =
  31.           curve3d.GetSamplePoints(intr.LowerBound, intr.UpperBound, fuzz);
  32.  
  33.         for (int i = 0; i < ptsApprox.Length-1; i++)
  34.         {
  35.           using (LineSegment3d l3d =
  36.             new LineSegment3d(ptsApprox[i].Point, ptsApprox[i+1].Point))
  37.           {
  38.             Point3d[] pts_int = l3d.IntersectWith(plane);
  39.             if (pts_int != null && pts_int.Length > 0)
  40.               foreach (Point3d p in pts_int) pts.Add(p);
  41.           }
  42.           // Отдельно обработаем замкнутую кривую.
  43.           if (curve3d.IsClosed() && (ptsApprox[0] != ptsApprox[ptsApprox.Length-1]))
  44.           {
  45.             using (LineSegment3d l3d =
  46.               new LineSegment3d(ptsApprox[0].Point, ptsApprox[ptsApprox.Length-1].Point))
  47.             {
  48.               Point3d[] pts_int = l3d.IntersectWith(plane);
  49.               if (pts_int != null && pts_int.Length > 0)
  50.                 foreach (Point3d p in pts_int) pts.Add(p);
  51.             }
  52.           }
  53.         }
  54.       }
  55.       return pts;
  56.     }
  57.  
  58. #pragma warning disable 0618
  59.  
  60.     /// <summary>
  61.     /// Команда для проверки работоспособности функции GetIntersectCurvePlane
  62.     /// </summary>
  63.     [CommandMethod("IntC3Plane")]
  64.     public void IntC3Plane()
  65.     {
  66.       Document doc = Application.DocumentManager.MdiActiveDocument;
  67.       if (doc == null) return;
  68.       Editor ed = doc.Editor;
  69.       //////////////////////////////////////////////////////////////////////////
  70.       // Запрашиваем плоскость. Пусть она определяется 3DГРАНЬ'ю (Face)
  71.       //////////////////////////////////////////////////////////////////////////
  72.       PromptEntityOptions prOpt = new PromptEntityOptions("");
  73.       prOpt.Message = "\nВыберите 3DГРАНЬ (3DFACE): ";
  74.       prOpt.SetRejectMessage("Это не 3DГРАНЬ (3DFACE)!");
  75.       prOpt.AddAllowedClass(typeof(Face), true);
  76.       PromptEntityResult res1 = ed.GetEntity(prOpt);
  77.       if (res1.Status != PromptStatus.OK) return;
  78.       //////////////////////////////////////////////////////////////////////////
  79.       // Запрашиваем кривую. Это любой примитив, унаследованный от Curve
  80.       //////////////////////////////////////////////////////////////////////////
  81.       prOpt.Message = "\nВыберите кривую: ";
  82.       prOpt.SetRejectMessage("Это не кривая!");
  83.       prOpt.RemoveAllowedClass(typeof(Face));
  84.       prOpt.AddAllowedClass(typeof(Curve), false);
  85.       PromptEntityResult res2 = ed.GetEntity(prOpt);
  86.       if (res2.Status != PromptStatus.OK) return;
  87.       using (Face face = res1.ObjectId.Open(OpenMode.ForRead) as Face)
  88.       {
  89.         using (Plane plane = new Plane(face.GetVertexAt(0), face.GetVertexAt(1), face.GetVertexAt(2)))
  90.         {
  91.           using (Curve curve = res2.ObjectId.Open(OpenMode.ForRead) as Curve)
  92.           {
  93.             Point3dCollection pts = GetIntersectCurvePlane(curve, plane);
  94.             using (BlockTableRecord btr = doc.Database.CurrentSpaceId.Open(OpenMode.ForWrite) as BlockTableRecord)
  95.             {
  96.               for (int i = 0; i < pts.Count; i++)
  97.               {
  98.                 ed.WriteMessage("\nТочка {0} = {1}", i, pts[i]);
  99.                 using (DBPoint dbpoint = new DBPoint(pts[i]))
  100.                 {
  101.                   btr.AppendEntity(dbpoint);
  102.                 }
  103.               }
  104.             }
  105.           }
  106.         }
  107.       }
  108.     }
  109.   }
  110. }
  111.  

 

 

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

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

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