明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 3080|回复: 9

[源码] 坐标变换法求块参照与曲线的交点, 向highflybird学习致敬!

[复制链接]
发表于 2013-10-3 17:27:22 | 显示全部楼层 |阅读模式
本帖最后由 zjupxw 于 2013-10-3 22:35 编辑

    国庆就要过去三天了,这三天一直在学习highflybird的坐标变换,刚开始云里雾里,慢慢的有了些思绪,模仿者写了个求块参照(当前仅适于用等比缩放的块参照)与曲线(直线、多段线等)的交点的子程序,调试了一下,效果还不错,特跟大家分享,向highflybird学习致敬!
    该子程序要调用highflybird的Matrix-Lib的子程序集,大家可到链接:http://bbs.mjtd.com/forum.php?mod=viewthread&tid=99926&extra=page%3D1%26filter%3Dtypeid%26typeid%3D108%26t ypeid%3D108 去下载!
  1. (defun  Get-line-block-intersect (line block Acdblist inter_model / matrix Revmatrix result intersect_lst intersect_pnt)
  2.   (if   (not(eq (type line) 'VLA-OBJECT)) (setq line (vlax-ename->vla-object line)) )                  ;转换line类型
  3.   (if   (eq (type block) 'VLA-OBJECT) (setq block (vlax-vla-object->ename block)) )                  ;转换block类型
  4.   (if   (and (eq (vla-get-objectname (vlax-ename->vla-object block)) "AcDbBlockReference" )              ;判断是否等比缩放矩阵
  5.        (equal (abs(cdr (assoc 41 (entget block)))) (abs(cdr (assoc 42 (entget block)))) 1e-8)
  6.        (equal (abs(cdr (assoc 42 (entget block)))) (abs(cdr (assoc 43 (entget block)))) 1e-8)
  7.     )
  8.     (progn
  9.       (setq matrix (Mat:DispToMatrix (car (MAT:RefGeom block)) (last (MAT:RefGeom block))) )           ;图块的变换矩阵        
  10.       (setq Revmatrix (Mat:DispToMatrix (car (MAT:RevRefGeom block)) (last (MAT:RevRefGeom block)) )  )   ;图块的逆变换矩阵
  11.       (vla-TransformBy line (vlax-tmatrix Revmatrix) )                              ;将直线进行逆变换以求交点
  12.       (vlax-for obj  (vla-item (vla-get-blocks (vla-get-ActiveDocument (vlax-get-acad-object)) ) (cdr(assoc 2 (entget block))) )
  13.         (cond  (   (member (vla-get-ObjectName obj) Acdblist)
  14.               (setq intersect_lst (append (vlax-invoke line 'intersectwith obj inter_model) intersect_lst) )    ;调用intersectwith方法求交点
  15.             )
  16.             (  (eq (vla-get-ObjectName obj) "AcDbBlockReference" )                    ;递归调用处理块中块
  17.               (setq intersect_pnt (append (Get-line-block-intersect line obj Acdblist inter_model) intersect_pnt) );将递归结果放入 intersect_pnt去再次变换
  18.             )
  19.         )
  20.       )
  21.       (if   intersect_lst (setq intersect_pnt (append (Intersect-pnt-Handle intersect_lst) intersect_pnt) ) )      ;交点的结果为一维表,将其转化为三维的点列表
  22.       (if  intersect_pnt (setq result (mapcar '(lambda(p) (MAT:mxp matrix p) ) intersect_pnt) ) )        ;将求得的交点变换为实际交点
  23.       (vla-TransformBy line (vlax-tmatrix matrix) )                              ;将曲线(直线)变换回去
  24.           (progn
  25.        (if  (not (eq (vla-get-ObjectName (vlax-ename->vla-object block)) "AcDbBlockReference" ) )
  26.          (setq result (vlax-invoke line 'intersectwith block inter_model) )                    ;非图块直接求交点
  27.        )   
  28.      )
  29.   )                                                     
  30. )
样例: (Get-line-block-intersect line block '("AcDbLine" "AcDbPolyline" "AcDbCircle" "AcDbArc") acExtendnone)
其中 line block参数既可以是图元也可以是VLA对象,上述样例中用于求图库中("AcDbLine" "AcDbPolyline" "AcDbCircle" "AcDbArc")  类型的组件与line的实际交点(acExtendnone)
程序每行写的有些太长,帖子中直接看上去不太好看,但放到EverEdit编辑器中,看着效果还可以的! ^_^
发表于 2013-10-3 21:28:58 | 显示全部楼层
很好的程序,学习了。
 楼主| 发表于 2013-10-3 22:34:05 | 显示全部楼层
忘记后面跟着的一段子程序了,Sorry!
  1. ;;本子程序用于处理一维交点程序点至三维交点
  2. (defun Intersect-pnt-Handle ( intersect_pnt_lst / result_pnt_lst )
  3.         (if  intersect_pnt_lst
  4.                   (progn
  5.                           (repeat (/ (length  intersect_pnt_lst) 3)
  6.                                 (setq result_pnt_lst (cons (list (car  intersect_pnt_lst) (cadr  intersect_pnt_lst) (caddr  intersect_pnt_lst)) result_pnt_lst)  
  7.                                          intersect_pnt_lst (cdddr intersect_pnt_lst)
  8.                                 )               
  9.                         )
  10.                 )
  11.         )
  12.         (reverse result_pnt_lst)
  13. )
发表于 2013-10-4 11:36:06 来自手机 | 显示全部楼层
手机上看不到你的程序,先猜想一下你是怎么做的。1 首先将曲线变换到块ECS中, 2块内各线与曲线求交点, 3 交点变换到WCS下
 楼主| 发表于 2013-10-4 16:10:26 | 显示全部楼层
本帖最后由 zjupxw 于 2013-10-4 16:12 编辑

又琢磨了大半天,模仿highflybird
http://bbs.mjtd.com/forum.php?mo ... 67&page=1#pid502223《块中图元原位复制》的方法,求得了非等比缩放图块(包括块中块)与直线(曲线)的交点,这样所有的求图块与曲线交点的情况都可以适用,代码如下:
  1. (defun Get-line-NoScale-block-intersect(line block Acdblist inter_model / lX lY lZ insert_pt line_blk
  2.                  mat Revmat ref scmat sX sY sZ trsmat
  3.                 new *space intersect_lst intersect_pnt result)
  4.         ;;; 匿名块子程序                                                ;;
  5.         (defun make-anonymous-block (obj insert_pt / blkobj origin bkName *space)
  6.                   (setq origin  (vlax-3d-point insert_pt))
  7.                   (setq blkobj (vla-add (vla-get-blocks *doc) origin "*U"))  
  8.                   ; Blocks(vla-add object insertionpoint name)
  9.                   (setq bkName (vla-get-name blkobj))
  10.                   (vlax-invoke *doc 'copyobjects (list obj) blkobj)   ;把obj拷贝进入匿名块
  11.                   (vla-Delete obj)                                                                        ;把obj(直线)删除
  12.                   (if         (zerop (vla-get-ActiveSpace *doc))
  13.                            (setq *space (vla-get-PaperSpace *doc))
  14.                            (setq *space (vla-get-modelspace *doc))
  15.                    )
  16.                   (vla-insertblock *space origin bkName 1 1 1 0) ;等比插入的匿名块
  17.                   (vla-put-Explodable blkobj :vlax-true)  ;设置属性为可分解
  18.                   blkobj
  19.         )
  20.         (if         (not(eq (type line) 'VLA-OBJECT)) (setq line (vlax-ename->vla-object line)) )                                                                        
  21.         ;转换line类型
  22.         (if         (eq (type block) 'VLA-OBJECT) (setq block (vlax-vla-object->ename block)) )                                                                        
  23.         ;转换block类型
  24.         (setq *doc (vla-get-activedocument (vlax-get-acad-object)))
  25.         (if         (zerop (vla-get-ActiveSpace *doc))
  26.         (setq *space (vla-get-PaperSpace *doc))
  27.         (setq *space (vla-get-modelspace *doc))
  28.     )
  29.     (vlax-invoke *doc 'copyobjects (list line) *space)                                                                                                                        
  30.     ;先拷贝曲线
  31.     (setq Revmat (Mat:DispToMatrix (car (MAT:RevRefGeom block))
  32.             (last (MAT:RevRefGeom block))) )                ;图块的逆变换矩阵
  33.     (setq mat (Mat:DispToMatrix (car (MAT:RefGeom block))
  34.             (last (MAT:RefGeom block))) )                        ;图块的变换矩阵
  35.     (setq lX (cdr (assoc 41 (entget block))) )                                                                                                                                                
  36.     (setq lY (cdr (assoc 42 (entget block))) )                                                                                                                                                        
  37.     (setq lZ (cdr (assoc 43 (entget block))) )                                                                                                                                                
  38.     (setq sX  (/ 1 lx))         ;非均匀缩放则要取得各个比例值
  39.     (setq sY  (/ 1 lY))
  40.     (setq sZ  (/ 1 lZ))
  41.     (setq sclMat (list (list sX 0 0 0)   ;乘以一个比例缩放矩阵使得比例均匀
  42.                      (list 0 sY 0 0)
  43.                      (list 0 0 sZ 0)
  44.                      (list 0 0  0 1)
  45.                 )
  46.     )
  47.     (setq trsmat (MAT:mxm (InverseMatrix sclMat) Revmat) )                                                                                                
  48.     ;因为逆变换,所以需 (setq trsmat (MAT:mxm (InverseMatrix sclMat) Revmat) )
  49.     ; (AB)^-1 =B^-1A^-1 ,原程序是 (setq trsmat (MAT:mxm mat sclMat))
  50.     (vla-transformby (vlax-ename->vla-object (entlast)) (vlax-tmatrix trsmat))  
  51.         ;将最后图元(复制直线)逆变换
  52.     (setq insert_pt (cdr(assoc 10 (entget(tblobjname "block" (cdr(assoc 2 (entget block))) )))) )                                                        
  53.     ;原图块的基点作为匿名图块的插入点
  54.     (setq line_blk (make-anonymous-block (vlax-ename->vla-object (entlast)) insert_pt))                                                                        
  55.     ;得到匿名图块        
  56.     (setq ref (vlax-ename->vla-object (entlast)))                                                                                                                                            
  57.     ;最后图块为插入的匿名图块         
  58.     (vla-put-xscalefactor ref (* (vla-get-xscalefactor ref) sX))                                                                                                                        
  59.     ;;将匿名图块变换到可求交点的位置
  60.     (vla-put-yscalefactor ref (* (vla-get-yscalefactor ref) sY))
  61.     (vla-put-zscalefactor ref (* (vla-get-zscalefactor ref) sZ))
  62.           (command "explode" (list (vlax-vla-object->ename ref)  insert_pt) )                                                                                                        
  63.           ;将匿名图块炸开以求交点
  64.           (setq new (vlax-ename->vla-object (entlast)) )                                                                                                                                          
  65.           ;最后图块为炸开后得到的直线
  66.     (vlax-for obj  (vla-item (vla-get-blocks (vla-get-ActiveDocument (vlax-get-acad-object)) )
  67.                             (cdr(assoc 2 (entget block))) )
  68.                 (cond        (         (member (vla-get-ObjectName obj) Acdblist)
  69.                                         (setq intersect_lst (append (vlax-invoke new 'intersectwith obj inter_model) intersect_lst) )               
  70.                                         ;调用intersectwith方法求交点
  71.                                 )
  72.                                 (        (eq (vla-get-ObjectName obj) "AcDbBlockReference" )                                                                                
  73.                                         ;递归调用处理块中块
  74.                                 (setq intersect_pnt (append (Get-line-block-intersect new obj Acdblist inter_model) intersect_pnt) )
  75.                                         ;将递归结果放入 intersect_pnt去再次变换
  76.                                 )
  77.                 )
  78.         )
  79.         (vla-delete (vlax-ename->vla-object (entlast)))                                                                                                                                         
  80.         ;删除炸开得到的直线
  81.         (vla-delete line_blk)                                                                                                                                                                                 
  82.         ;删除匿名图块
  83.         (if         intersect_lst (setq intersect_pnt (append (Intersect-pnt-Handle intersect_lst) intersect_pnt) ) )                        
  84.         ;交点的结果为一维表,将其转化为三维的点列表
  85.         (if        intersect_pnt (setq result (mapcar '(lambda(p) (MAT:mxp mat p) ) intersect_pnt) ) )                                
  86.         ;将求得的交点变换为实际交点
  87.         ;(if         result (NetBee-2dimension-coordinate result (list 0 < >) 0 )        )                                                                        
  88.         ;调用排序子程序对交点排序,该子程序在论坛的自定义Lisp函数中有,需要的自己去下载
  89. )
 楼主| 发表于 2013-10-4 16:17:00 | 显示全部楼层
这里有个疑问,highflybird原程序中sclMat定义如下:
(setq sclMat (list (list sX 0 0 1)   ;乘以一个比例缩放矩阵使得比例均匀
               (list 0 sY 0 1)
                     (list 0 0 sZ 1)
                     (list 0 0  0 1)
                )
)
我这样变换出来的直线的Z坐标变为1,使得求不到交点,所以必须将sclMat定义如下:
(setq sclMat (list (list sX 0 0 0)   ;乘以一个比例缩放矩阵使得比例均匀
               (list 0 sY 0 0)
                     (list 0 0 sZ 0)
                     (list 0 0  0 1)
                )
这里不知为什么?

发表于 2014-7-6 15:49:17 | 显示全部楼层
坐标变换。。。。。。
发表于 2014-7-8 17:06:52 | 显示全部楼层
zjupxw 发表于 2013-10-4 16:17
这里有个疑问,highflybird原程序中sclMat定义如下:
(setq sclMat (list (list sX 0 0 1)   ;乘以一个比例 ...

我也不太明白,不过看帮助文件中是这样说的“矩阵的前三列指定缩放比例和旋转角度,第四列是一个转换矢量”。如果第4列都是1会按照下式这样加上去吧,也没弄太明白。

本帖子中包含更多资源

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

x
发表于 2020-3-7 11:12:36 | 显示全部楼层
看不明白   
发表于 2022-10-10 21:08:03 来自手机 | 显示全部楼层
向大佬学习
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-12-25 00:50 , Processed in 0.860905 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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