判断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,那么就说明我在多段线内。

浙公网安备 33010602011771号