;;说明:判断点在多段线构成的多边形内侧还是外侧;;参数:pt:点;;参数:var:多段线构成的多边形图元名或者多边型点表;;参数:flag:如果为T,则点在多边形上时,则判断为多边形内侧,否则则判断为外侧;;返回:内侧为:T,外侧为:nil;;(PtIsInPoly (getpoint) (car (entsel)) t);;(PtIsInPoly (getpoint) (list (getpoint) (getpoint)) t)(defun PtIsInPoly(pt var flag / getptlst judgestart vlist)(defun getptlst(e) (mapcar 'cdr (vl-remove-if-not (function (lambda(x) (= 10 (car x)))) (entget e))))(defun judgestart(vlist / cnt diff idx len numints online p1 p1code p1x p1y p2 p2code p2x p2y vlist x xdiff xx y ydiff)(if (not (equal (car vlist) (last vlist)))(setq vlist (append vlist (list (car vlist)))))(setq X (car pt)Y (cadr pt)len (length vlist)cnt 0Idx 0NumInts 0OnLine nil)(while (and (not OnLine) (< cnt len))(setqp2 (nth cnt vlist)p2x (car p2)p2y (cadr p2)p2code (if (>= p2y y) 2 0)p2code (if (>= p2x x) (1+ p2code) p2code))(if p1(setq diff (boole 6 p1code p2code)ydiff (boole 1 diff 2)xdiff (boole 1 diff 1)p1x (car p1)p1y (cadr p1)))(if (= ydiff 2)(progn(setq xx (+ p1x (* (/ (- p2x p1x) 1. (- p2y p1y)) (- y p1y))))(cond((equal xx x 0.0001) (setq online T))((> xx x) (setq NumInts (1+ NumInts))))))(if (and (= xdiff 1) (= y p1y p2y)) (setq OnLine T))(setq p1code p2code p1 p2 cnt (1+ cnt)))(if Online flag (= (boole 1 NumInts 1) 0001)))(if (equal (type var) 'ENAME)(judgestart (getptlst var))(if (and var (listp var) (> (length var) 1)) (judgestart var) (progn (princ "\n点表输入有误!") (prin1)))))
=======================================================================================
以下原文链接
矩形只是多段线的一种解,但是矩形可以利用叉乘做到快速求解,这方面可以自行去搞搞.
这里提供一个最通用的.
测试命令:
public class JJ_test_ckk{[CommandMethod("JJ_test_ckk")]public void TT(){Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;Database db = Acap.DocumentManager.MdiActiveDocument.Database;ed.WriteMessage(Environment.NewLine + "惊惊net测试区:");var ppo = new PromptPointOptions(Environment.NewLine + "测试点:"){AllowArbitraryInput = true,//任意输入AllowNone = true//允许回车};var ppr = ed.GetPoint(ppo);//用户点选if (ppr.Status != PromptStatus.OK){return;}var peo = new PromptEntityOptions(Environment.NewLine + "点选多段线"){AllowObjectOnLockedLayer = false,AllowNone = false};var res = ed.GetEntity(peo);if(res.Status != PromptStatus.OK) return;db.Action(tr=>{var ent2 =res.ObjectId.ToEntity(tr);if (ent is Polyline pl && MathTool.IsPointInPL(ppr.Value, pl.GetPoint3ds())){ed.WriteMessage(Environment.NewLine + "内内内内内内内内");}else{ed.WriteMessage(Environment.NewLine + "外外外外外外外外外外外");}});}}
id.isok
/// <summary>/// id有效,未被删除/// </summary>/// <param name="id"></param>/// <returns></returns>public static bool IsOk(this ObjectId id){return !id.IsNull && id.IsValid && !id.IsErased && !id.IsEffectivelyErased && id.IsResident;}
射线法:
/// <summary>/// 判断点在闭合多段线内(线上也是内)射线法/// </summary>/// <param name="p">判断的点</param>/// <param name="pts">边界点集</param>/// <returns></returns>public static bool IsPointInPL(Point3d p, IEnumerable<Point3d> pts){var px = p.X;var py = p.Y;var flag = false;var poly = pts.ToArray();int l = poly.Length;int j = l - 1;for (var i = 0; i < l; i++){var pt1x = poly[i].X;//头var pt1y = poly[i].Y;var pt2x = poly[j].X;//尾var pt2y = poly[j].Y;// 点与多边形顶点重合if ((pt1x.Eq(px) && pt1y.Eq(py)) || (pt2x.Eq(px) && pt2y.Eq(py))){return true;}// 判断线段两端点是否在射线两侧if ((pt1y < py && pt2y >= py) || (pt1y >= py && pt2y < py)){// 线段上与射线 Y 坐标相同的点的 X 坐标var x = pt1x + (py - pt1y) * (pt2x - pt1x) / (pt2y - pt1y);// 点在多边形的边上if (x.Eq(px)){return true;}// 射线穿过多边形的边界if (x > px){flag = !flag;}}j = i;}// 射线穿过多边形边界的次数为奇数时点在多边形内return flag;}
