07/09/2016
Получение точек пересечения кривой и плоскости
Для получения пересечения кривой и плоскости можно пользоваться различными методами. Один из методов, который предложен в этой статье, это аппроксимация кривой с получением точек аппроксимации, а затем получение пересечения отрезков, образованных этими точками и плоскостью. Ниже пример кода, который реализует этот алгоритм:
Код - C#: [Выделить]
- using System;
- using Autodesk.AutoCAD.Runtime;
- using Autodesk.AutoCAD.ApplicationServices;
- using Autodesk.AutoCAD.DatabaseServices;
- using Autodesk.AutoCAD.Geometry;
- using Autodesk.AutoCAD.EditorInput;
- [assembly: CommandClass(typeof(Rivilis.CurvePlaneIntersection))]
- namespace Rivilis
- {
- public class CurvePlaneIntersection
- {
- /// <summary>
- /// Функция находит все точки пересечения кривой и плоскости.
- /// </summary>
- /// <param name="curve">кривая</param>
- /// <param name="plane">плоскость</param>
- /// <returns></returns>
- static public Point3dCollection GetIntersectCurvePlane(Curve curve, Plane plane)
- {
- Point3dCollection pts = new Point3dCollection();
- using (Curve3d curve3d = curve.GetGeCurve())
- {
- Interval intr = curve3d.GetInterval();
- BoundBlock3d blk = curve3d.BoundBlock;
- // Максимальная величина хорды для аппроксимации кривой
- // С этим значением можно играться
- double fuzz = blk.GetMinimumPoint().DistanceTo(blk.GetMaximumPoint()) * 1e-6;
- PointOnCurve3d[] ptsApprox =
- curve3d.GetSamplePoints(intr.LowerBound, intr.UpperBound, fuzz);
- for (int i = 0; i < ptsApprox.Length-1; i++)
- {
- using (LineSegment3d l3d =
- new LineSegment3d(ptsApprox[i].Point, ptsApprox[i+1].Point))
- {
- Point3d[] pts_int = l3d.IntersectWith(plane);
- if (pts_int != null && pts_int.Length > 0)
- foreach (Point3d p in pts_int) pts.Add(p);
- }
- // Отдельно обработаем замкнутую кривую.
- if (curve3d.IsClosed() && (ptsApprox[0] != ptsApprox[ptsApprox.Length-1]))
- {
- using (LineSegment3d l3d =
- new LineSegment3d(ptsApprox[0].Point, ptsApprox[ptsApprox.Length-1].Point))
- {
- Point3d[] pts_int = l3d.IntersectWith(plane);
- if (pts_int != null && pts_int.Length > 0)
- foreach (Point3d p in pts_int) pts.Add(p);
- }
- }
- }
- }
- return pts;
- }
- #pragma warning disable 0618
- /// <summary>
- /// Команда для проверки работоспособности функции GetIntersectCurvePlane
- /// </summary>
- [CommandMethod("IntC3Plane")]
- public void IntC3Plane()
- {
- Document doc = Application.DocumentManager.MdiActiveDocument;
- if (doc == null) return;
- Editor ed = doc.Editor;
- //////////////////////////////////////////////////////////////////////////
- // Запрашиваем плоскость. Пусть она определяется 3DГРАНЬ'ю (Face)
- //////////////////////////////////////////////////////////////////////////
- PromptEntityOptions prOpt = new PromptEntityOptions("");
- prOpt.Message = "\nВыберите 3DГРАНЬ (3DFACE): ";
- prOpt.SetRejectMessage("Это не 3DГРАНЬ (3DFACE)!");
- prOpt.AddAllowedClass(typeof(Face), true);
- PromptEntityResult res1 = ed.GetEntity(prOpt);
- if (res1.Status != PromptStatus.OK) return;
- //////////////////////////////////////////////////////////////////////////
- // Запрашиваем кривую. Это любой примитив, унаследованный от Curve
- //////////////////////////////////////////////////////////////////////////
- prOpt.Message = "\nВыберите кривую: ";
- prOpt.SetRejectMessage("Это не кривая!");
- prOpt.RemoveAllowedClass(typeof(Face));
- prOpt.AddAllowedClass(typeof(Curve), false);
- PromptEntityResult res2 = ed.GetEntity(prOpt);
- if (res2.Status != PromptStatus.OK) return;
- using (Face face = res1.ObjectId.Open(OpenMode.ForRead) as Face)
- {
- using (Plane plane = new Plane(face.GetVertexAt(0), face.GetVertexAt(1), face.GetVertexAt(2)))
- {
- using (Curve curve = res2.ObjectId.Open(OpenMode.ForRead) as Curve)
- {
- Point3dCollection pts = GetIntersectCurvePlane(curve, plane);
- using (BlockTableRecord btr = doc.Database.CurrentSpaceId.Open(OpenMode.ForWrite) as BlockTableRecord)
- {
- for (int i = 0; i < pts.Count; i++)
- {
- ed.WriteMessage("\nТочка {0} = {1}", i, pts[i]);
- using (DBPoint dbpoint = new DBPoint(pts[i]))
- {
- btr.AppendEntity(dbpoint);
- }
- }
- }
- }
- }
- }
- }
- }
- }
Автор: Александр Ривилис
Обсуждение: http://adn-cis.org/forum/index.php?topic=7320
Опубликовано 07.09.2016