明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1367|回复: 12

[已解答] 在用户坐标系下用vlax-ename,entget,entmake绘制圆的切线

[复制链接]
发表于 2016-5-17 14:34 | 显示全部楼层 |阅读模式
*这个源码在世界坐标系下可以运行画切线操作,但是应用于用户坐标系就不行了,请问需要怎么改?
*以下为源码:

(defun C:jac6 ( / #k1 #os1 &r1 &tc1 ang1 ent1 ent2 ob1 ob2 pt1 pt2 pt3 x)
(setvar "cmdecho" 0)
(setvar "blipmode" 0)
(vl-load-com) ;;加载vlax扩展函数
(setq #os1 (getvar "osmode"))
(if (and (setq ent1 (entsel "\n请选择圆"));1
          (setq ent1 (car ent1))
          (setq #k1 (entget ent1));获取ent1的DXF码
          (= (cdr (assoc 0 #k1)) "CIRCLE");对象类型
          (setq ob1 (vlax-ename->vla-object ent1))
          (setq pt1 (getpoint "\n请选择圆外一点"))
     )
  (progn;;1
   (setvar "osmode" 0)
   (setq pt2 (cdr (assoc 10 #k1));提取圆心坐标
         &tc1 (cdr (assoc 8 #k1));取得圆图层
   )
   (setq pt3 (mapcar '(lambda (x) (* x 0.5)) (mapcar '+ pt1 pt2)));两点中心点
   (setq &r1 (distance pt3 pt1));长度
   (entmake (list '(0 . "CIRCLE") (cons 10 pt3) (cons 40 &r1)));绘制圆
   (setq ent2 (entlast) ob2 (vlax-ename->vla-object ent2))
   (if (and (setq pt3 (vlax-invoke ob1 'IntersectWith ob2 0));2
            (= (length pt3) 6)
       );计算交点,如果在圆外一点就有交点
    (progn;;2
     (setq &r1 (cdr (assoc 40 #k1)));取得圆半径
     (setq ang1 (angle pt2 pt1) pt2 (polar pt2 ang1 &r1));计算修剪点
     (setq pt2 (list (car pt3) (cadr pt3)) pt3 (cdddr pt3))
     (entmake (list '(0 . "LINE") (cons 8 &tc1) (cons 10 pt1) (cons 11 pt2)));绘制切线
     (setq ent3 (entlast) ob3 (vlax-ename->vla-object ent3))
     (setq u1 (list 0 0 0))
     (command"offset" &r1 ent3 u1)
     (setq ent4 (entlast) ob4 (vlax-ename->vla-object ent4))
    );progn;2
   );if;2
   (entdel ent2) ;删除绘制的圆
   (setvar "osmode" #os1)
  );progn;1
);if;1
(prin1)
);



该贴已经同步到 yhs_2016的微博
发表于 2016-5-17 18:50 | 显示全部楼层
加一句(command "ucs" "w")
(defun C:jac6 ( / #k1 #os1 &r1 &tc1 ang1 ent1 ent2 ob1 ob2 pt1 pt2 pt3 x)
(setvar "cmdecho" 0)
(setvar "blipmode" 0)
(vl-load-com) ;;加载vlax扩展函数
(command "ucs" "w")
(setq #os1 (getvar "osmode"))
(if (and (setq ent1 (entsel "\n请选择圆"));1
          (setq ent1 (car ent1))
          (setq #k1 (entget ent1));获取ent1的DXF码
          (= (cdr (assoc 0 #k1)) "CIRCLE");对象类型
          (setq ob1 (vlax-ename->vla-object ent1))
          (setq pt1 (getpoint "\n请选择圆外一点"))
     )
  (progn;;1
   (setvar "osmode" 0)
   (setq pt2 (cdr (assoc 10 #k1));提取圆心坐标
         &tc1 (cdr (assoc 8 #k1));取得圆图层
   )
   (setq pt3 (mapcar '(lambda (x) (* x 0.5)) (mapcar '+ pt1 pt2)));两点中心点
   (setq &r1 (distance pt3 pt1));长度
   (entmake (list '(0 . "CIRCLE") (cons 10 pt3) (cons 40 &r1)));绘制圆
   (setq ent2 (entlast) ob2 (vlax-ename->vla-object ent2))
   (if (and (setq pt3 (vlax-invoke ob1 'IntersectWith ob2 0));2
            (= (length pt3) 6)
       );计算交点,如果在圆外一点就有交点
    (progn;;2
     (setq &r1 (cdr (assoc 40 #k1)));取得圆半径
     (setq ang1 (angle pt2 pt1) pt2 (polar pt2 ang1 &r1));计算修剪点
     (setq pt2 (list (car pt3) (cadr pt3)) pt3 (cdddr pt3))
     (entmake (list '(0 . "LINE") (cons 8 &tc1) (cons 10 pt1) (cons 11 pt2)));绘制切线
     (setq ent3 (entlast) ob3 (vlax-ename->vla-object ent3))
     (setq u1 (list 0 0 0))
     (command"offset" &r1 ent3 u1)
     (setq ent4 (entlast) ob4 (vlax-ename->vla-object ent4))
    );progn;2
   );if;2
   (entdel ent2) ;删除绘制的圆
   (setvar "osmode" #os1)
  );progn;1
);if;1
(prin1)
);
 楼主| 发表于 2016-5-17 19:33 | 显示全部楼层
feng83 发表于 2016-5-17 18:50
加一句(command "ucs" "w")
(defun C:jac6 ( / #k1 #os1 &r1 &tc1 ang1 ent1 ent2 ob1 ob2 pt1 pt2 pt3 x) ...

我刚试了一下,在绕wcs的y轴旋转45度的ucs下画圆做切线,好像不行,只是把当前坐标系换回wcs了。
发表于 2016-5-17 19:43 | 显示全部楼层
yhs_2016 发表于 2016-5-17 19:33
我刚试了一下,在绕wcs的y轴旋转45度的ucs下画圆做切线,好像不行,只是把当前坐标系换回wcs了。

没具体看你程序是怎么运行的,只是针对坐标系原点问题,如果你不做坐标系原点切换(trans)就用(command "ucs" "w"),这样不用切换
 楼主| 发表于 2016-5-17 19:57 | 显示全部楼层
feng83 发表于 2016-5-17 19:43
没具体看你程序是怎么运行的,只是针对坐标系原点问题,如果你不做坐标系原点切换(trans)就用(command  ...

trans我不太会用,如果知道现在ucs的原点,x,y轴方向,用trans怎么改啊?
发表于 2016-5-17 20:05 | 显示全部楼层
trans   函数

语法

    (trans pt from to [disp])

功能及参数

    此函数可以将一个点的坐标值 (或一个位移量) 从某一坐标系统转换到另一个坐标系统。pt参数个含有三个实型数的串列, 可以解释成一个 3D 的点或一个 3D 的位移 (向量)。from 这个参数是一个代码 (Code), 代表 pt 所在的坐标系统, 而 to 这个参数也是一个代码, 代表 pt 所想要转换到的坐标系统 。disp 参数是可有可无的, 假如此参数存在而且其值并非 nil, 则 pt 所代表的就是一个 3D 的位移而不是一个点。下列所述的任何一个代码均可为 from 和 to 的参数。

    ● 下表所列出的是坐标系统整型数码:


坐标系统


通用坐标系统 (WCS)


用户坐标系统 (UCS)


显示:目前视区的 DCS (当使用码0或码1时)。目前模型空间视区的 DCS(当使用码3时)


图纸空间 DCS (只能在使用码2时使用)


    ● 一些函数, 例如: entnext、entlast、entsel、nentsel和 ssname 函数所返回的图元名。如果您是使用这一方式, 则可让您将一点转换到一个特殊图元的图元坐标系统(Entity Coordinate System, ESC)上, 或是从 ESC 转换到另一种坐标系统(对某些图元而言, ECS 和 WCS 是一样的, 所以对这些图元作 ECS 和 WCS 之间的转换并没有意义)上。

    ● 一个 3D 的凸出向量(Extrusion Vector), 它是个含有三个实型数值的表。这是某一坐标系统和一个图元的 ECS之间互相转换的另一种方法。然而, 对 ECS 和 WCS 相同的图元来说, 这种转换并没有作用。trans 将会返回 to 参数所在坐标系统的 3D 点(或位移) 坐标值。

例如, 已知 UCS 是绕着 WCS 的 Z 逆轴时针旋转 90°, 那么:



    (trans '(1.0 2.0 3.0) 0 1)  返回    (2.0 -1.0 3.0)

    (trans '(1.0 2.0 3.0) 1 0)  返回    (-2.0 1.0 3.0)

    下列所述是 trans 所适用的坐标系统, 在此我们同时说明如何使用这些坐标系统:

    WCS:通用坐标系统。这是一个参考 (reference)  坐标系统。其他所有的坐标系统全都是相对于此一坐标系统来定义的。WCS 也是惟一不改变的坐标系统。它的主要用途是在相对于 WCS 所测量得到的值都可以很正确的转换到其他的坐标系统上。

    UCS:用户坐标系统是一个工作 (working) 坐标系统, 它是由用户自行设定的坐标系统, 以便使绘图编辑的工作更容易。所有输入的点(包括 AutoLISP表达式所返回的点, 但不包括前面有*记号的点), 全都视为相对于这一坐标系统。所以, 如果您想要在 AutoCAD 命令中使用 WCS、ECS 或 DCS 的坐标值您就必须先使用 trans, 将它们转换成 UCS 的坐标值。

    ECS:图元坐标系统。由 entget 函数所返回的点坐标值即是相对于这一坐标系统所测量得到的, 这样的点几乎没有什么用处, 除非将这些点转换到适当的坐标系统上。

    DCS:显示坐标系统 (Display Coordinate System)。此系统即为图片在显示前所转换的坐标系统, 此坐标系统的原点为标的(TARGET) 点, 而Z 轴为观测方向。所以, 在 DCS 上永远是平面视图。也就是说, 在视区上, DCS 的 Y 轴向上, 而 X 轴向右。它可以用来决定这些图元在屏幕上给用户看起来是什么样子。当整型数代码 from 和to为 2 和 3 时, 2 表示目前模型空间的视区将使用DCS, 而3表示图纸空间使用DCS(请引用下面 PSDCS)。当代码 2 与其他任何运算元一起使用时, 则不管它是模型空间或图纸空间, 都会假定为目前空间的 DCS, 同时另一点也在目前空间中。

    PSDCS:图纸空间显示坐标系统 (Paper Space Display Coor dinate System)。这只能用来在图纸空间 DCS 和活动的模型空间视区的 DCS 之间进行点的转换。基本上这是一种 2D 的转换, 其中 X 和 Y 坐标总是按比例来决定的, 同时如果 disp 参数没有指定或值为nil 时没有差距。但是 Z 坐标都是以比例来决定的, 并没有经过平移, 因此您可以用来决定两个显示坐标系统之间的比例因数 。除了两个 DCS 之间的转换之外, 将不会在两个空间之间进行转换。

    例如, 假设您想要画一条线, 它的起始点正是一串文字的插入点, 那么在不使用 Osnap 的情况下, 您可以将此文字图素的插入点从文字图元的 ECS 转换到 UCS, 如下所示:

    (trans text-insert-point text-ename 1)

    然后将结果输入到 From point:"的提示语句后。相反的, 在输入点坐标值到 entmod 时, 您必须先将点 (或位移)坐标值转换成所想要的 ECS 坐标值。例如, 您想要在UCS 上移动一个圆, 而所要移动的位移量是 1、2、3, 那么在不使用 MOVE 命令的情况下, 您必须将此位移的 UCS 转换到此圆的 ECS, 如下所示:

    (trans '(1 2 3) 1 circle-ename)

    然后, 您再将结果的位移量加到此圆的中心点上即可。

    例如, 假设某个用户输入一点, 他想要知道现在屏幕上某一条线的两个端点到底是哪一个端点看起来比较靠近用户输入的那一点, 那么首先请您将用户输入的那一点从 UCS 转换到 DCS 上:

    (trans user-point 1 2)

然后, 将那条线的两个端点从 UCS 转换到 DCS 上:

    (trans endpoint line-ename 2)

从上述所得到的答案, 您就可以分别计算从用户输入的点到两个端点间的距离(Z 坐标值可忽略), 如此您就可决定哪一个端点看起来比较靠近了。trans 也可以转换 2D 点。为了达到这个目的, AutoLISP会将 Z 坐标填上一个适当的值。这个填入的 Z 坐标值是由 from 的坐标系统以及您是将此输入的 2D 点当做是一个点还是一个位移来转换, 两者共同决定的。这个填入的 Z坐标值, 如下表所示:



位移

WCS
0.0
0.0

UCS
目前高度
0.0

ECS
0.0
0.0

DCS
投影到目前的绘图平面(UCS XY 平面+目前高度)
0.0

PSDCS
投影到目前的绘图平面(UCS XY 平面+目前高度)
0.0

 楼主| 发表于 2016-5-17 20:12 | 显示全部楼层
wcs是以这个棱台底面中心为原点,横向y,纵向x,垂向z,ucs以一个侧面为xoy面(如图),现在想做过ucs xoy面内一点做该平面内一圆的切线,需要对代码怎么改,或是有什么其他方法吗?

本帖子中包含更多资源

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

x
 楼主| 发表于 2016-5-17 20:32 | 显示全部楼层
feng83 发表于 2016-5-17 20:05
trans   函数

语法

能麻烦你帮我改一下吗,感觉还是没会用啊TT,上面是我要做的图,要过下边那层右上点做坐标原点旁的小圆的切线,实在不会啊,帮帮忙啊,万分感谢!
以下是我画主体部分的源码:
(defun c:jac()
(setvar "cmdecho" 0)
(setvar "blipmode" 0)

(setq w1 (getreal"/底层水平片宽度:"))
(setq l1 (getreal"/底层水平片长度:"))
(setq w2 (getreal"/顶层水平片宽度:"))
(setq l2 (getreal"/顶层水平片长度:"))
(setq x1 (/ w1 2))
(setq y1 (/ l1 -2))
(setq x2 (/ w1 -2))
(setq y2 (/ l1 2))
(setq p1(list x1 y1 0))
(setq p3(list x2 y2 0))
(setq p2(list(car p1)(cadr p3)0))
(setq p4(list(car p3)(cadr p1)0))
(command "line" p1 p2 p3 p4 "c")
(setq h (getreal"/顶层、底层水平片高差:"))
(setq x3 (/ w2 2))
(setq y3 (/ l2 -2))
(setq x4 (/ w2 -2))
(setq y4 (/ l2 2))
(setq p5(list x3 y3 h))
(setq p7(list x4 y4 h))
(setq p6(list(car p5)(cadr p7)h))
(setq p8(list(car p7)(cadr p5)h))
(command "line" p5 p6 p7 p8 "c")
(command "line" p5 p1 "")
(command "line" p6 p2 "")
(command "line" p7 p3 "")
(command "line" p8 p4 "")
(setq n (getreal"/水平片层数:"))
(setq m 3)
(setq s1 (/(- w1 w2) 2))
(setq s2 (/(- l1 l2) 2))
(while(<= m n)
(setq m(1+ m))
(setq e (getreal"/输入该层水平片高度:"))
(setq hi (- h e))
(setq k (/ hi h))
(setq t1 (+(/ w2 2)(* s1 k)))
(setq q1 (+(/ l2 2)(* s2 k)))
(setq t2(* t1 -1))
(setq q2(* q1 -1))
(setq pa(list t1 q2 e))
(setq pc(list t2 q1 e))
(setq pb(list(car pa)(cadr pc)e))
(setq pd(list(car pc)(cadr pa)e))
(command "line" pa pb pc pd "c")
)
(command"ucs" "3" p1 p2 p5)

(setq h1 (sqrt(+ (* s1 s1) (* h h))))
(setq tg (/ (* 2 h1) (- l1 l2)))
(setq afa (atan tg))
(setq af (* afa (/ 180 pi)))
(setq sn (sin afa))
(setq r1 (getreal"/ 输入立片管径:"))
(setq r2 (getreal"/ 输入底层片管径:"))
(setq r3 (getreal"/ 输入下数第二层片管径:"))
(setq d4 (getreal"/ 输入拉筋管直径:"))
(setq r4 (/ d4 2))
(setq xk1 (+ (/ r1 sn) (/ r2 tg)))
(setq tnb (/ h s1))
(setq bat (atan tnb))
(setq snb (sin bat))
(setq ay3 (/ e snb))
(setq yk3 (- ay3 r3))
(setq a1 (- l1 (/ r1 sn)))
(setq a2 (/ yk3 tg))
(setq xk3 (+ a1 a2))
(setq k1(list xk1 r2 0))
(setq pt1(list xk3 yk3 0)); (setq pt1 (trans k3 1 0))
(setq kk1(polar k1 afa 75))
(setq kk3(polar pt1 (- (* 2 pi) afa) 75))

(vl-load-com) ;;加载vlax扩展函数
(setq #os1 (getvar "osmode"))
(if (and (command "circle" kk1 r4)
          (setq ent1 (entlast) ob1 (vlax-ename->vla-object ent1));1
          (setq ent1 (car ent1))
          (setq #k1 (entget ent1));获取ent1的DXF码
          (= (cdr (assoc 0 #k1)) "CIRCLE");对象类型
          (setq ob1 (vlax-ename->vla-object ent1))
     )
  (progn;;1
   (setvar "osmode" 0)
   (setq pt2 (cdr (assoc 10 #k1));提取圆心坐标
         &tc1 (cdr (assoc 8 #k1));取得圆图层
   )
   (setq pt3 (mapcar '(lambda (x) (* x 0.5)) (mapcar '+ pt1 pt2)));两点中心点
   (setq &r1 (distance pt3 pt1));长度
   (entmake (list '(0 . "CIRCLE") (cons 10 pt3) (cons 40 &r1)));绘制圆
   (setq ent2 (entlast) ob2 (vlax-ename->vla-object ent2))
   (if (and (setq pt3 (vlax-invoke ob1 'IntersectWith ob2 0));2
            (= (length pt3) 6)
       );计算交点,如果在圆外一点就有交点
    (progn;;2
     (setq &r1 (cdr (assoc 40 #k1)));取得圆半径
     (setq ang1 (angle pt2 pt1) pt2 (polar pt2 ang1 &r1));计算切点
     (setq pt2 (list (car pt3) (cadr pt3)) pt3 (cdddr pt3))
     (entmake (list '(0 . "LINE") (cons 8 &tc1) (cons 10 pt1) (cons 11 pt2)));绘制切线
     (setq ent3 (entlast) ob3 (vlax-ename->vla-object ent3))
     (setq u1 (list 0 0 0))
     (command"offset" &r1 ent3 u1)
     (setq ent4 (entlast) ob4 (vlax-ename->vla-object ent4))
    );progn;2
   );if;2
   (entdel ent2) ;删除绘制的圆
   (setvar "osmode" #os1)
  );progn;1
);if;1
(prin1)
);
发表于 2016-5-18 19:28 | 显示全部楼层
trans 好像不能从XoY平面切换到XoZ平面的吧,它只是基于同一个平面,进行用户坐标系同WCS,  UCS,   ECS,    DCS,    PSDCS:等坐标系之间的相互转换
发表于 2016-5-18 19:30 | 显示全部楼层
yhs_2016 发表于 2016-5-17 20:32
能麻烦你帮我改一下吗,感觉还是没会用啊TT,上面是我要做的图,要过下边那层右上点做坐标原点旁的小圆的 ...

你的要是固定在X-Z平面内,在提取坐标的时候就提取相应坐标,(第一项X,第二项Y,第三项Z)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-18 20:24 , Processed in 0.214747 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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