判断CAD中点是否在封闭的多段线内

目前判断的多段线是全部由直线构成的,且是封闭的。

 1 public class IsInPolyline
 2     {
 3         [CommandMethod("IsInPolylineTest")]
 4         public void Test()
 5         {
 6             Document doc = Application.DocumentManager.MdiActiveDocument;
 7             Database db = doc.Database;
 8             Editor ed = doc.Editor;
 9 
10             PromptEntityOptions peo = new PromptEntityOptions("\n选择一条多段线: ");
11             peo.SetRejectMessage("Only a polyline !");
12             peo.AddAllowedClass(typeof(Polyline), true);
13             PromptEntityResult per = ed.GetEntity(peo);
14             if (per.Status != PromptStatus.OK)
15                 return;
16 
17             using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
18             {
19                 Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);
20                 PromptPointOptions ppo = new PromptPointOptions("\n拾取一个点 <quit>: ");
21                 ppo.AllowNone = true;
22                 while (true)
23                 {
24                     PromptPointResult ppr = ed.GetPoint(ppo);
25                     if (ppr.Status != PromptStatus.OK)
26                         break;
27                     if (pline != null)
28                     {
29                         List<Point3d> ptList = new List<Point3d>();
30                         for (int i = 0; i < pline.NumberOfVertices; i++)
31                         {
32                             ptList.Add(pline.GetPoint3dAt(i));
33                         }
34                         Application.ShowAlertDialog(IsPointInsidePolygon(ptList, ppr.Value) ? "" : "不在");
35                     }
36                 }
37 
38             }
39         }
40 
41 
42         // 判断点是否在线段上(二维)
43         public static bool IsPointOnSegment(Point3d p, Point3d q, Point3d r)
44         {
45             if (q.X <= Math.Max(p.X, r.X) && q.X >= Math.Min(p.X, r.X) &&
46                 q.Y <= Math.Max(p.Y, r.Y) && q.Y >= Math.Min(p.Y, r.Y))
47             {
48                 return true;
49             }
50             return false;
51         }
52 
53         // 判断点是否在多边形内部(使用射线法,仅考虑二维)
54         public static bool IsPointInsidePolygon(List<Point3d> polygonPoints, Point3d testPoint)
55         {
56             int intersections = 0;
57             int j = polygonPoints.Count - 1;
58 
59             // 遍历多边形的每条边
60             for (int i = 0; i < polygonPoints.Count; i++)
61             {
62                 Point3d pi = polygonPoints[i];
63                 Point3d pj = polygonPoints[j];
64 
65                 // 忽略测试点恰好在多边形边上的情况
66                 if (!IsPointOnSegment(pi, pj, testPoint))
67                 {
68                     // 使用向量的叉积来判断交点
69                     // 这里我们简化计算,只考虑二维平面的叉积(即方向)
70                     if ((pi.Y > testPoint.Y) != (pj.Y > testPoint.Y) &&
71                         (testPoint.X < (pj.X - pi.X) * (testPoint.Y - pi.Y) / (pj.Y - pi.Y) + pi.X))
72                     {
73                         intersections++;
74                     }
75                 }
76 
77                 j = i; // 更新上一个点的索引
78             }
79 
80             // 奇数个交点表示点在多边形内部
81             return intersections % 2 != 0;
82         }
83     }

 在部分情况下 这个射线法会失效,例如以下情况:

 因为当前默认是朝向右侧做的射线,会出现两个交点,交点的数量为偶数,所以这里判断的结果是不在CAD内,实际是错的。对于这种情况目前没有很好的解决办法,

所以我向上再做一次射线,只要两者任意的结果为true,那么就说明我在多段线内。

posted @ 2024-07-11 11:57  奋斗星  阅读(102)  评论(0)    收藏  举报