找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 9758|回复: 35

[教学] 给大家写个“给图中的BLOCK添加遮罩”的工具

[复制链接]

已领礼包: 145个

财富等级: 日进斗金

发表于 2013-5-10 16:53:33 | 显示全部楼层 |阅读模式

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

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

×
看 sachindkini 朋友的 “块断曲线”的工具有感,该工具见帖子:http://bbs.xdcad.net/thread-667964-1-1.html

用XDRX_API给大家写了一个给现有BLOCK定义添加WIPEOUT,达到块断曲线同样功能的工具,不仅仅是“断”曲线,可以遮罩任何东西。

看演示,编程思路和技巧看二楼。


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

已领礼包: 145个

财富等级: 日进斗金

 楼主| 发表于 2013-5-10 16:56:15 | 显示全部楼层
[pcode=lisp,true]
;;判断BLOCK定义中是否已有wipeout
(defun $xdob_Block_hasWipeout (blkname / e has)
  (setq has nil)
  (if (xdrx_object_get "block" blkname)
    (progn
      (while (and
               (not has)
               (setq e (xdrx_object_next))
             )
        (if (= "AcDbWipeout" (car e))
          (setq has t)
        )
      )
    )
  )
  has
)

;;对象表、选择集删除
(defun $xdlsp_object_delete (el / e el1 ss x)
  (cond
    ((= (type el) 'ename)
      (mapcar
        '(lambda (x)
           (xdrx_object_delete x)
         )
        el
      )
    )
    ((= 'pickset el)
      (xdrx_setsstodb ss 0)
      (while (setq e (xdrx_getentdxf 0))
        (xdrx_object_delete e)
      )
    )
  )
)
;;主函数,给现有的BLOCK定义,添加wipeout实体,并放入块容器最前面(避免遮罩自身块内实体)
(defun $XDOB_Block_AppendWipeout (blkname tf / box e el el1 el2 ob x)
  (if (and
        (setq ob (xdrx_object_get "block" blkname))  ;;得到BLOCK 对象块容器对象
        (not ($xdob_block_haswipeout blkname))   ;; 判断是否已经制作过wipeout
      )
    (progn
      (while (setq e (xdrx_object_next))   ;;遍历块容器得到所有块内实体并copy到模型空间
        (setq e (cadr e))
        (setq el1 (cons e el))
        (xdrx_entity_transformedcopy e $xdtb_matrix_mat0)
        (setq el2 (cons (entlast) el2))
      )
      (setq el1 (reverse el1)
            el2 (reverse el2)
      )
      ($XDLSP_Object_Delete el1)   ;;删除块内的实体,清空块,以便在第一个位置插入wipeout
      (setq box (apply
                  'xdrx_entity_box         ;;实体包围盒
                  el2
                )
      )
      ($xdlsp_makewipeout box)   ;;制作wipeout
      (mapcar
        '(lambda (x)
           (xdrx_block_append_entity blkname x)  ;;wipeout第一,然后依次插入原来的块内实体。
         )
        (setq el2 (cons (entlast) el2))
      )
      (xdrx_object_delete el2)  ;; 删除临时copy的实体。
      (if tf
         (command ".wipeout" "f" "off")  ;; 根据开关变量,是否显示wipeout外框
      )
    )
  )
  t
)
[/pcode]

测试命令:

