回望南山
记忆痕迹可以鲜明, 回望往事如数家珍——
posts - 177,  comments - 54,  trackbacks - 0

;;;射线法及角度法求解点是否在曲线内
;;;
;;;
;;;射线法,支持各种曲线的测试

(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 深藏记忆 阅读(334) 评论(0)  编辑  收藏 所属分类: Vlisp之韵

飘过是缘,相识最真

订阅到抓虾
google reader
gougou


点击这里给我发消息


<2008年3月>
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345

常用链接

留言簿(5)

随笔分类

随笔档案

文章分类

文章档案

相册

收藏夹

八面来息

天天充电

同行者

积分与排名

  • 积分 - 58699
  • 排名 - 61

最新评论

阅读排行榜

评论排行榜