;;;射线法及角度法求解点是否在曲线内
;;;
;;;
;;;射线法,支持各种曲线的测试
(DEFUN InCurve (pt ent / COUNT TMPRAY)
(IF (EQUAL pt (VLAX-CURVE-GETCLOSESTPOINTTO ent pt) 1E-6)
(ALERT "***点在线上***")
(PROGN (SETQ ent (VLAX-ENAME->VLA-OBJECT ent)
TmpRay (VLAX-ENAME->VLA-OBJECT
(ENTMAKEX (LIST '(0 . "RAY")
'(100 . "AcDbEntity")
'(100 . "AcDbRay")
(CONS 10 pt)
(CONS 11 (MAPCAR '+ pt '(1 0)))
;;相当于(polar pt 0 1)
)
)
)
pt (VLAX-3D-POINT pt)
Count 0
)
;;可根据需要调整扫描角度提高检索速度,本程序采用12度
(REPEAT 30
(VLA-ROTATE TmpRay pt (/ PI 15))
;;下面这句可以看到扫描过程,实际使用时可以注释掉
;;(COMMAND "delay" 50)
(IF (ZEROP
(REM (LENGTH (VLAX-INVOKE ent 'INTERSECTWITH TmpRay ACEXTENDNONE)
)
6
)
)
(SETQ Count (1- Count))
(SETQ Count (1+ Count))
)
)
(VLA-DELETE TmpRay)
(IF (MINUSP Count)
(ALERT "***点在线外***")
(ALERT "***点在线内***")
)
)
)
(PRINC)
)
;;;判断是否在封闭多边形内只有这两种方法。射线法比角度法效率高。
;;;
;;;多谢snoopychen提供的资料,粗粗看了一下,发现了一些问题,说错的地方请指正:
;;;1.Luis E的用的是line扫描,效果不如ray.
;;;2.John Uhden用的虽然是ray,但只有一条,出错率很高,比如ray通过曲线端点或相切.我的程序也是ray,不过是旋转生成多条ray,然后统计.统计是程序的关键,可以有效规避上述错误,假设只生成7条ray,就可以允许其中三条是通过端点或相切,结果依然正确.
;;;3.CAB收集的程序很长,没全看,好象是角度法,似乎不支持曲线.
;;;
;;;就射线法和角度法,我的认识是:
;;;1.射线法效率高,但出错率也高,特别对于自相交的曲线,很难判断.比如五角星,点击中间区域,不同方向的射线交点多数是2点,就好象在曲线外似的.
;;;2.角度法效率低,但只要扫描精度够高,可以保证判断结果正确.角度法可以计算出曲线自相交时,点位于第几层.角度法的关键就是怎样在不出错的情况下提高速度.
;;;
;;;我的程序没有附加考虑比如是否选到曲线,曲线是否闭合,UCS/WCS转换等错误判断,只提供了核心部分,这样阅读起来比较直观,实际使用的时候需要增加这些判断.
;;;
;;;角度法有其自身的优势,看看下面的程序:
;;;
;;;
(DEFUN InCurve (pt ent / CURPA DXF0 DXF10 ELST ENDPA KEY NEAPT PTS)
;;三维空间曲线的判断未完善
;;(SETQ pt (TRANS pt 1 0)) ;To WCS
(IF (EQUAL pt
(SETQ NeaPt (VLAX-CURVE-GETCLOSESTPOINTTO ent pt))
1E-6
)
(ALERT "***点在线上***")
(PROGN (SETQ elst (ENTGET ent))
(setq EndPa (VLAX-CURVE-GETENDPARAM ent))
(SETQ dxf0 (CDR (ASSOC 0 elst)))
(COND ((EQUAL EndPa (* 2 PI) 1E-6) ;CIRCLE+ELLIPSE
(setq dxf10 (cdr (assoc 10 elst)))
(IF (> (DISTANCE pt dxf10) (DISTANCE NeaPt dxf10))
(ALERT "***点在线外***")
(ALERT "***点在线内***")
)
)
((= dxf0 "LWPOLYLINE") ;支持bulge
(SETQ pts (MAPCAR (FUNCTION CDR)
(VL-REMOVE-IF (FUNCTION (LAMBDA (x) (/= 10 (CAR x)))) elst)
)
)
(IF (ZEROP (SETQ key (CheckInCurve pt ent (CONS NeaPt pts))))
(ALERT "***点在线外***")
(ALERT (STRCAT "***点在线内第 " (ITOA key) " 层***"))
)
)
((= dxf0 "SPLINE")
(setq pts (list (vlax-curve-getStartPoint ent)))
(setq CurPa 0)
;;可根据需要调整点数
(REPEAT 100
(SETQ pts (CONS (VLAX-CURVE-GETPOINTATPARAM
ent
(SETQ CurPa (+ CurPa (* EndPa 0.01)))
)
pts
)
)
)
(IF (ZEROP (SETQ key (CheckInCurve pt ent (CONS NeaPt pts))))
(ALERT "***点在线外***")
(ALERT (STRCAT "***点在线内第 " (ITOA key) " 层***"))
)
)
(T (ALERT "***暂时不支持的曲线类型***"))
)
)
)
)
(DEFUN CheckInCurve (pt Curve pts)
;;添加最近点,也可以用其他方式,
;;当曲线存在重复点用vl-sort可能会出错,这里偷了点懒
(SETQ pts (VL-SORT pts
(FUNCTION (LAMBDA (p1 p2)
(< (VLAX-CURVE-GETPARAMATPOINT Curve p1)
(VLAX-CURVE-GETPARAMATPOINT Curve p2)
)
)
)
)
)
;;狂刀兄写的,太精辟了,I Like it!!!
(FIX
(+ (/ (ABS
(APPLY (FUNCTION +)
(MAPCAR (FUNCTION
(LAMBDA (p1 p2) (REM (- (ANGLE pt p1) (ANGLE pt p2)) PI))
)
(CONS (LAST pts) pts)
pts
)
)
)
PI
)
0.5
)
)
)
posted on 2008-03-12 22:09
深藏记忆 阅读(341)
评论(0) 编辑 收藏 所属分类:
Vlisp之韵