[pcode=lisp,true]
(defun c:t5 ( / blkname e e1 from_coord mat p1 to_coord to_vx to_vy to_vz)
  (if (and
        (setq e (car (xdrx_entsel "\n拾取插入块<退出>:" '((0 . "INSERT"))))) ;;支持filter的xdrx_entsel
        (setq blkname (xdrx_getentdxf 2))  ;;得到块名
        ($xdob_block_appendwipeout blkname t) ;; 制作遮罩块,不显示边框。
      )
    (progn
      (while (and
               (setq e1 (xdrx_entsel "\n拾取插入的曲线<退出>:" '((0 . "*line,arc,circle,ellipse")))) ;;拾取曲线实体
               (setq p1 (xdrx_curve_closestpoint (car e1) (cadr e1)))  ;;保证点在曲线上,最近点。
             )
        (setq p1 (last p1)
              from_coord ($xdlsp_entity_getecscoordsystem e) ;; 得到插入块的 “源实体坐标系"
              to_vx (xdrx_curve_getfirstderiv (car e1) p1)         ;;目标坐标系的X轴
              to_vy (xdrx_vector_perpvector to_vx)                ;;目标坐标系的Y轴
              to_vz (xdrx_vector_crossproduct to_vx to_vy)  ;;目标坐标系的Z轴
              to_coord (list (cadr e1) to_vx to_vy to_vz)          ;;向量叉乘得到Z轴
              mat (xdrx_matrix_aligncoordsystem from_coord to_coord) ;;求得源坐标系到目标坐标系的变换矩阵
        )
        (xdrx_entity_transformedcopy e mat);; 作用到实体上,完成一个对齐的插入块。
      )
    )
  )
  (princ)
)
[/pcode]

添加wipeout到块定义编程要点如下:

1、往BLOCK定义中添加wipeout实体,由于draworder对除模型空间外的其他块表容器不起作用,所以我们一定要把wipeout放入块定义的第一个实体。本程序只是简单的求块内所有实体的“包围盒”制作wipeout,具体特定的应用也可以找轮廓线等制作精确的wipeout。

2、如果做到1呢? 程序中把块定义所有实体Transform Copy 出来,然后删除掉块定义中的所有实体后,添加wipeout实体到块定义中。添加后,在一次把Copy出的实体添加回块表容器中。

测试命令T5的编程要点:

1、程序没有用到 sachindkini 朋友提供的LEE-MAC的角度法在曲线上插入块,还是使用了矩阵的方法,主要还是让大家理解矩阵的方便。

2、这个程序里面,没有用以前介绍的,求各种中间矩阵,然后用矩阵组合,最后应用矩阵到块的方法,介绍了另外一种更方便的矩阵方法,就是直接从一个坐标系到另一个坐标的变换方法。

3、图块INSERT的实体坐标系如图:


QQ截图20130510172137.png

我们通过函数

[pcode=lisp,true]
(defun $XDLSP_Entity_GetEcsCoordSystem(e / m_w2u oldcmd)
  (setq oldcmd (getvar "cmdecho"))
  (command "ucs" "Object" e)
  (setq m_w2u (xdrx_matrix_ucs2wcs))
  (command "ucs" "p")
  (setvar "cmdecho" oldcmd)
  ($xdlsp_matrix_getCoordSystem m_w2u)
)
[/pcode]

  1. 命令: ($XDLSP_Entity_GetEcsCoordSystem (car (entsel)))
  2. 选择对象: ((707.705 -42.4508 0.0) (1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
复制代码
上面返回值说明: car --实体坐标系的原点坐标(WCS)
                             '(1 0 0)----实体坐标系的X轴向量
                             '(0 1.0 0.0)----实体坐标系的Y轴向量
                             '(0.0 0.0 1.0)--实体坐标系的Z轴向量
实体坐标系的表示方式就是 from = '(原点 X轴向量 Y轴向量 Z轴向量)

考虑到图块的插入点不一定是图块的中心,所以我们求了图块实体的包围盒的中点(WCS),作为坐标系的原点(因为我们要按照中点去插入曲线上)。

4、曲线插入点位置的UCS坐标系,如图


QQ截图20130510172754.png

这个坐标系是如何得到的尼?

代码:

[pcode=lisp,true]
           (setq   to_vx (xdrx_curve_getfirstderiv (car e1) p1)
              to_vy (xdrx_vector_perpvector to_vx)
              to_vz (xdrx_vector_crossproduct to_vx to_vy)
              to_coord (list (cadr e1) to_vx to_vy to_vz)
           )
[/pcode]

过程手动演示如图:

QQ截图20130510172424.png

解释:

  1. a. 得到曲线在插入点的一阶导数的单位向量(也就是曲线在该点的切向量to_VX),即UCS的X轴。
  2. b. 求向量to_VX的切向量(VerpVector)得到to_VY,即UCS的Y轴。
  3. c. to_VX 和VY 向量叉乘得到VZ,即UCS的Z轴。
  4. d. 和插入点的WCS坐标一起,就得到了UCS的坐标系表达 to <--- (插入点 to_x to_y to_z)
复制代码
现在得到了变换前的原坐标系 from_coord  ,也得到了目标坐标系 to_coord

下面用XDRX_API的从一个坐标系到另一个坐标系的变换矩阵函数xdrx_matrix_alignCoordSystem

[pcode=lisp,true]
(setq mat (xdrx_matrix_alignCoordSystem from_coord to_coord))
[/pcode]

这样直接根据两个坐标系就直接得到了变换矩阵,而省略了以前需要在各自坐标系还需要的额外的变换。

最后用XDRX_API实体矩阵COPY函数: xdrx_entity_transFromedCopy 得到了一份坐标系对齐的实体(插入的WIPEOUT块)。

[pcode=lisp,true]
(xdrx_entity_transformedcopy e mat)
[/pcode]

源坐标系和目标坐标系,都是相对WCS坐标系定义的,就是他们的原点都是WCS下的点

上面说了那么多,其实看到程序代码也就几行。思路清晰,矩阵构造准确,程序很容易写。


不清楚的,可以跟帖研讨坐标系间变换矩阵的方法。

XDRX_API 16 版本下载地址: http://bbs.xdcad.net/forum.php?mod=viewthread&tid=667981

点评

谢谢老大分享思路和经验  详情 回复 发表于 2013-8-1 21:06

评分

参与人数 2D豆 +10 贡献 +1 收起 理由
wowan1314 + 5 坐标系变换更快捷,都不用去想中间怎么转。.
炫翔 + 5 + 1 很给力!经验;技术要点;资料分享奖!

查看全部评分

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

使用道具 举报

发表于 2013-5-10 18:14:50 | 显示全部楼层
{:soso_e102:}先占个位置,慢慢学习  还有源码说!{:soso_e183:}
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

使用道具 举报

已领礼包: 1632个

财富等级: 堆金积玉

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

使用道具 举报

已领礼包: 19个

财富等级: 恭喜发财

发表于 2013-5-10 20:55:15 | 显示全部楼层
这工具牛,以前自己做过INSERT实体的WIPEOUT,不过都顶多是用组和INSERT组合在一起,有时候组关的时候,移动实体就会出现WIPEOUT没了。现在好了,直接给做到块里面了,再也不怕丢了。有了这工具,那些什么打断的是不是都可以不用了。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 449个

财富等级: 日进斗金

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

使用道具 举报

已领礼包: 5586个

财富等级: 富甲天下

发表于 2013-5-11 10:27:53 | 显示全部楼层
XDRX_API 16 版本下载地址: http://bbs.xdcad.net/forum.php?tid=667981

XDRX_API 16 版本下载地址.jpg

评分

参与人数 1D豆 +4 收起 理由
XDSoft + 4 热心帮忙奖!

查看全部评分

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

使用道具 举报

已领礼包: 604个

财富等级: 财运亨通

发表于 2013-5-11 10:58:22 | 显示全部楼层
这个块遮罩功能太好了,盼之久矣,感谢楼主!!!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

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

使用道具 举报

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

使用道具 举报

已领礼包: 308个

财富等级: 日进斗金

发表于 2013-5-13 10:43:47 | 显示全部楼层
:lol老大出手,不同凡响,这个功能很好
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2013-5-13 10:46:25 | 显示全部楼层
LZ 没有讲讲为什么要重新生成一遍 Entity,还有 Autocad 的显示是如何控制的,而且 SortentsTable 和 实体生成是什么关系?
DrawOrder 改变的是什么?永久改变还是临时改变?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

 楼主| 发表于 2013-5-13 12:52:29 | 显示全部楼层
Free-Lancer 发表于 2013-5-13 10:46
LZ 没有讲讲为什么要重新生成一遍 Entity,还有 Autocad 的显示是如何控制的,而且 SortentsTable 和 实体 ...

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

使用道具 举报

已领礼包: 1999个

财富等级: 堆金积玉

发表于 2013-5-13 13:16:56 | 显示全部楼层
dear sir,
wow nice code api

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-28 15:27 , Processed in 0.465628 second(s), 64 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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