找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1659|回复: 13

[分享]:也谈关于如何测试点是否在任意多边形内(用纯lisp)

  [复制链接]
发表于 2003-12-10 13:35:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
测试点是否在多边形内用的是“射线法”,即过点作一条射线,如果该射线与多边形相交奇数次,则点在多边形内,如果不相交或相交偶数次,则点在多边形外。问题是在cad中如何用lsp作这条假想的射线。
我的方法是,先测出多边形的总宽度,过点向左和右作两条比这个宽度稍长的线,如果两边均与多边形相交奇数次,则点在多边形内。为了更严谨,我上下左右作四条线。

  1. ;;获取表中最大值
  2. (defun max_lst (lst / lst n m a b maxpt)
  3.   (setq n (length lst))
  4.   (setq m 0)
  5.   (setq a (nth 0 lst))
  6.   (while (/= m n)
  7.     (setq b (nth m lst))
  8.     (if        (> b a)
  9.       (setq maxpt b
  10.             a b
  11.       )
  12.       (setq maxpt a)
  13.     )
  14.     (setq m (1+ m))
  15.   )
  16.   maxpt
  17. )
  18. ;;获取表中最小值
  19. (defun min_lst (lst / lst n m a b minpt)
  20.   (setq n (length lst))
  21.   (setq m 0)
  22.   (setq a (nth 0 lst))
  23.   (while (/= m n)
  24.     (setq b (nth m lst))
  25.     (if        (< b a)
  26.       (setq minpt b
  27.             a b
  28.       )
  29.       (setq minpt a)
  30.     )
  31.     (setq m (1+ m))
  32.   )
  33.   minpt
  34. )
  35. ;;将点表中的x或y坐标组成新表
  36. (defun point_x (pt_lst xory / pt_xlst)
  37.   (setq pt_xlst '())
  38.   (foreach n pt_lst
  39.     (if        (= xory x)
  40.       (setq pt_xlst (cons (car n) pt_xlst))
  41.     )
  42.     (if        (= xory y)
  43.       (setq pt_xlst (cons (cadr n) pt_xlst))
  44.     )
  45.   )
  46.   (setq pt_xlst (reverse pt_xlst))
  47. )
  48. ;;测试点是否在多边形内(判断四个方向,如果四个方向均认为在多边形内,点就肯定在多边形内。)
  49. (defun ea:point_inm (p pm xory ang / p1 p2 tf tf1 tf2 mx my)
  50.   (setq mx (- (max_lst (point_x pm xory)) (min_lst (point_x pm xory))))
  51.   (setq        p1  (last pm)
  52.         px1 (polar p ang (+ mx 100))
  53.   )
  54.   (foreach p2 pm
  55.     (if        (inters p px1 p1 p2)
  56.       (if (= tf nil)
  57.         (setq tf t)
  58.         (setq tf nil)
  59.       )
  60.     )
  61.     (setq p1 p2)
  62.   )
  63.   tf
  64. )

  65. (defun c:qqq ()
  66.   (setq aalst '())
  67.   (setq aa (getpoint "\n选取多边形的一个顶点"))
  68.   (setq aalst (cons aa aalst))
  69.   (setq dd aa)
  70.   (while (setq cc (getpoint aa "\n选取多边形的下一顶点"))
  71.     (grdraw aa cc 7 1)
  72.     (setq aa cc)
  73.     (setq aalst (cons aa aalst))
  74.   )
  75.   (grdraw aa dd 7 1)
  76.   (while (setq bb (getpoint "\n选取一点"))
  77.     (if        (or (and (ea:point_inm bb aalst x 0)
  78.                  (ea:point_inm bb aalst x pi)
  79.             )
  80.             (and (ea:point_inm bb aalst x (* 0.5 pi))
  81.                  (ea:point_inm bb aalst x (* 1.5 pi))
  82.             )
  83.         )
  84.       (princ "\n该点在多边形内 ")
  85.       (princ "\n该点不在多边形内")
  86.     )
  87.   )
  88.   (princ)
  89. )

)欢迎大家来测试。看看有没有例外。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
发表于 2003-12-10 13:55:51 | 显示全部楼层
运行出错呀~
另外我想这种情况,是不是测不准?
算法设计不精密,测四个方向的意义不大,只是提高了准确率,却不能做到100%准确~
我想,
除了测量射线与多边形的各边的交点数(M),
还需要测量在射线上的多边形的端点数(N),
与射线重合的多边形边线的条数(O)
如果(rem  (- (+ M N) O)2)为奇数则在多边形内部,否则就在外部。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2003-12-10 14:03:13 | 显示全部楼层
说说有什么提示,我这里是好的呀,我试了上面的图形没有问题,同样可以的。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2003-12-10 14:18:21 | 显示全部楼层
那为什么要测四个方向呢?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2003-12-10 14:22:19 | 显示全部楼层
呵呵上面的程序是有个错误,现在改好了,你试试,我上面说过,只要两个方向就行了。
嗯上面的图形确实有问题,你说的对!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2003-12-10 14:44:01 | 显示全部楼层
转贴此帖来自明经通道
(defun GetNext (i n)
  (if (= i (1- n))
    0
    (1+ i)
  )
)

(defun c:test( / ss pt sname ent pt_tmp pt_lst vname area areaall)
  (setq ss (ssget))
  (setq pt (getpoint "Enter the point:"))
  (setq sname (ssname ss 0))
  (setq ent (entget sname))
  (while (setq pt_tmp (assoc 10 ent))
    (setq pt_lst (append pt_lst (list (cdr pt_tmp))))
    (setq ent (cdr (member pt_tmp ent)))
    (setq pts (append pts (list pt)))
  )
  (setq area 0)
  (setq i 0)
  (setq n (length pt_lst))
  (while (< i n)
    (entmake (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(67 . 0) '(410 . "Model") '(100 . "AcDbPolyline")
     '(90 . 7) '(70 . 0) '(43 . 0.0) '(38 . 0.0) '(39 . 0.0)
     (cons 10 pt)
     '(40 . 0.0) '(41 . 0.0) '(42 . 0.0)
     (cons 10 (nth i pt_lst))
     '(40 . 0.0) '(41 . 0.0) '(42 . 0.0)
     (cons 10 (nth (GetNext i n) pt_lst))
     '(210 0.0 0.0 1.0))
      )
    (setq ent (entlast))
    (setq vname (vlax-ename->vla-object ent))
    (setq area (+ area (vla-get-area vname)))
    (entdel ent)
    (setq i (1+ i))
  )
  (setq areaall (vla-get-area (vlax-ename->vla-object sname)))
  (if (equal area areaall 0.000000001)
    (princ "\nin")
    (princ "\nout")
  )
  (princ)
)
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2003-12-10 15:30:35 | 显示全部楼层
改了一下,现在只有一种情况判断错误,就是当点在……怎么说呢看图吧,就是wkai提供的图形的那个点上,我想只要再增加其它的角度,只要其中任一角度判断在多边形内那点就在多边形内。当然那个点那个点还是存在的,但是碰到这个点的可能性就太小了,已经能满足实际需要了。

现在知道我判断四个方向的用意了吧。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2003-12-10 15:46:54 | 显示全部楼层
就是用四个点虚拟出一个矩形然后再判断这个点的坐标就可以了是吗
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2003-12-10 16:27:39 | 显示全部楼层
最初由 zhynt 发布
[B]现在知道我判断四个方向的用意了吧。 [/B]


算法精确的话,只需要判断一次~
测试一下我的程序
http://www.xdcad.net/forum/showt ... d=677002#post677002
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 488个

财富等级: 日进斗金

发表于 2003-12-10 22:25:22 | 显示全部楼层
射线算法,autodesk上好像有.
晓东用arx写的(好像有bug)

求的那点射向无重远(保证出那个框就可以)
交点是单数就在里面,反之在外面.(除在曲线上)
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2003-12-11 02:52:59 | 显示全部楼层
主要是在lsp中作不出无穷远的点,只要是有长度,就有例外.
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2003-12-11 08:04:55 | 显示全部楼层

  1. ;; From a Tony Tanzillo suggestion, see
  2. ;; John Uhden's @cv_inside function thread.
  3. ;; minimal, dirty, etc...
  4. ;;
  5. (defun ALE_ISINSIDE (IMPPNT ENTNAM / NEWENT ENTARE)
  6.   (command "_.AREA" "_O" ENTNAM)
  7.   (setq ENTARE (getvar "AREA"))
  8.   (command "_.OFFSET" (/ ENTARE 10000) ENTNAM IMPPNT "" "_.AREA" "_O"
  9.     (setq NEWENT (entlast))
  10.   )
  11.   (entdel NEWENT)
  12.   (> ENTARE (getvar "AREA"))
  13. )

  14. ;;command: pline 0.0 100,0 100,50 0,50 c

  15. ;;command: (ALE_IsInside '(-0.00000000001 -0.00000000001) (entlast))
  16. ;;nil

  17. ;;command: (ALE_IsInside '(0.00000000001 0.00000000001) (entlast))
  18. ;;T
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2003-12-11 08:32:58 | 显示全部楼层
如果那个点在图形上的时候会出现不同的结果,有的点详图形上,有的点说不图形上。主要表现在凹多边形。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2003-12-11 10:08:06 | 显示全部楼层
Wkai的程序比我的强多了,我的这个基本上可以枪毙了。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2025-9-26 20:47 , Processed in 0.455327 second(s), 59 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表