1. ;;说明:判断点在多段线构成的多边形内侧还是外侧
  2. ;;参数:pt:点
  3. ;;参数:var:多段线构成的多边形图元名或者多边型点表
  4. ;;参数:flag:如果为T,则点在多边形上时,则判断为多边形内侧,否则则判断为外侧
  5. ;;返回:内侧为:T,外侧为:nil
  6. ;;(PtIsInPoly (getpoint) (car (entsel)) t)
  7. ;;(PtIsInPoly (getpoint) (list (getpoint) (getpoint)) t)
  8. (defun PtIsInPoly(pt var flag / getptlst judgestart vlist)
  9. (defun getptlst(e) (mapcar 'cdr (vl-remove-if-not (function (lambda(x) (= 10 (car x)))) (entget e))))
  10. (defun judgestart(vlist / cnt diff idx len numints online p1 p1code p1x p1y p2 p2code p2x p2y vlist x xdiff xx y ydiff)
  11. (if (not (equal (car vlist) (last vlist)))
  12. (setq vlist (append vlist (list (car vlist))))
  13. )
  14. (setq X (car pt)
  15. Y (cadr pt)
  16. len (length vlist)
  17. cnt 0
  18. Idx 0
  19. NumInts 0
  20. OnLine nil
  21. )
  22. (while (and (not OnLine) (< cnt len))
  23. (setq
  24. p2 (nth cnt vlist)
  25. p2x (car p2)
  26. p2y (cadr p2)
  27. p2code (if (>= p2y y) 2 0)
  28. p2code (if (>= p2x x) (1+ p2code) p2code)
  29. )
  30. (if p1
  31. (setq diff (boole 6 p1code p2code)
  32. ydiff (boole 1 diff 2)
  33. xdiff (boole 1 diff 1)
  34. p1x (car p1)
  35. p1y (cadr p1)
  36. )
  37. )
  38. (if (= ydiff 2)
  39. (progn
  40. (setq xx (+ p1x (* (/ (- p2x p1x) 1. (- p2y p1y)) (- y p1y))))
  41. (cond
  42. ((equal xx x 0.0001) (setq online T))
  43. ((> xx x) (setq NumInts (1+ NumInts)))
  44. )
  45. )
  46. )
  47. (if (and (= xdiff 1) (= y p1y p2y)) (setq OnLine T))
  48. (setq p1code p2code p1 p2 cnt (1+ cnt))
  49. )
  50. (if Online flag (= (boole 1 NumInts 1) 0001))
  51. )
  52. (if (equal (type var) 'ENAME)
  53. (judgestart (getptlst var))
  54. (if (and var (listp var) (> (length var) 1)) (judgestart var) (progn (princ "\n点表输入有误!") (prin1)))
  55. )
  56. )

=======================================================================================
以下原文链接
矩形只是多段线的一种解,但是矩形可以利用叉乘做到快速求解,这方面可以自行去搞搞.
这里提供一个最通用的.

测试命令:

  1. public class JJ_test_ckk
  2. {
  3. [CommandMethod("JJ_test_ckk")]
  4. public void TT()
  5. {
  6. Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;
  7. Database db = Acap.DocumentManager.MdiActiveDocument.Database;
  8. ed.WriteMessage(Environment.NewLine + "惊惊net测试区:");
  9. var ppo = new PromptPointOptions(Environment.NewLine + "测试点:")
  10. {
  11. AllowArbitraryInput = true,//任意输入
  12. AllowNone = true//允许回车
  13. };
  14. var ppr = ed.GetPoint(ppo);//用户点选
  15. if (ppr.Status != PromptStatus.OK)
  16. {
  17. return;
  18. }
  19. var peo = new PromptEntityOptions(Environment.NewLine + "点选多段线")
  20. {
  21. AllowObjectOnLockedLayer = false,
  22. AllowNone = false
  23. };
  24. var res = ed.GetEntity(peo);
  25. if(res.Status != PromptStatus.OK) return;
  26. db.Action(tr=>
  27. {
  28. var ent2 =res.ObjectId.ToEntity(tr);
  29. if (ent is Polyline pl && MathTool.IsPointInPL(ppr.Value, pl.GetPoint3ds()))
  30. {
  31. ed.WriteMessage(Environment.NewLine + "内内内内内内内内");
  32. }
  33. else
  34. {
  35. ed.WriteMessage(Environment.NewLine + "外外外外外外外外外外外");
  36. }
  37. });
  38. }
  39. }

id.isok

  1. /// <summary>
  2. /// id有效,未被删除
  3. /// </summary>
  4. /// <param name="id"></param>
  5. /// <returns></returns>
  6. public static bool IsOk(this ObjectId id)
  7. {
  8. return !id.IsNull && id.IsValid && !id.IsErased && !id.IsEffectivelyErased && id.IsResident;
  9. }

射线法:

  1. /// <summary>
  2. /// 判断点在闭合多段线内(线上也是内)射线法
  3. /// </summary>
  4. /// <param name="p">判断的点</param>
  5. /// <param name="pts">边界点集</param>
  6. /// <returns></returns>
  7. public static bool IsPointInPL(Point3d p, IEnumerable<Point3d> pts)
  8. {
  9. var px = p.X;
  10. var py = p.Y;
  11. var flag = false;
  12. var poly = pts.ToArray();
  13. int l = poly.Length;
  14. int j = l - 1;
  15. for (var i = 0; i < l; i++)
  16. {
  17. var pt1x = poly[i].X;//头
  18. var pt1y = poly[i].Y;
  19. var pt2x = poly[j].X;//尾
  20. var pt2y = poly[j].Y;
  21. // 点与多边形顶点重合
  22. if ((pt1x.Eq(px) && pt1y.Eq(py)) || (pt2x.Eq(px) && pt2y.Eq(py)))
  23. {
  24. return true;
  25. }
  26. // 判断线段两端点是否在射线两侧
  27. if ((pt1y < py && pt2y >= py) || (pt1y >= py && pt2y < py))
  28. {
  29. // 线段上与射线 Y 坐标相同的点的 X 坐标
  30. var x = pt1x + (py - pt1y) * (pt2x - pt1x) / (pt2y - pt1y);
  31. // 点在多边形的边上
  32. if (x.Eq(px))
  33. {
  34. return true;
  35. }
  36. // 射线穿过多边形的边界
  37. if (x > px)
  38. {
  39. flag = !flag;
  40. }
  41. }
  42. j = i;
  43. }
  44. // 射线穿过多边形边界的次数为奇数时点在多边形内
  45. return flag;
  46. }