xxsheng 发表于 2008-4-9 17:18:00

本帖最后由 作者 于 2008-4-10 8:53:55 编辑

(defun >&>(>a >b);计算向量的点积----
  (apply '+ (mapcar '* >a >b))
)
;|功能:自动选择所有相似的图形----
;(objsimilar (car (entsel)))|;
(defun objsimilar(ent1 / n objtype i allderiv1 entlen tmp dianji ss m tmpent par l tmplen allderiv2 tmpdianji
                 rdianji)
  (setq n(fix(- (vlax-curve-getendParam ent1) (vlax-curve-getStartParam ent1)))
    objtype(cdr(assoc 0 (entget ent1)))
    i -1 allderiv1 nil
    entlen (vlax-curve-getDistAtParam ent1 (vlax-curve-getendparam ent1))
    )
  (while (<(setq i(1+ i))n)
    (setq allderiv1(cons (vlax-curve-getFirstDeriv ent1 i) allderiv1))
  )
  (setq tmp (car allderiv1)
    dianji(mapcar '(lambda(x)(>&> x tmp)) allderiv1)
    )
  ;上面获得曲线的类名,参数值,一阶导数---------------------------------
  (if (and (setq ss(ssget "x" (list (cons 0 objtype))))
       (setq ss(ssdel ent1 ss))
       (setq m(sslength ss))
      )
    (progn
      (setq i -1)
      (while (<(setq i(1+ i))m)
    (setq tmpent(ssname ss i))
    (if(= n (setq par(fix(- (vlax-curve-getendParam tmpent)(vlax-curve-getStartParam tmpent)))))
      (progn
        (setq l -1 allderiv2 nil tmplen(vlax-curve-getDistAtParam tmpent (vlax-curve-getendparam tmpent)))
        (while (<(setq l(1+ l))n)
          (setq allderiv2(cons (vlax-curve-getFirstDeriv tmpent l) allderiv2)))
        (setq tmp (car allderiv2)
          tmpdianji(mapcar '(lambda(x)(>&> x tmp)) allderiv2)
          )
        (setq tmp (/ tmplen entlen)
          tmp(* tmp tmp)
          )
        (setq rdianji(mapcar '(lambda(x)(* tmp x)) dianji))
        (if (equal rdianji tmpdianji 1e-3);如果要有容差的话,这里可以改变一下--
          (progn;相似--------
        ;其实比例已经出来了,旋转角度也可以由两个向量得到,最多只要镜像就可以了--
        (redraw tmpent 3)
          )
        )
      )
    )
      )
    )
  )
)

xxsheng 发表于 2008-4-9 17:21:00

不好意思,才想起来,任意两条线段和圆弧都是相似,,,不过上面的对于其他类型的曲线应该都可以了,镜像,旋转,缩放,,,,,,,,,,,,,,,,,,,,,,,

njwtg 发表于 2008-4-11 08:27:00

谢谢<strong><font color="#0000ff">,</font></strong>请问怎么转化啊?

hanyu_gis 发表于 2008-4-11 09:22:00

<p>有些难度啊。</p><p>有的符号什么的不是一企图产远啊,有的符号是两种图元做出来的,这种在程序中怎么判别呢?如果是线的话还好弄些。</p><p>希望看到高手的解决方案。</p>

xxsheng 发表于 2008-4-11 10:01:00

;|功能:自动选择所有相似的图形并生成块----对于线段和弧形还有圆可能不能很好的支持,需要另外判断-----
;(objsimilar (car (entsel)))
觉得实用性好像不是很强~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
还有一个就是如果曲线的前三个顶点在同一个直线上的话,可能不能正确的判断镜像---

|;
(defun objsimilar(ent1 / n objtype i allderiv1 entlen adwg blks spoint npoint blkname blkdef mspace tmp dianji 1ofent1
                 ss m tmpent par l allderiv2 tmplen tmpdianji tmp2 rdianji insp tmpp2 1ofent2 zdir ang tmpblkref
                 mat threep tmpthreep tmpdir rdir)
  (setq n(fix(- (vlax-curve-getendParam ent1) (vlax-curve-getStartParam ent1)))
    objtype(cdr(assoc 0 (entget ent1)))
    i -1 allderiv1 nil
    entlen (vlax-curve-getDistAtParam ent1 (vlax-curve-getendparam ent1))
    adwg(vlax-get (vlax-get-acad-object) "Activedocument")
    blks(vlax-get adwg "blocks")
    spoint(vlax-curve-getStartPoint ent1)
    npoint(vlax-curve-getPointatparam ent1 1)
    blkname(getvar "tdusrtimer")
    blkdef(vlax-invoke blks 'add spoint blkname)
    mspace(vlax-get adwg "modelspace")
    )
  (vlax-invoke adwg 'copyobjects (list (vlax-ename->vla-object ent1)) blkdef);生成块-----
  (while (<= (setq i(1+ i)) n)
    (setq allderiv1(cons (vlax-curve-getFirstDeriv ent1 i) allderiv1))
  )
  (setq tmp (car allderiv1)
    dianji(mapcar '(lambda(x)(>&> x tmp)) allderiv1)
    1ofent1(->1ofa (>-> npoint spoint))
  )
  ;上面获得曲线的类名,参数值,一阶导数---------------------------------如果只有两个点的话-
  (if (and (setq ss(ssget "x" (list (cons 0 objtype))))
       (setq ss(ssdel ent1 ss))
       (setq m(sslength ss))
      )
    (progn
      (setq i -1)
      (while (<(setq i(1+ i))m)
    (setq tmpent(ssname ss i))
    (if(= n (setq par(fix(- (vlax-curve-getendParam tmpent)(vlax-curve-getStartParam tmpent)))))
      (progn
        (setq l -1 allderiv2 nil tmplen(vlax-curve-getDistAtParam tmpent (vlax-curve-getendparam tmpent)))
        (while (<= (setq l(1+ l)) n)
          (setq allderiv2(cons (vlax-curve-getFirstDeriv tmpent l) allderiv2)))
        (setq tmp (car allderiv2)
          tmpdianji(mapcar '(lambda(x)(>&> x tmp)) allderiv2)
          )
        (setq tmp (/ tmplen entlen)
          tmp2(* tmp tmp)
          )
        (setq rdianji(mapcar '(lambda(x)(* tmp2 x)) dianji))
        (if (equal rdianji tmpdianji 1e-3);如果要有容差的话,这里可以改变一下--
          (progn;相似--------
        ;其实比例已经出来了,旋转角度也可以由两个向量得到,最多只要镜像就可以了--
        (redraw tmpent 3)
        (setq insp(vlax-curve-getStartPoint tmpent)
              tmpp2(vlax-curve-getPointatparam tmpent 1)
              )
        (setq 1ofent2(->1ofa (>-> tmpp2 insp)))
        (setq zdir(>*> 1ofent1 1ofent2))
        (setq ang(acos (>&> 1ofent1 1ofent2)))
        (if (equal '(0 0 0) zdir 1e-3);两向量平行或者反向,---------------------
          (setq tmpblkref(vlax-invoke mspace 'InsertBlock insp
                       blkname tmp tmp tmp ang))
          (progn
            (setq tmpblkref(vlax-invoke mspace 'InsertBlock insp
                       blkname tmp tmp tmp 0))
            (setq mat(rotatemat insp (mapcar '+ zdir insp) ang))
            (vla-transformby tmpblkref (vlax-tmatrix mat))
          )
          ;;上面解决了绕Z轴旋转的问题------------------------------------------
        )
        ;;下面解决镜像和三维旋转的问题-----------------------------------------
        (if (> n 2);只有当段数大于2的时候也就是至少三个点的时候才进行判断镜像--
          (progn
            ;;首先进行原来线段的前两个向量的叉乘--
            ;;再进行新线段的前两个向量的叉乘------
            ;;求两个叉乘的法向量,并且得到角度-----
            ;;然后旋转该角度----------------------
            (setq threep(vlax-curve-getPointatparam ent1 2)
              threep(>-> threep spoint)
              tmpthreep(>-> (vlax-curve-getPointatparam tmpent 2) insp)
              zdir(->1ofa(>*> 1ofent1 threep))
              tmpdir(->1ofa(>*> 1ofent2 tmpthreep))
              rdir(>*> zdir tmpdir)
              ang(acos (>&> zdir tmpdir))
              )
            (if (equal '(0 0 0) rdir 1e-3);两向量平行或者反向,---------------------
              (progn
            (if (< (>&> zdir tmpdir) 0)
              (progn
                (setq mat(rotatemat insp tmpp2 pi))
                (vla-transformby tmpblkref (vlax-tmatrix mat)))
            )
              )
              (progn
            (setq mat(rotatemat insp (mapcar '+ rdir insp) ang))
            (vla-transformby tmpblkref (vlax-tmatrix mat))
              )
            )
          )
        )
        ;上面创建块完毕,可以直接进行删除原来的图元---------------------------
        ;(entdel tmpent)
          )
        )
      )
    )
      )
    )
  )
)
;;定义向量的减法>->
(defun >->(>a >b)
  (mapcar '- >a >b)
)
(defun ->1ofa(>a / |a|);对零向量未加判断-----------------
  (setq |a|(/ 1 ((sqrt(apply '+ (mapcar '* >a >a))))))
  (mapcar '(lambda(y)(* y |a|)) >a)
)
;;定义向量的数性积>&>
(defun >&>(>a >b)
  (apply '+ (mapcar '* >a >b))
)
;|旋转矩阵----
罗德里格斯旋转公式:
T(v)=(r&> (cos 0.785398) v)+(r&> (sin 0.785398) (>*> u v))+(r&> (* (- 1 (cos 0.785398))(>&> u v)) u)
(>+> (r&> (cos 0.785398) v)(>+> (r&> (sin 0.785398) (>*> u v)) (r&> (* (- 1 (cos 0.785398))(>&> u v)) u)))
参数一为旋转轴的起点,可以为nil,则起点为'(0 0 0)
参数二为旋转轴的端点,如果第一个参数为nil,则本参数代表旋转轴的方向向量--
参数三为旋转角度---------
(rotatemat '(1 2 3) '(5 5 5) pi)
|;
(defun rotatemat(sp ep ang / ->1of i cosv sinv antimat t1 t2 t3)
  (if sp
    (setq ->1of(->1ofa (mapcar '- ep sp)))
    (setq ->1of(->1ofa ep))
  )
  (setq cosv(cos ang)
    sinv(sin ang)
    antimat(antisymmetricmatof-> ->1of)
    t1(list (list cosv 0 0)(list 0 cosv 0)(list 0 0 cosv))
    t2(r*mat (- 1 cosv) (>@> ->1of nil))
    t3(r*mat sinv antimat)
    t1(mat+mat t1 t2)
    t1(mat+mat t1 t3)
    )
  (if (->zerop sp)
    (list (list (car(car t1))(cadr(car t1))(caddr(car t1)) 0)
      (list (car(cadr t1)) (cadr(cadr t1))(caddr(cadr t1))0)
      (list (car(caddr t1))(cadr(caddr t1))(caddr(caddr t1))0)
      '(0 0 0 1))
    (progn
      (setq sp(>-> sp (mapcar '(lambda(x)(>&> x sp)) t1)))
      (list (list (caar t1)(cadar t1)(caddar t1) (car sp))
        (list (caadr t1)(cadadr t1)(caddr(cadr t1)) (cadr sp))
        (list (caaddr t1)(cadr(caddr t1))(caddr(caddr t1)) (caddr sp))
        '(0 0 0 1))
    )   
  )
)
;|定义向量的等价反对称矩阵-----------------------------
(antisymmetricmatof-> '(1 2 3));返回:((0 -3 2) (3 0 -1) (-2 1 0))
|;
(defun antisymmetricmatof->(->a / a b c)
  (setq a(car ->a)
    b(cadr ->a)
    c(caddr ->a))
  (list (list 0 (- c) b)
    (list c 0 (- a))
    (list (- b) a 0)
    )
)
;|功能:定义向量的张量积--<计算机图形学几何工具算法详解 P105>
(>@> '(1 0 0) '(1 0 0))
就是矩阵相乘:(mat*mat '((1) (0) (0)) '((1 0 0)))
             (mat*mat (transposed (list ->a)) (list ->b))
返回:((1 0 0) (0 0 0) (0 0 0))
(>@> '(4 5 2) '(1 3 2));返回:((4 12 8) (5 15 10) (2 6 4))
|;
(defun >@>(->a ->b / tmp)
  (if (null ->b)(setq ->b ->a))
  (mapcar '(lambda(x)(mapcar '(lambda(y)(* x y)) ->b)) ->a)
)
;;定义数乘矩阵------------------------------------
;;(r*mat 5 '((1 2 3 100)(4 5 6 200)(7 8 9 300)(10 11 12 400)))
(defun r*mat(r mat)
  (mapcar '(lambda(x)(mapcar '(lambda(y)(* r y)) x))mat)
)
;;定义矩阵的相加----------------------------------
(defun mat+mat(lst1 lst2)
  (mapcar '(lambda(x y)(mapcar '(lambda(m n)(+ m n)) x y)) lst1 lst2)
)
;;定义向量的叉乘>*>
;;叉乘得到的向量的意义:方向与>a和>b均垂直,
;;且使(>a >b (>*> >a >b))成右手系--------
;;几何意义:叉乘的模等于以两向量为邻边的平行四边形的面积-
(defun >*>(>a >b)
     (list (- (* (cadr >a)(caddr >b)) (* (caddr >a)(cadr >b)))
       (- (* (caddr >a)(car >b)) (* (car >a)(caddr >b)))
       (- (* (car >a)(cadr >b)) (* (cadr >a)(car >b))))
    )
)

无痕 发表于 2008-4-11 13:42:00

为什么每行前面打 ";" ?

njwtg 发表于 2008-4-11 13:50:00

<p><strong><font face="Verdana" color="#61b713">xxsheng先生,您好!</font></strong></p><p><strong><font face="Verdana" color="#61b713">能否请您做成lsp,运行的命令是什么呀?怎么用不起来?</font></strong></p>

ZZXXQQ 发表于 2008-4-11 18:40:00

无痕发表于2008-4-11 13:42:00static/image/common/back.gif为什么每行前面打 \";\" ?

<p></p>好象是浏览器的问题。如果不是微软的浏览器,发贴就会这样。

njwtg 发表于 2008-4-18 11:03:00

请问怎么用啊?

phonixs 发表于 2008-4-19 11:56:00

<p>太厉害了........</p><p>正在漫漫研究..</p><p></p><p></p>
页: 1 2 [3] 4 5
查看完整版本: [求助]恳求zzxxqq,如何将图元转成块