马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 newer 于 2017-8-3 15:22 编辑
首先我们来看看OCS。
一些2D对象的坐标定义在对象坐标系(lwpolyline,blocks,text ...等等)中,此外,lwpolylines有一个高程数据。
例如,在WCS(图片中为白色)的原点为(1.402 0.347 4.866)并绕3轴旋转的UCS(图片中的绿色)上,以(0 0 0)的方式插入块,旋转为0.0 (橙色)。
现在,得到块参考DXF数据:
得到插入点:
(cdr (assoc 10 (entget ent))) -> (1.444 1.806 4.519)
得到旋转角:
(cdr (assoc 50 (entget ent))) -> 0.39099
我们可以看到插入点坐标既不是WCS(1.402 0.347 4.866)也不是UCS(0.0 0.0 0.0),旋转不是0。
因为坐标是在OCS中定义的,并且关于OCS的X轴的旋转。
OCS根据挤出方向(或正常)和任意轴动量守恒定义(参见帮助手册 “开发人员指南” 的DXF部分中的 “高级DXF概念”)。
对于根据Z矢量计算OCS的X轴和Y轴的例子,您可以看到此消息。
让我们看看有关OCS(红色)的更多信息:
所以,所有OCS的起源与WCS起源相同,和具有相同拉伸方向(210 DXF代码或普通属性)的所有对象都具有相同的OCS。
要计算由3点定义的平面的法向量,见下面的代码:
计算点P1到P2的单位向量
 - ;;; VEC1 Returns the single unit vector from p1 to p2
- (defun vec1 (p1 p2)
- (if (not (equal p1 p2 1e-009))
- (mapcar
- '(lambda (x) (/ x (distance p1 p2)))
- (mapcar '- p2 p1)
- )
- )
- )
求三点组成平面的法线向量
获取当前UCS的Z轴向量
 - ;;; UCSZDIR Returns the Normal Unit Vector of the current UCS
- (defun ucszdir ()
- (trans '(0 0 1) 1 0 T)
- )
一些数学函数
 - ;;; ASIN Returns the arcsinus of a number in radians
- (defun ASIN (num)
- (if (<= -1 num 1)
- (atan num (sqrt (- 1 (expt num 2))))
- )
- )
- ;;;ACOS Returns the arccosinus of a number in radians
- (defun ACOS (num)
- (if (<= -1 num 1)
- (atan (sqrt (- 1 (expt num 2))) num)
- )
- )
- ;;; ANGLE_3PTS Returns the angle (in radians) defined by its summit and two points
- ;;; Returned angle is always positive and less than or equal to pi radians.
- ;; Using vector calculus
- (defun angle_3pts (sum p1 p2 / v1 v2)
- (if (and
- (setq v1 (vec1 sum p1))
- (setq v2 (vec1 sum p2))
- )
- (cond
- ((equal v1 v2 1e-009) 0.0)
- ((equal v1 (mapcar '- v2) 1e-009) pi)
- (T (* 2 (asin (/ (distance v1 v2) 2))))
- )
- )
- )
- ;; Using the "Théorème de Carnot"
- (defun angle_3pts (sum p1 p2 / d1 d2 d3)
- (setq d1 (distance sum p1)
- d2 (distance sum p2)
- d3 (distance p1 p2)
- )
- (if (and (not (zerop d1)) (not (zerop d2))
- (ACOS (/ (+ (* d1 d1) (* d2 d2) (- (* d3 d3)))
- (* 2 d1 d2)
- )
- )
- )
- )
下面代码求一点相对一个平面的高程
 - ;;; ELEV Returns the elevation of point pt from the plane defined by p1 p2 p3
- (defun elev (pt p1 p2 p3)
- (* (cos (angle_3pts p1 (mapcar '+ p1 (norm_3pts p1 p2 p3)) pt))
- (distance p1 pt)
- )
- )
下面代码返回点投影到平面上的坐标
 - ;;; PROJ_PT Returns the coordinates of the projection of point pt
- ;;; on the plane defined by the points p1 p2 p3.
- (defun proj_pt (pt p1 p2 p3)
- (mapcar '-
- pt
- (mapcar '(lambda (x) (* x (elev pt p1 p2 p3)))
- (norm_3pts p1 p2 p3)
- )
- )
- )
知道了上面,我觉得通过下面的代码,应该比较容易在3D下理解TRANS函数的作用。
要得到块参考插入点的WCS坐标,使用的方法是使用它的ename数据:
(trans (cdr (assoc 10 (entget ent))) ent 0) -> (1.402 0.347 4.866),它是WCS中的UCS起始坐标。
以及在UCS中获得它:
(trans(cdr(assoc 10(entget ent)))ent 1)返回非常接近(0.0 0.0 0.0)的(4.440e-016 4.440e-016 8.881e-016)
也可以使用DXF组码210 :
(trans(cdr(assoc 10(entget ent))))(cdr(assoc 210(entget ent)))0)
要使用(entmake ...)或(vla-add ...)在UCS平面上创建2D对象,必须使用另一种方法,因为ent不存在。
所以我们必须计算UCS XY平面的法向量:
(setq ucszdir(trans'(0 0 1)1 0 T))
可以使用ucszdir以及ent或(cdr(assoc 210(entget ent)))。
在与entmake一起使用的列表中:
(cons 210 ucszdir)
ucszdir也是在(vla-put-Normal ...)表达式中使用的Normal属性。
现在坐标的X,Y可以求出,但是旋转如何计算呢?
要获得OCS X轴和UCS X轴之间的角度:
(angle '(0 0 0) (trans (getvar "UCSXDIR") 0 ucszdir)) -> 0.39099作为块旋转DXF数据。
最后,得到lwpolyline的高程(对于块参考的Z坐标的分形,文本...)
要使用entmake或vla-add在UCS平面上创建lwpolyline,我们必须使用trans和ucszdir来指定它的高程:
(caddr(trans'(0 0 0)1 ucszdir)) - > 4.519作为块插入点的Z坐标(DXF组码10)。
希望上面能对您有帮助。
|