明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 393|回复: 6

[函数] 判断点在封闭曲线内,跟随黄总的步伐

[复制链接]
发表于 2024-4-3 23:34 | 显示全部楼层 |阅读模式
本帖最后由 dtucad 于 2024-4-3 23:37 编辑

http://bbs.mjtd.com/thread-189728-1-1.html
跟随黄总的步伐,也来两个判断点在封闭曲线内的函数,水平有限,如有错误请反馈
  1. ;第一种
  2. ;判断点是否在非自交多边形内,使用射线交叉法,从要测试的点向任意方向引一条射线,统计射线与多边形边界的交点数量。如果交点数目是奇数,则点位于多边形内部;如果是偶数,则点位于多边形外部。如果交点为多边形顶点可能无法正确判断,此时旋转射线重新判断。
  3. ;参数:pt判断的点、pts多边形点表、fz误差
  4. ;返回:1在内部、0在线上、-1在外部
  5. (defun JudPtinPts (pt pts fz / box d i inter k line lines lines-tmp memberfz ray)
  6.   (defun MemberFz (pt lst fz);带误差的member
  7.     (vl-some (function (lambda(x) (equal pt x fz))) lst)
  8.   )
  9.   
  10.   (setq lines (mapcar (function list) pts (append (cdr pts) (list (car pts)))))
  11.   (if (vl-some ;判断点在线上
  12.         (function (lambda (x / ang1 ang2 p1 p2)
  13.                     (setq p1 (car x))
  14.                     (setq p2 (cadr x))
  15.                     (or
  16.                       (or
  17.                         (equal pt p1 fz)
  18.                         (equal pt p2 fz)
  19.                       )
  20.                       (and
  21.                         (setq ang1 (angle p1 pt))
  22.                         (setq ang2 (angle pt p2))
  23.                         (or (equal ang1 ang2 1e-6)
  24.                           (equal (abs (- ang1 ang2)) (* pi 2) 1e-6)
  25.                         )
  26.                       )
  27.                     )
  28.                   )
  29.         )
  30.         lines
  31.       )
  32.     0;在线上
  33.     (progn;判断交点数量
  34.       (setq box (mapcar (function (lambda (a b) (apply (function mapcar) (cons a b)))) '(min max) (list pts pts)))
  35.       (setq d (+ (apply 'distance box) (distance pt (car pts))))
  36.       (setq ray (list pt (polar pt 0 d)));虚拟一条足够长的射线
  37.       (setq lines-tmp lines)
  38.       (setq i 0 k 0)
  39.       (while (and lines-tmp (< k 360))
  40.         (setq line (car lines-tmp))
  41.         (setq lines-tmp (cdr lines-tmp))
  42.         (if (setq inter (apply 'inters (append ray line)));有交点
  43.           (if (not (MemberFz inter pts fz));且交点不为顶点
  44.             (setq i (1+ i));交点数量
  45.             (setq i 0;归零
  46.               k (1+ k)
  47.               ray (list pt (polar pt (* (/ pi 180) k) d));射线旋转1°
  48.               lines-tmp lines;重新判断
  49.             )
  50.           )
  51.         )
  52.       )
  53.       (cond
  54.         ((zerop (rem i 2)) -1);偶数个交点,在线外
  55.         (t 1);奇数,在线内
  56.       )
  57.     )
  58.   )
  59. )
  1. ;第二种
  2. ;判断点是否在封闭曲线内,生成图元射线找与封闭曲线交点(判断原理同上),支持多段线、圆、椭圆、样条曲线等封闭曲线
  3. ;参数:pt判断的点、e曲线图元名、fz误差
  4. ;返回:1在内部、0在线上、-1在外部
  5. (defun JudPtinCurr (pt e fz / *error* ang cp ed getinter i islock isvertex its k la layobj list->3pair loop mkray obj-cur obj-ray ray vlay)
  6.   ;错误处理
  7.   (defun *error* (msg)
  8.     (if (not (vlax-erased-p obj-ray))
  9.       (vla-Delete obj-ray)
  10.     )
  11.     (princ msg)
  12.   )
  13.   ;表转3D点表
  14.   (defun list->3pair (old / new)
  15.     (while (setq new (cons (list (car old) (cadr old) (caddr old)) new) old (cdddr old)))
  16.     (reverse new)
  17.   )
  18.   ;找2个对象的交点 不延长 返回:交点列表
  19.   (defun getinter (obj1 obj2 / inter iplist re)
  20.     (if (not (vl-catch-all-error-p
  21.                (setq iplist (vl-catch-all-apply 'vlax-safearray->list
  22.                               (list (vlax-variant-value (vla-intersectwith obj1 obj2 acextendnone)))
  23.                             ))))
  24.       (list->3pair iplist)
  25.     )
  26.   )
  27.   ;判断交点是否为曲线顶点或在射线角度上的切点
  28.   (defun IsVertex (obj pt ang / ang-de de n name)
  29.     (if (and
  30.           (setq name (vla-get-ObjectName obj))
  31.           (setq n (vlax-curve-getParamAtPoint obj pt))
  32.         )
  33.       (if (and
  34.             (or
  35.               (= name "AcDbPolyline")
  36.               (= name "AcDb2dPolyline")
  37.               (= name "AcDb3dPolyline")
  38.               (= name "AcDbSpline")
  39.             )
  40.             (equal (fix n) n 1e-8)
  41.           )
  42.         t ;为顶点
  43.         (and ang
  44.           (setq de (vlax-curve-getFirstDeriv obj n))
  45.           (setq ang-de (angle '(0 0 0) de))
  46.           (or ;为切点
  47.             (equal ang-de ang 1e-8)
  48.             (equal ang-de (+ pi ang) 1e-8)
  49.             (equal ang-de (+ (* pi 2) ang) 1e-8)
  50.           )
  51.         )
  52.       )
  53.     )
  54.   )
  55.   ;生成射线 返回图元名
  56.   (defun MKRay (p1 p2)
  57.     (entmakeX
  58.       (list
  59.         '(0 . "RAY")
  60.         '(100 . "AcDbEntity")
  61.         '(100 . "AcDbRay")
  62.         (cons 10 p1)
  63.         (cons 11 (mapcar '- p2 p1))
  64.       )
  65.     )
  66.   )
  67.   
  68.   (setq obj-cur (vlax-ename->vla-object e))
  69.   (if (and
  70.         (setq cp (vlax-curve-getClosestPointTo obj-cur pt))
  71.         (equal cp pt fz)
  72.       )
  73.     0;在线上
  74.     (progn
  75.       (if (and ;解锁当前图层
  76.             (setq la (getvar "CLAYER"))
  77.             (setq layobj (vla-get-Layers (vla-get-activedocument (vlax-get-acad-object))))
  78.             (setq vlay (vla-item layobj la))
  79.           )
  80.         (if (= (vla-get-lock vlay) :vlax-true)
  81.           (progn
  82.             (vla-put-lock vlay :vlax-false)
  83.             (setq islock t)
  84.           )
  85.         )
  86.       )
  87.       (setq ang 0)
  88.       (setq pt (trans pt 1 0))
  89.       (setq ray (MKRay pt (polar pt ang 10)))
  90.       (setq ed (entget ray))
  91.       (setq obj-ray (vlax-ename->vla-object ray))
  92.       (setq k 0 loop t)
  93.       (while (and loop (< k 360))
  94.         (if (setq its (getinter obj-cur obj-ray));有交点
  95.           (progn
  96.             (if (vl-every (function (lambda(p) (not (IsVertex obj-cur p ang)))) its)
  97.               (setq i (length its);交点数量
  98.                 loop nil
  99.               )
  100.               (progn;交点为顶点或切点
  101.                 (setq k (1+ k) ang (* (/ pi 180) k))
  102.                 (entmod (subst (cons 11 (mapcar '- (polar pt ang 10) pt)) (assoc 11 ed) ed));射线旋转1°
  103.               )
  104.             )
  105.           )
  106.           (setq loop nil)
  107.         )
  108.       )
  109.       (if (not (vlax-erased-p obj-ray))
  110.         (vla-Delete obj-ray)
  111.       )
  112.       (if islock ;恢复锁定
  113.         (vla-put-lock vlay :vlax-true)
  114.       )
  115.       (cond
  116.         ((or (not i)(zerop (rem i 2))) -1);偶数个交点,在线外
  117.         (t 1);奇数,在线内
  118.       )
  119.     )
  120.   )
  121. )

评分

参与人数 3明经币 +3 金钱 +5 收起 理由
hubeiwdlue + 1 赞一个!
ssyfeng + 1 赞一个!
tigcat + 1 + 5 很给力!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2024-4-4 19:16 | 显示全部楼层
  1. (defun xyp-PtInCurve (pt e fuzz / p1)
  2.   "xyp-PtInCurve 点是否在封闭曲线内 (xyp-PtInCurve pt点 e封闭曲线 fuzz容差)"
  3.   ;; 1在内部;0在线上;-1在外部
  4.   (if (and (xyp-IsCurve e) (xyp-CurveIsClose e)(setq p1 (vlax-curve-getclosestpointto e pt)))
  5.     (cond ((equal (distance pt p1) 0 fuzz) 0)
  6.           ((xyp-PtInPtn pt (xyp-CurveDivNum e 1000)) 1)
  7.           (t -1)
  8.     )
  9.   )
  10. )
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2024-4-3 23:38 | 显示全部楼层
;测试
(defun c:tt (/ en pt pts)
        (and
                (setq pt (getpoint))
                (setq en (car (entsel "\n选闭合曲线")))
                (setq pts (mapcar '(lambda (x) (trans (cdr x) 0 1)) (vl-remove-if-not '(lambda (x) (= 10 (car x))) (entget en))))
                (princ "\n第一种(不支持弧线):")
                (princ (JudPtinPts pt pts 1e-6))
                (princ "\n第二种(支持弧线):")
                (princ (JudPtinCurr pt en 1e-6))
        )
        (princ)
)
发表于 2024-4-4 10:25 | 显示全部楼层
你的也很不错啊,谢谢啊
发表于 2024-4-4 15:01 | 显示全部楼层
  1. (defun xyp-PtInPtn (p pt)
  2.   "xyp-PtInPtn 点在点集内 (xyp-PtInPtn p点 pt点集)"
  3.   (equal(abs(apply'+(mapcar'(lambda(x y)(rem(-(angle x p)(angle y p))pi))pt(cons(last pt)pt))))pi 1e-8)
  4. )
 楼主| 发表于 2024-4-4 16:37 | 显示全部楼层

院长的代码虽然短小精悍,但是功能比较单一,没法正确判断点在线上,没法判断带弧形的曲线,我以前也是用的类似的,鉴于场景需要,参考黄总的思路写了这个通杀的(上面的第二种函数),各种曲线都到碗里来,还可以自定义精度(可以把离线比较近的点视为在线上,特别适合那些画图不准确的)

评分

参与人数 1明经币 +1 收起 理由
xyp1964 + 1 赞一个!

查看全部评分

发表于 2024-4-7 09:42 | 显示全部楼层
大师出手就是不一样
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-5-2 06:58 , Processed in 1.049871 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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