qq1254582201 发表于 2021-10-22 14:33:00

判断点是否在封闭多段线内【转载+优化】

一、使用多重多边形。使用函数AppendLoopFromBoundary(pline, true, tolerance)传入多段线范围线和容差创建多重多边形,然后根据函数IsPointInsideMPolygon((point, tolerance). Count返回值是否为1来判断是否在多段线内部。
二、使用Region和Brep,几乎所有的实体都适用于Region,通过Region.CreateFromCurves(curves)来创建Region,然后传入到Brep中,利用GetPointContainment(point, out result)返回的BrepEntity来判断是否是
Autodesk..BoundaryRepresentation.Face,如果是,则最终为多段线内。
当然这里的解释表现得抽象了些,大家可以通过阅读代码来了解细节方面流程。值得注意的是在使用上面的函数时,必须导入acdbmgdbrep、AcMPolygonMGD两个dll动态链接库。可以说MPolygon具有一定的拓扑运算能力,可以弥补AutoCAD在几何拓扑运算方面的小小缺陷。当然了更多MPolygon有待进一步研究。
————————————————
版权声明:本文为CSDN博主「yGIS」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.BoundaryRepresentation;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IsInPolyline
{
    public class Class1
    {
      
      
      public static void test()
      {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptEntityOptions peo = new PromptEntityOptions("\n选择一条多段线: ");
            peo.SetRejectMessage("Only a polyline !");
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return;
            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                PromptPointOptions ppo = new PromptPointOptions("\n拾取一个点 : ");
                ppo.AllowNone = true;
                while (true)
                {
                  PromptPointResult ppr = ed.GetPoint(ppo);
                  if (ppr.Status != PromptStatus.OK)
                        break;
                  Application.ShowAlertDialog(
                        pline.IsPointInside(ppr.Value) ? "Inside" : "Outside");
                }
               
            }
      }
      
      public void test2() {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptEntityOptions peo = new PromptEntityOptions("\n选择一条多段线: ");
            peo.SetRejectMessage("Only a polyline !");
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return;
            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            {
               Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);
               if (!pline.Closed)
               {
                     ed.WriteMessage("\n多段线必须为闭合");
                     return;
               }
               DBObjectCollection curves = new DBObjectCollection();
               curves.Add(pline);
               try
               {
                     using (DBObjectCollection regions = Region.CreateFromCurves(curves))
                     using (Region region = (Region)regions)
                     {
                        PromptPointOptions ppo = new PromptPointOptions("\nPick a point : ");
                        ppo.AllowNone = true;
                        while (true)
                        {
                              PromptPointResult ppr = ed.GetPoint(ppo);
                              if (ppr.Status != PromptStatus.OK)
                                  break;
                              Application.ShowAlertDialog(
                                                GetPointContainment(region, ppr.Value).ToString());
                        }
                     }
               }
               catch (System.Exception exn)
               {
                     ed.WriteMessage("\nError: " + exn.Message);
               }
            }
      }
      private PointContainment GetPointContainment(Region region, Point3d point)
      {
            PointContainment result = PointContainment.Outside;
            using (Brep brep = new Brep(region))
            {
                if (brep != null)
                {
                  using (BrepEntity ent = brep.GetPointContainment(point, out result))
                  {
                        if (ent is Autodesk.AutoCAD.BoundaryRepresentation.Face)
                        {
                            result = PointContainment.Inside;
                        }
                  }
                }
            }
            return result;
      }
    }
}以上是原作者的代码。但是方法一缺少了重要的pline.IsPointInside(pt),以下为自己东拼西凑的:IsPointInside(this Polyline pline, Point3d pt)

public static bool IsPointInside(this Polyline pline, Point3d pt)
      {
            bool str = true;
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                var mPolygon = new MPolygon();
                btr.AppendEntity(mPolygon);
                tr.AddNewlyCreatedDBObject(mPolygon, true);
                mPolygon.UpgradeOpen();
                if (pline is Polyline)
                  mPolygon.AppendLoopFromBoundary((Polyline)pline, true, 1E-12);
                mPolygon.ColorIndex = 1;
                mPolygon.DowngradeOpen();
                var jj = mPolygon.IsPointInsideMPolygon(pt, 1E-12).Count;
                if (jj != 1)
                {
                  str = false;
                }
                //tr.Commit();
            }
            return str;
      }

**** Hidden Message *****
页: [1]
查看完整版本: 判断点是否在封闭多段线内【转载+优化】