xxsheng 发表于 2008-2-21 15:18:00

我的向量和矩阵学习心得

;xxsheng-----2008年2月21日-----------------------
;^_^版权所有,复制修改随便~,但最好保留俺的大名~~~~
;|主要思路:创建一个向量计算的坐标表示方法--------
->o         零向量                 --
->zerop     判断向量是否零向量     --
->1         判断向量是否单位向量   --
>+>         为向量相加             --
>->         为向量相减             --
>&>         向量的数性积         --
r&>         向量的数乘            --
>*>         向量的叉乘            --
->          获得pi点->p2的向量->   --
||          求向量的模           --
cosval      求两向量夹角的余弦     --
prl         求向量A在轴l上面的射影 --
->1ofa      求与向量a平行的单位向量--
|;
;|基本知识储备:
定义: 向量            既有大小又有方向的标量(也叫矢量).<如物理的作用力或者位移就是一种矢量>
      向量的模        有向线段的长度,称为向量的模(或向量的长度)-
      零矢量          长度为0的向量。零向量的方向是不确定的。------
      单位矢量        长度为1的矢量。------------------------------
      两矢量相等      长度相等,方向相同,与起点无关。-------------
      反矢量          长度相同,方向相反的矢量。-------------------
      共线矢量        平行于同一直线的一组矢量。-------------------
      共面矢量        平行于同一平面的一组矢量。-------------------
      矢量的加法      三角形法则          ->AB+->BC=->AC
                      多边形法则          ->AF=->AB+->BC+->CD...+->EF
      矢量的减法      根据矢量的加法反推---------------------------
      矢量的数乘      实数r与矢量->a的乘积r->a是一个矢量,其模=|绝对值r|数学乘->a的模-
                      实数r>0,方向与矢量->a方向同,
                      实数r<0,方向与矢量->a方向相反,
      两矢量的数性积  矢量->a的模和矢量->b的模数学乘再数学乘两矢量的角度的cos(余弦)--
      两矢量的矢性积  两个矢量->a与->b的矢性积(又叫外积,叉积)->a*->b是这样一个矢量:
                      模=矢量->a的模数学乘矢量->b的模再数学乘两矢量的角度的sin(正弦)-
                      方向:与矢量->a和矢量->b都垂直,并且(->a ->b ->a*->b)乘右手法则--
      仿射标架        {->O ->e1 ->e2 ->e3}叫做空间中的一个标架.
                      若->e1 ->e2 ->e3都是单位矢量则{->O ->e1 ->e2 ->e3}叫做笛卡儿标架-------
                      若->e1 ->e2 ->e3互相垂直的笛卡儿标架则叫做笛卡儿直角标架,简称直角标架。-
      矢量的坐标      取定标架{->O ->e1 ->e2 ->e3},若->A=x数乘->e1+y数乘->e2+z数乘->e3,称----
                      {x y z}为->A关于标架{->O ->e1 ->e2 ->e3}的坐标-----------------
                      取定标架{->O ->e1 ->e2 ->e3},B为任意一点,->OB称为点B的径矢---
                      则->OB关于标架的坐标{x y z}称为点B的坐标。---------------------
                      矢量的坐标等于其终点坐标减去其起点坐标.------------------------
      射影矢量        ->AB的起点A和终点B在轴l上的射影为点A'和点B',则->A'B'为->AB在l上的射影矢量-------
      射影            ->A'B'在l上的长度称为->AB在轴l上的射影-------------------------
定理  零矢量与共线(共面)的矢量组均共线(共面);
定理  共线矢量必共面;
定理  两矢量必共面;
定理  三矢量中若有两矢量共线,则这三矢量一定共面。-

|;

;定义向量->o为零向量-----
(setq ->o '(0 0 0))
;判断向量是否零向量------
(defun ->zerop(a)
  (equal a ->o)
  ;(equal a '(0 0 0))
)
;判断向量是否单位向量---
(defun ->1(a)
  (equal (|| a) 1.0)
  ;(equal (apply '+ (mapcar '(lambda(x)(expt x 2))a)) 1.0)
)
;定义向量的模||
(defun ||(>a)
  (float(sqrt(apply '+ (mapcar '(lambda(x)(expt x 2)) >a))))
)
;获得pi点->p2的向量>>
(defun ->(p1 p2)
  (mapcar '- p2 p1)
)
;定义向量的加法>+>
(defun >+>(>a >b)
  (mapcar '+ >a >b)
)
;定义向量的减法>->
(defun >->(>a >b)
  (mapcar '- >a >b)
)
;定义向量的数性积>&>
(defun >&>(>a >b)
  (apply '+ (mapcar '* >a >b))
)
;定义向量的数乘r&>
(defun r&>(f >b)
  (mapcar '(lambda(x)(* f x)) >b)
)
;定义向量的叉乘>*>
;叉乘得到的向量的意义:方向与>a和>b均垂直,
;且使(>a >b (>*> >a >b))成右手系--------
;几何意义:叉乘的模等于以两向量为邻边的平行四边形的面积-
(defun >*>(>a >b)
  ;(y1*z2-y2*z1 z1*x2-z2*x1 x1*y2-x2*y1)
  ;(y= cadr x= car z= caddr)
  (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)))
  )
)
;|定义两向量的夹角的余弦cosval
;cos(->A和->B夹角)=x1*x2+y1*y2+z1*z2/(* (sqrt (+ x1*x1 y1*y1 z1*z1))(sqrt (+ x2*x2 y2*y2 z2*z2)))
                  =(->A和->B的数性乘)/(->A的模*->B的模)
;->A垂直于->B则x1*x2+y1*y2+z1*z2=0
;计算两向量的夹角的cos数值cosval|;
(defun cosval(->a ->b)
  (/ (>&> ->a ->b)(* (|| ->a )(|| ->b)))
  ;|(/ (apply '+ (mapcar '* ->a ->b)) (* (sqrt (+ (expt (car ->a) 2) (expt (cadr ->a) 2) (expt (caddr ->a) 2)))
                       (sqrt (+ (expt (car ->b) 2) (expt (cadr ->b) 2) (expt (caddr ->b) 2)))))|;
)
;向量A在轴l上面的射影---------------
;prl->A=|A|*cos(两向量夹角)---------
(defun prl(->a l / cosvall)
  (* (cosval ->a l) (|| ->a))
)
;求与向量a平行的向量的单位向量------
;结果应该有两个的-------------------
(defun ->1ofa(a / |a|)
  (cond
    ((->zerop a);零向量-------------
     nil
    )
    ((->1 a) a)
    (t
     (setq |a|(|| a))
     (mapcar '(lambda(x)(/ x |a| )) a)
    )
  )
)

;向量的基本定理在程序中的实现-----------

;定理1  共线向量定理的推导--两向量的叉乘等于0则两向量平行或者共线--
;实例应用1:判断三点是否共线-------------
;(3pin1line '(0 0 0) '(1 2 3) '(2 4 6))
(defun 3pin1line(p1 p2 p3 / p1->p2 p1->p3)
  ;先获得两个向量,然后叉乘--------------
  (setq p1->p2(-> p1 p2))
  (setq p1->p3(-> p1 p3))
  ;然后判断是否为零向量-----------------
  (->zerop (>*> p1->p2 p1->p3))
)
;更进一步------------------------------
;点p3和线段p1p2的关系--
;当点在起点延长线返回-1,在起点上面返回0,在线段中间返回1,在--
;线段终点返回2,在终点延长线上返回3.....
;不共线返回nil
;(pntandline '(0 0 0) '(1 2 3) '(2 4 6));返回3
;(pntandline  '(1 2 3) '(0 0 0) '(2 4 6));返回-1
;(pntandline  '(1 2 3)  '(2 4 6) '(1.5 3 4.5));返回1
;(pntandline  '(1 2 3)  '(2 4 6) '(1.5 4 4.5));返回nil
;(pntandline  '(1 2 3) '(0 0 0) '(1 2 3));返回0
;(pntandline  '(1 2 3) '(0 0 0) '(0 0 0));返回2
(defun pntandline(p1 p2 p3 / p1->p2 p1->p3 zerop? scale shuxingji)
  (setq p1->p2(-> p1 p2))
  (setq p1->p3(-> p1 p3))
  (setq zerop?(->zerop (>*> p1->p2 p1->p3)))
  (cond
    (zerop?;三点共线-------------------
     (cond
       ((->zerop p1->p2) 0);向量p1->p2为零向量,设p3在起点,返回0
       ((->zerop p1->p3) 0);向量p1->p3为零向量,给定的点和起点重合,返回0--
       (t
    (mapcar '(lambda(x y)(if (and (not (zerop x))(not (zerop y)))
                     (setq scale (/ (float y) (float x))))) p1->p2 p1->p3)
    (cond
      ((minusp scale) -1);在起点延长线上-------------------------
      ((equal scale 1) 2);在终点上-------------------------------
      ((< scale 1) 1)    ;在起点上-------------------------------
      (t 3)              ;在线段内部-----------------------------
    )
       )
     )
    )
    (t;三点不共线返回nil
     nil)
  )
)
;线段的定比分点坐标---------------------
;定理2:对有向线段A->B,若存在点C满足A->C=numb*C->B,则称点C分线段A->B成定比numb
;设A(x1 y1 z1),B(x2 y2 z2)则分有向线段A->B成定比numb的分点C的坐标是--
;x=(x1+numb*x2)/(1+numb) y=(y1+numb*y2)/(1+numb) z=(z1+numb*z2)/(1+numb)
(defun clippt(p1 p2 scale / tmp)
  (setq tmp(+ scale 1.0))
  (list
    (/ (+ (car p1) (* (car p2) scale)) tmp)
    (/ (+ (cadr p1) (* (cadr p2) scale)) tmp)
    (/ (+ (caddr p1) (* (caddr p2) scale)) tmp)
  )
)
;实例应用2,获得两点或线段的n等分点------
;(dividepnt '(1 0 0) '(11 12 13) 5)
;返回:((3.0 2.4 2.6) (5.0 4.8 5.2) (7.0 7.2 7.8) (9.0 9.6 10.4))
(defun dividepnt(p1 p2 n / pts p1->p2/n)
  (setq n(float n))
  (setq p1->p2(-> p1 p2));获得向量------
  ;(setq p1->p2(mapcar '- p2 p1))
  (setq p1->p2/n(mapcar '(lambda(x)(/ x n)) p1->p2))
  ;获得等分向量,然后和起点向量相加------
  (setq n(fix n))
  (repeat (setq n(1- n))
    (setq p1  (>+> p1 p1->p2/n)
      pts (cons p1 pts)
    )
  )
  (reverse pts)
)
;|定理3 两向量的数性积(乘)等于0则两向量垂直------
       大于0和小于0应该也是有实际意义的,学习中---
;实例应用3,判断两条直线是否垂直-----
;(isvertical '(0 0 0) '(1 0 0) '(0 5 0) '(0 8 0));返回t|;
(defun isvertical(p1 p2 p3 p4 / ->a ->b)
  (setq ->a(-> p1 p2)
    ->b(-> p3 p4)
    )
  (= 0 (>&> ->a ->b))
  ;(= 0 (apply '+ (mapcar '* ->a ->b)))
)
;更进一步,判断点p3是否在线段的垂直中线上---------
;(invercline '(0 0 0) '(1 0 0) '(0.5 1 2));返回t
;(invercline '(0 0 0) '(1 0 0) '(0.5 5 6));返回t
;(invercline '(0 0 0) '(1 0 0) '(0.6 1 2));返回nil
(defun invercline(p1 p2 p3 / midpt p1->p2 midpt->p3)
  ;|(setq midpt(mapcar '(lambda(x y)(/ (+ x y)2.0)) p1 p2);中点--
        p1->p2(-> p1 p2 )                               ;线段的矢量-
    midpt->p3(-> p3 midpt)                          ;中点和p3的矢量-
    )
  (= 0 (>&> p1->p2 midpt->p3))|;
  (setq midpt(mapcar '(lambda(x y)(/ (+ x y)2.0)) p1 p2))
  (isvertical p1 p2 p3 midpt)
)
;更进一步,求P3在线p1p2上的垂足-------------------
;知识点:射影,两向量夹角--------------------------
;(foot '(0 0 0) '(1 0 0) '(2.0 4.0 0));返回:(2.0 0.0 0.0)
;(foot '(0 0 0) '(1 1 0) '(2.0 4.0 0));返回:(3.0 3.0 0.0)
(defun foot(p1 p2 p3 / p1->p2 p1->p3 prll |p1->p2| tmp->)
  (setq p1->p2(-> p1 p2);线段的向量--------------
    p1->p3(-> p1 p3);线段起点到p3的向量------
    prll(prl p1->p3 p1->p2);计算p1->p3在p1->p2的射影--
    |p1->p2|(|| p1->p2);计算向量的模---------
    tmp->(/ prll (float |p1->p2|))
    )
  ;现在我们就可以计算向量p1P3'了------------------
  (r&> tmp-> p1->p2)
)
;共面向量定理:如果两个向量不共线,则向量p与向量a,b 共面的充要条件是存在实数对x,y,使p = xa + yb
;推论:点A,B,C是空间不共线的三点,又点P满足等式:->OP = x->OA + y->OB + z->OC,
;其中x, y , z为R, 则如果x + y + z = 1, P,A,B,C四点共面.
;实例应用3,判断四点是否共面-----也就是判断两线是否共面-----------------
;(coplanar '(0 0 0) '(1 1 0) '(2.0 4.0 0) '(3.0 3.0 0.0));返回:T
;(coplanar '(0 0 1) '(1 1 0) '(2.0 4.0 0) '(3.0 3.0 0.1));返回:nil
(defun coplanar(p1 p2 p3 p4 / p1->p4 p1->p2 p1->p3 tmp->)
  (cond
    ((3pin1line p1 p2 p3);三点共线,则四点肯定共面-
     t)
    (t;三点不共线,先获得向量----------------------
     (setq p1->p4(-> p1 p4)
       p1->p2(-> p1 p2)
       p1->p3(-> p1 p3)
       tmp->(>*> p1->p2 p1->p3);获得p1->p2 p1->p3两个矢量的法向量---
       )
     ;如果四点共面,则p1->p4和tmp->的角度肯定为90度,也就是两个向量垂直---
     (if (= 0 (>&> tmp-> p1->p4))
       t
       nil
     )
    )
  )
)
;|上面x + y + z = 1还有计算好像很不好玩了,,,,,,,,,,,,,,,,
;还有就是叉乘的方式是不是真的太奇怪了????----------------
;回过头再来看叉乘的公式:
(y1*z2-y2*z1 z1*x2-z2*x1 x1*y2-x2*y1)
如果我们改成好看一点的方式:
(x1 y1 z1)
(x2 y2 z2)
那么叉乘的结果是???难道???难道这就是,,,传说中的矩阵??????
|;
;|上面x + y + z = 1还有计算好像很不好玩了,,,,,,,,,,,,,,,,
;还有就是叉乘的方式是不是真的太奇怪了????----------------
;回过头再来看叉乘的公式:
(y1*z2-y2*z1 z1*x2-z2*x1 x1*y2-x2*y1)
如果我们改成好看一点的方式:
(x1 y1 z1)
(x2 y2 z2)
那么叉乘的结果是???难道???难道这就是,,,传说中的矩阵??????
|;

;|下面开始矩阵的学习中-----------------------------------
((1.0 0.0 0.0 2.30857)
 (0.0 1.0 0.0 0.83973)
 (0.0 0.0 1.0 0.0)
 (0.0 0.0 0.0 1.0))
 上面为某块的矩阵,,,,,matrix
 其实就是一个标架,,如果把它还原一下应该是:
 ((2.30857 0.83973 0.0);->O
  (1.0 0.0 0.0)        ;->e1
  (0.0 1.0 0.0)        ;->e2
  (0.0 0.0 1.0)        ;->e3
 )
看出来了,,原来,,,天啊,,矩阵其实还是就是标架------------------
坐标其实就是向量在该标架下的不同的基底向量的射影,组合成坐标--
那么矩阵和向量数性乘代表什么呢?
我们知道向量op可以被标架表示为x*->e1+y*->e2+z*->e3
 向量乘该矩阵其实就是求出向量到该标架的坐标?????????????
也就是说cad里面的世界坐标标架其实是:
((1.0 0.0 0.0 0)
 (0.0 1.0 0.0 0)
 (0.0 0.0 1.0 0)
 (0.0 0.0 0.0 1.0))
 任何向量只要和该矩阵进行数性乘就可以得到世界坐标系的坐标了--
|;
(defun >tomatrix(p)
  (list (car p)(cadr p)(caddr p) 1.0)
)
;定义向量和矩阵的乘法-----------------------------------
;转换指定矩阵上的点为世界坐标系坐标---------------------
(defun >*matrix(matrix p)
  ;根据上面的理解,我们可以计算了------------------------
  ;(setq p(list (car p)(cadr p)(caddr p) 1.0))
  (setq p(>tomatrix p))
  (list (>&> (car matrix) p)
    (>&> (cadr matrix) p)
    (>&> (caddr matrix) p)
    )
)
;转换世界坐标系坐标为指定的矩阵指定的标架的坐标---------
;其实就是求向量P在指定矩阵的标架上的射影----------------
(defun >prlmatrix(matrix p / e1 e2 e3)
  ;根据上面的理解,我们可以计算了------------------------
  ;(setq p(list (car p)(cadr p)(caddr p) 1.0))
  (setq e1(car matrix)
    e2(cadr matrix)
    e3(caddr matrix))
  (setq p(-> (list (last e1) (last e2) (last e3))
         p))
  (list (prl p (list (car e1)(cadr e1)(caddr e1)))
    (prl p (list (car e2)(cadr e2)(caddr e2)))
    (prl p (list (car e3)(cadr e3)(caddr e3)))
    )
)
;所以从上面看出,只要一个矩阵,我们就可以
;从子坐标系转换到世界坐标,(>*matrix 矩阵 点)
;或者从世界坐标转换到子坐标系统---(>prlmatrix 矩阵 点)
;下面就是该怎么构建矩阵的问题了~~~~
;哈,看了一天书,先写到这里,什么时候能接上继续学习再说~~~~~

434939575 发表于 2021-9-27 08:56:24

,这么详细,感谢分享 ,对矩阵不理解。慢慢学习下。

白色微風1991 发表于 2021-9-27 12:41:50

哎,好文字就是看不懂,樓主我頂你!

jdhszh 发表于 2008-2-22 20:01:00

佩服

vken7az2p 发表于 2008-2-22 21:56:00

利害阿

xxsheng 发表于 2008-2-23 09:26:00

<br/>foot函数有点错误:<br/>(defun foot(p1 p2 p3 / p1-&gt;p2 p1-&gt;p3 prll |p1-&gt;p2| tmp-&gt;)<br/>  (setq p1-&gt;p2(-&gt; p1 p2);线段的向量--------------<br/>    p1-&gt;p3(-&gt; p1 p3);线段起点到p3的向量------<br/>    prll(prl p1-&gt;p3 p1-&gt;p2);计算p1-&gt;p3在p1-&gt;p2的射影--<br/>    |p1-&gt;p2|(|| p1-&gt;p2);计算向量的模---------<br/>    tmp-&gt;(/ prll (float |p1-&gt;p2|))<br/>    )<br/>  ;现在我们就可以计算向量p1P3'了------------------<br/>  (&gt;+&gt; p1 (r&amp;&gt; tmp-&gt; p1-&gt;p2));应该添加一个起点向量~我测试的时候,起点都是(0 0 0),所以没有注意.<br/>)<br/>;函数cosval应该再增加零向量的判断,根据向量定义,零向量和任何向量共线,返回(cos 0)的数值为1<br/>(defun cosval(-&gt;a -&gt;b)<br/>  (cond<br/>    ((or (-&gt;zerop -&gt;a)(-&gt;zerop -&gt;b));存在零向量则返回1<br/>     1;为了<br/>    )<br/>    (t (/ (&gt;&amp;&gt; -&gt;a -&gt;b) (* (|| -&gt;a )(|| -&gt;b))))<br/>  )<br/>)<br/>;函数prl添加零向量判断,<br/>;因为零向量在任何轴上的射影都是0--------<br/>(defun prl(-&gt;a l / cosvall)<br/>  (cond<br/>    ((-&gt;zerop -&gt;a) 0)<br/>    (t (* (cosval -&gt;a l) (|| -&gt;a)))<br/>  )<br/>)<br/>

xxsheng 发表于 2008-2-23 14:56:00

<div>;上面的dividepnt,应该也可以这么写的--<br/>;(dividept '(1 0 0) '(11 12 13) 5);返回:((3.0 2.4 2.6) (5.0 4.8 5.2) (7.0 7.2 7.8) (9.0 9.6 10.4))<br/>(defun dividept(p1 p2 n / pts m tmpp)<br/>  (setq p1-&gt;p2(-&gt; p1 p2));获得向量------<br/>  (setq m(/ 1 (float n)))<br/>  (while (&gt; (setq n(1- n)) 0)<br/>    (setq tmpp  (r&amp;&gt; (* n m) p1-&gt;p2)<br/>      tmpp  (&gt;+&gt; p1 tmpp)       <br/>      pts (cons tmpp pts)<br/>    )<br/>  )<br/>)<br/>;|三点共线即两个向量平行,则可以推导出另外一个判断三点共线--<br/>;z1/z2=x1/x2=y1/y2=scale,推理出x1*y2-y1*x2=0=x1*z2-x2*z1<br/>;(3pinline '(0 0 0) '(1 2 3) '(2 4 6)) ;返回t|;<br/>(defun 3pinline(p1 p2 p3 / p1-&gt;p2 p1-&gt;p3)<br/>  (setq p1-&gt;p2(-&gt; p1 p2)<br/>    p1-&gt;p3(-&gt; p1 p3))<br/>  (= 0 (- (* (car p1-&gt;p2)(cadr p1-&gt;p3))(* (cadr p1-&gt;p2)(car p1-&gt;p3)))<br/>       (- (* (car p1-&gt;p2)(caddr p1-&gt;p3))(* (caddr p1-&gt;p2)(car p1-&gt;p3))))<br/>)<br/>;从矢量的叉乘意义知道,两个矢量叉乘的矢量的模就是以两个矢量为邻边的平行四边形的面积--<br/>;实际应用:计算三角形的面积.-<br/>;(areas '(0 0 0) '(1 2 0) '(1 3 0));返回:0.5<br/>;(areas '(0 0 0) '(0 0 0) '(0 0 0));返回:0.0<br/>(defun areas(p1 p2 p3 / p1-&gt;p2 p1-&gt;p3)<br/>  (setq p1-&gt;p2(-&gt; p1 p2)<br/>    p1-&gt;p3(-&gt; p1 p3))<br/>  (/ (|| (&gt;*&gt; p1-&gt;p2 p1-&gt;p3)) 2.0);两个向量叉乘再求模再除以2------------------------<br/>)<br/>;函数更改为<br/>(defun &gt;tomatrix(p)<br/>  (append p '(1.0))<br/>)<br/>;矩阵转换中的--我当时还是在cad系统里面测试,没有认真考虑到变换坐标系,更改后就可以了~<br/>(defun &gt;prlmatrix(matrix p / e1 e2 e3)<br/>  ;根据上面的理解,我们可以计算了------------------------<br/>  ;(setq p(list (car p)(cadr p)(caddr p) 1.0))<br/>  (setq e1(car matrix)<br/>    e2(cadr matrix)<br/>    e3(caddr matrix))<br/>  (setq p(-&gt; (list (last e1) (last e2) (last e3))<br/>         p))<br/>  (list (/ (prl p (list (car e1)(cadr e1)(caddr e1)))(|| (list (car e1)(cadr e1)(caddr e1))))<br/>        (/ (prl p (list (car e2)(cadr e2)(caddr e2)))(|| (list (car e2)(cadr e2)(caddr e2))))<br/>    (/ (prl p (list (car e3)(cadr e3)(caddr e3)))(|| (list (car e3)(cadr e3)(caddr e3))))<br/>    )<br/>)<br/>;|<br/>什么是矩阵?---<br/>不管它了,还是先看坐标系的转换-----------------------------<br/>首先,向量的坐标表示是向量在标架的定义{o e1 e2 e3}的一个表达-----<br/>也就是说,其实,,,,任何对象都是向量?和书上的概念不同?管他呢!<br/>让我们来看一看向量的基础----------------------------------<br/>同一个标架上(O i j k):<br/>假设向量A表达为(1 2 3),向量B表达为(4 5 6),向量C(3 3 3),,,,<br/>则根据向量基本计算法则有:向量AB表达为(3 3 3),那么向量c和AB是什么关系呢???<br/>向量C和向量AB在该标架下的坐标表示是一样的,也就是相等.<br/>而实质是:向量A=矩阵{1 2 3}乘标架矩阵{O i j k}<br/>         向量B=矩阵{4 5 6}乘标架矩阵{O i j k}<br/>         向量C=矩阵{3 3 3}乘标架矩阵{O i j k}<br/>         向量AB=矩阵{3 3 3}乘标架矩阵{向量A i j k}<br/>从这里应该可以看见,把向量C变换为向量B其实就是向量C乘{向量A i j k}<br/>那么转换坐标系其实很简单了;;;<br/>假设我们定义一个坐标系:坐标原点(1 2 3),i(10 0 0),j(0 10 0),k(0 0 10)<br/>设向量C在世界标架为(3 3 3),转换到新定义的坐标系的实质就是该向量乘新--<br/>的坐标系矩阵-----------------<br/>((1 2 3)(10 0 0)(0 10 0)(0 0 10))<br/>((10 0 0 1)(0 10 0 2)(0 0 10 3)(0 0 0 1))<br/>(&gt;*matrix '((10 0 0 1)(0 10 0 2)(0 0 10 3)(0 0 0 1)) '(1 2 3))<br/>;返回:(11.0 22.0 33.0)<br/>;转换到世界坐标------------------------------------------<br/>;世界坐标如何转化为该坐标呢?-----------------------------<br/>(&gt;prlmatrix '((10 0 0 1)(0 10 0 2)(0 0 10 3)(0 0 0 1)) '(11.0 22.0 33.0))<br/>;返回:(1.0 2.0 3.0)<br/>可是仔细看,,其实我们的&gt;*matrix函数就是一个矩阵相乘------------<br/>我们的向量(0.2 0.1 0.0)看成是{0.2 0.1 0.0}矩阵<br/>坐标系看成是{(10 0 0 1)(0 10 0 2)(0 0 10 3)(0 0 0 1)}矩阵<br/>那么坐标系转换的过程其实说到底还是矩阵的相乘在操作着----------<br/>注意看,在转换前后我们的向量的坐标发生了变化,,,,,,,,,,,,,,,,,,,<br/>抛弃我们在进行坐标系转换的看法,,,<br/>从另外一个角度看,向量和坐标系的矩阵的相乘,竟然会使向量从(0.2 0.1 0.0)变到了(3.0 3.0 3.0)<br/>也就是说在经过一个矩阵乘法以后,向量(这费解的东西)竟然变换了---<br/>难道矩阵的功能就是使向量进行变换或者说生长????----------------<br/>也就是说矩阵可以操作坐标系转换也可以变换向量??????????????????<br/>|;<br/><br/>;定义矩阵的相乘-----------------------------------<br/>;矩阵C(i, j) =(矩阵A的第i行)点乘(B的第j列)<br/>;显然就是矩阵A的行矢量叉乘矩阵的列矢量------------<br/>;我们把矩阵B转化为列序,然后进行点乘---------------<br/>(defun mat*mat(mat1 mat2 / p)<br/>  (setq p(apply 'mapcar (cons 'list mat2)))<br/>  (mapcar '(lambda(x)(mapcar '(lambda(y)(&gt;&amp;&gt; x y)) p))mat1)<br/>)<br/>;构建平移,缩放,旋转矩阵这些相对简单,甚至可以抄就好了~~呵呵,何必学习~~~~~<br/>;至于矩阵的概念???,,,,,,,,<br/><br/></div>

cnks 发表于 2008-2-23 16:12:00

学习。。。

CLONESOME 发表于 2008-3-31 00:57:00

<p>学习一下哟</p>

xxsheng 发表于 2008-4-1 10:55:00

本帖最后由 作者 于 2008-4-9 16:22:51 编辑

;|功能:定义向量的张量积--
(>@> '(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)
)
;|功能:定义矢量的混合积--------------
(>&>*> '(1 2 5) '(2 0 -2) '(2 3 4));返回12
;几何意义:求以三个向量为边的平行六面体的体积-
          三个向量共面则混合积为0----
|;
(defun >&>*>(>a >b >c)
  (- (+ (* (car >a)(cadr >b)(caddr >c))
    (* (caddr >a)(car >b)(cadr >c))
    (* (cadr >a)(caddr >b)(car >c)))
     (+ (* (car >a) (caddr >b)(cadr >c))
    (* (cadr >a)(car >b)  (caddr >c))
    (* (caddr >a)(cadr >b)(car >c))))
)
;|定义向量和矩阵的乘法-----------------------------------
转换指定矩阵上的点为世界坐标系坐标-----------------------
点的变换需要加最后一个维数       1
向量的变换则需要加最后一个维数为 0
其实和矩阵相乘是一个道理了~~~~~~~~
(>*matrix '((10 0 1)(0 10 2)(0 0 1)) '(0.9 1.8))
(mat*mat '((10 0 1)(0 10 2)(0 0 1)) '((0.9) (1.8) (1)))
(>*matrix '((10 0 0 1)(0 10 0 2)(0 0 10 3)(0 0 0 1)) '(1 2 3))
(mat*mat '((10 0 0 1)(0 10 0 2)(0 0 10 3)(0 0 0 1)) '((1) (2) (3)(1)))
|;
(defun >*matrix(matrix verp)
  (setq verp(append verp '(0)))
  (reverse(cdr(reverse(mapcar '(lambda(x)(>&> x verp)) matrix))))
)
;点和矩阵的乘法----------------------------------------
(defun p*matrix(matrix p)
  (setq p(append p '(0)))
  (reverse(cdr(reverse(mapcar '(lambda(x)(>&> x p)) matrix))))
)
;|定义向量的等价反对称矩阵-----------------------------
(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)
    )
)
;|功能:定义矩阵的转置矩阵--------------------------
(transposed '((1 2 3 100)(4 5 6 200)(7 8 9 300)(10 11 12 400)))
|;
(defun transposed(mat)
  (apply 'mapcar (cons 'list mat))
)
;;定义矩阵的相乘-----------------------------------
;;矩阵C(i, j) =(矩阵A的第i行)点乘(B的第j列)
;;显然就是矩阵A的行矢量叉乘矩阵的列矢量------------
;;我们把矩阵B转化为列序,然后进行点乘---------------
;(mat*mat '((2 3)(9 1)) '((1 7 5)(4 6 8)))
(defun mat*mat(mat1 mat2 / p)
  (if (and
    (listp (car mat1))
    (listp mat2)
    (= (length (car mat1)) (length mat2));只有M=N才能定义矩阵的乘法------------
      )
    (progn
      (setq p(transposed mat2))
      (mapcar '(lambda(x)(mapcar '(lambda(y)(apply '+ (mapcar '* x y))) p))mat1)
    )
  )
)
;;定义矩阵的相加----------------------------------
(defun mat+mat(lst1 lst2)
  (mapcar '(lambda(x y)(mapcar '(lambda(m n)(+ m n)) x y)) lst1 lst2)
)
;|利用>prlmatrix求逆矩阵--------------------------
(inversemat '((10 0 0 1)(0 10 0 2)(0 0 10 3)(0 0 0 1)))
(isunit (mat*mat (setq tmp '((10 0 0 1)(0 10 0 2)(0 0 10 3)(0 0 0 1)))(inversemat tmp)))
只能适用于正交矩阵????????????????????????????????
|;
(defun inversemat(mat / tmatrix po o i j k |||)
  ;;其实从>prlmatrix就可以推导出下面的结果---------
  (setq mat(reverse(cdr(reverse mat))))
  (setq tmatrix(mapcar '(lambda(x)(reverse(cdr(reverse x)))) mat))
  (setq po(mapcar '- (mapcar 'last mat)))
  (setq |||(mapcar '(lambda(x)(apply '+ (mapcar '(lambda(y)(* y y)) x))) tmatrix))
  (setq o(mapcar '(lambda(x y)(/ (float(>&> po x)) y)) tmatrix |||))
  ;;(setq tmatrix(apply 'mapcar (cons 'list tmatrix)))
  ;;其实如果反转一下也可以支持二维矩阵的,,,算了,何必麻烦----------
  (setq i(mapcar '(lambda(x y)(/ (float(car x)) y)) tmatrix |||))
  (setq j(mapcar '(lambda(x y)(/ (float(cadr x)) y)) tmatrix |||))
  (setq k(mapcar '(lambda(x y)(/ (float(caddr x)) y)) tmatrix |||))
  (list (list (car i)(cadr i)(caddr i) (car o))
    (list (car j)(cadr j)(caddr j) (cadr o))
    (list (car k)(cadr k)(caddr k) (caddr o))
    '(0 0 0 1))
)
;|平移矩阵--
(movemat (getpoint)(getpoint))
(movemat nil (getpoint))
(movemat (getpoint) nil)
|;
(defun movemat(sp ep / tmpp)
  (if (and sp ep)
    (setq tmpp(mapcar '- ep sp))
    (if sp
      (setq tmpp sp)
      (setq tmpp ep)
    )
  )
  (list (list 1 0 0 (car tmpp))
    (list 0 1 0 (cadr tmpp))
    (list 0 0 1 (caddr tmpp))
    '( 0 0 0 1))
)
;|等比例缩放矩阵--
(scalemat (getpoint "\n缩放基点:")(getreal "\n缩放比例:"))
(scalemat nil (getreal "\n缩放比例:"))
|;
(defun scalemat(p s)
  (if (->zerop sp)
    (list
    (list s 0 0 0)
    (list 0 s 0 0)
    (list 0 0 s 0)
    '(0 0 0 1)
    )
    (progn
      (setq p(r&> (- 1.0 s) p))
      (list
    (list s 0 0 (car p))
    (list 0 s 0 (cadr p))
    (list 0 0 s (caddr p))
    '(0 0 0 1)
    )
    )   
  ) 
)
;|旋转矩阵----3d旋转
罗德里格斯旋转公式:
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))
    )   
  )
)
;|镜像矩阵-3d镜像
(mirrormat sp norver);参数一为镜像基点,参数二为镜像面的法向量-
(mirrormat (setq tmp(getpoint "\n选择镜像的起点:")) (>*> '(0 0 1) (>-> (getpoint "\n选择镜像的端点:") tmp)))
|;
(defun mirrormat(sp norver / i 1of t1)
  (setq i '((1 0 0)(0 1 0)(0 0 1))
    1of(->1ofa norver)
    t1(r*mat -2 (>@> 1of nil))
    t1(mat+mat i t1)
    )
  (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 (car(car t1))(cadr(car t1))(caddr(car t1)) (car sp))
    (list (car(cadr t1))(cadr(cadr t1))(caddr(cadr t1)) (cadr sp))
    (list (car(caddr t1))(cadr(caddr t1))(caddr(caddr t1)) (caddr sp))
    '(0 0 0 1))
    )   
  ) 
)
;|正交投影矩阵-
(orthprojmat '(0 0 0) '(0 0 1));俯视图变换矩阵----
(orthprojmat '(0 0 0) '(1 0 0));侧视图变换矩阵----
(orthprojmat '(0 0 0) '(0 1 0));主视图变换矩阵----
|;
(defun orthprojmat(p norver / i 1of t1)
  (setq i '((1 0 0)(0 1 0)(0 0 1))
    1of(->1ofa norver)
    t1(r*mat -1 (>@> 1of nil))
    t1(mat+mat i t1)
    )
  (if (->zerop p)
    (list (list (car(car t1))(cadr(car t1))(caddr(car t1)) 0)
      (list (car(cadr t1)) (cadr(cadr t1))(caddr(cadr t1)))
      (list (car(caddr t1))(cadr(caddr t1))(caddr(caddr t1)))
      '(0 0 0 1))
    (progn
      (setq p(>-> p (mapcar '(lambda(x)(>&> x p)) t1)))
      (list
    (list (car(car t1))(cadr(car t1))(caddr(car t1)) (car p))
    (list (car(cadr t1))(cadr(cadr t1))(caddr(cadr t1)) (cadr p))
    (list (car(caddr t1))(cadr(caddr t1))(caddr(caddr t1)) (caddr p))
    '(0 0 0 1))
    )   
  )
)
;|功能:用户坐标系矩阵的获得----
(ucsmat)
|;
(defun ucsmat( / x y z o)
  (setq x(getvar 'ucsxdir)
    y(getvar 'ucsydir)
    z(>*> x y)
    o(getvar 'ucsorg))
  (list (list (car x)(cadr x)(caddr x)(car o))
    (list (car y)(cadr y)(caddr y)(cadr o))
    (list (car z)(cadr z)(caddr z)(caddr o))
    '(0 0 0 1))
)
;|功能:获得MTEXT的外框------返回的是当前坐标系的角点---------------
(mtextboundbox (car(entsel)))
和系统的vla-GetBoundingBox不同的是这个返回的更加准确,而且更加快速--xxsheng 4-2
|;
(defun mtextboundbox(mtextent / height width insp xdir zdir ydir align)
  (setq mtextent(entget mtextent)
        height(cdr(assoc 43 mtextent))
    width (cdr(assoc 42 mtextent))
    insp(cdr(assoc 10 mtextent)) ;插入点,收到71组码的影响------
    xdir(cdr(assoc 11 mtextent)) ;文本的x轴方向--
    zdir(cdr(assoc 210 mtextent));文本的Z轴方向--
    ydir(list (- (* (cadr zdir)(caddr xdir)) (* (caddr zdir)(cadr xdir)));叉乘得到Y轴方向-------
          (- (* (caddr zdir)(car xdir)) (* (car zdir)(caddr xdir)))
          (- (* (car zdir)(cadr xdir)) (* (cadr zdir)(car xdir))))
    align(cdr(assoc 71 mtextent))
    insp(trans insp 0 1);转变插入点为当前坐标系--
    )
  (cond
    ((eq align 1);左上---
     (setq height(- height))
     (list (mapcar '+ insp (mapcar '(lambda(x)(* x height)) ydir))
       (mapcar '+ insp (mapcar '(lambda(x)(* x width)) xdir))
     )
    )
    ((eq align 2);中上---
     (setq height(- height))
     (list (mapcar '+ insp
              (mapcar '(lambda(x)(* x 0.5 height)) ydir)
              (mapcar '(lambda(x)(* x -0.5 width)) xdir))
       (mapcar '+ insp
              (mapcar '(lambda(x)(* x 0.5 height)) ydir)
              (mapcar '(lambda(x)(* x 0.5 width)) xdir))
     )
    )
    ((eq align 3);右上---
     (setq height(- height)
       width(- width)
       )
     (list insp
       (mapcar '+ insp
              (mapcar '(lambda(x)(* x height)) ydir)
              (mapcar '(lambda(x)(* x width)) xdir))
     )
    )
    ((eq align 4);左中--
     (list (mapcar '+ insp (mapcar '(lambda(x)(* x -0.5 height)) ydir))
       (mapcar '+ insp
              (mapcar '(lambda(x)(* x 0.5 height)) ydir)
              (mapcar '(lambda(x)(* x width)) xdir))
     )
    )
    ((eq align 5);正中--
     (list (mapcar '+ insp
              (mapcar '(lambda(x)(* x -0.5 height)) ydir)
              (mapcar '(lambda(x)(* x -0.5 width)) xdir))
       (mapcar '+ insp
              (mapcar '(lambda(x)(* x 0.5 height)) ydir)
              (mapcar '(lambda(x)(* x 0.5 width)) xdir))
     )
    )
    ((eq align 6);右中--
     (setq width(- width))
     (list (mapcar '+ insp
              (mapcar '(lambda(x)(* x -0.5 height)) ydir)
              (mapcar '(lambda(x)(* x width)) xdir))
       (mapcar '+ insp
              (mapcar '(lambda(x)(* x 0.5 height)) ydir))
     )
    )
    ((eq align 7);左下---
     (list insp
       (mapcar '+ insp
              (mapcar '(lambda(x)(* x height)) ydir)
              (mapcar '(lambda(x)(* x width)) xdir))
     )
    )
    ((eq align 8);中下---
     (list (mapcar '+ insp (mapcar '(lambda(x)(* x -0.5 width)) xdir))
       (mapcar '+ insp
              (mapcar '(lambda(x)(* x height)) ydir)
              (mapcar '(lambda(x)(* x 0.5 width)) xdir))
     )
    )
    (t;右下---
     (setq width(- width))
     (list (mapcar '+ insp (mapcar '(lambda(x)(* x width)) xdir))
       (mapcar '+ insp (mapcar '(lambda(x)(* x height)) ydir))
     )
    )
  )
)
;|功能:获得块的矩阵----支持三维-----------------
(blkmat (vlax-ename->vla-object(car(entsel))))
------------------------------2008-04-02-xxsheng
|;
(defun blkmat (vobj / mxm origin ang inspt zdir xdir ydir rmat movmatrix resmatrix)
  (defun mxm (m q / qt)
    (setq qt (apply 'mapcar (cons 'list q)))
    (mapcar '(lambda (x) (mapcar '(lambda (y) (apply '+ (mapcar '* y x))) qt)) m)
  )
  (and
    (setq origin(vlax-get (vlax-invoke (vlax-get (vlax-get (vlax-get-acad-object) "Activedocument") "blocks")
                "item"  (vlax-get vobj "name")) "origin"))
    (setq ang (vlax-get vobj "Rotation"))
    (setq inspt (mapcar '- (vlax-get vobj "InsertionPoint") origin));需要增加块定义原点的判断~~~~
    (setq zdir (vlax-get vobj "Normal"))
    (setq xdir(trans (list (cos ang)(sin ang) 0) zdir 0))
    (setq ydir(list (- (* (cadr zdir)(caddr xdir)) (* (caddr zdir)(cadr xdir)));叉乘得到Y轴方向-------
            (- (* (caddr zdir)(car xdir)) (* (car zdir)(caddr xdir)))
            (- (* (car zdir)(cadr xdir)) (* (cadr zdir)(car xdir)))))
    (setq rmat(list (list (car xdir)(car ydir) (car zdir) 0)
            (list (cadr xdir)(cadr ydir)(cadr zdir) 0)
            (list (caddr xdir)(caddr ydir)(caddr zdir) 0)))
    (setq rmat(mapcar '(lambda(x y)(mapcar '(lambda(m)(* m y)) x))
                 rmat
                 (list (vlax-get vobj "XScaleFactor")
                       (vlax-get vobj "YScaleFactor")
                       (vlax-get vobj "ZScaleFactor")
                       )))
    (setq rmat(list (car rmat) (cadr rmat) (caddr rmat) '(0 0 0 1)))
    (setq movmatrix(list (list 1 0 0 (car inspt))(list 0 1 0 (cadr inspt))(list 0 0 1 (caddr inspt))
                     '(0 0 0 1)))
    (setq rmat(mxm movmatrix rmat))
  )
  rmat
)
;|获得块的逆矩阵-------支持三维-----------------
(iblkmat (vlax-ename->vla-object(car(entsel))))
                   ~~~~~~~~~~~2008-04-02-xxsheng
|;
(defun iblkmat(vobj / mxm origin ang inspt zdir xdir ydir rmat xsf ysf zsf sclmatrix movmatrix resmatrix)
  (defun mxm (m q / qt)
    (setq qt (apply 'mapcar (cons 'list q)))
    (mapcar '(lambda (x) (mapcar '(lambda (y) (apply '+ (mapcar '* y x))) qt)) m)
  )
  (and
    (setq origin(vlax-get (vlax-invoke (vlax-get (vlax-get (vlax-get-acad-object)
                               "Activedocument") "blocks") "item"
                (vlax-get vobj "name")) "origin"))
    (setq ang (-(vlax-get vobj "Rotation")))       ;旋转角反转----------------------------------------
    (setq inspt (mapcar '- origin (vlax-get vobj "InsertionPoint")));插入点反向-----------------------
    (setq zdir (mapcar '- (vlax-get vobj "Normal")));z轴坐标反向--------------------------------------
    (setq xdir(trans (list (- (cos ang)) (- (sin ang)) 0) zdir 0));不用trans也是可以的只是要换算来换算去的比较麻烦--
    (setq ydir(list (- (* (cadr xdir)(caddr zdir)) (* (caddr xdir)(cadr zdir)));叉乘得到Y轴方向-------
            (- (* (caddr xdir)(car zdir)) (* (car xdir)(caddr zdir)))  ;交换得到反向----------
            (- (* (car xdir)(cadr zdir)) (* (cadr xdir)(car zdir)))))
    (setq zdir (mapcar '- zdir));Z轴反向回来----------------------------------------------------------
    (setq rmat(list (list (car xdir)(cadr xdir)(caddr xdir)  0)
            (list (car ydir)(cadr ydir)(caddr ydir) 0)
            (list (car zdir)(cadr zdir)(caddr zdir) 0)
            '(0 0 0 1)
            ))
    (setq xsf (/ 1.0 (vlax-get vobj "XScaleFactor")))
    (setq ysf (/ 1.0 (vlax-get vobj "YScaleFactor")))
    (setq zsf (/ 1.0 (vlax-get vobj "ZScaleFactor")))
    (setq sclmatrix(list(list xsf 0 0 0)(list 0 ysf 0 0)(list 0 0 zsf 0) '(0 0 0 1)))
    (setq movmatrix(list(list 1 0 0 (car inspt))(list 0 1 0 (cadr inspt))(list 0 0 1 (caddr inspt))
                    '(0 0 0 1)))
    (setq rmat(mxm sclmatrix (mxm rmat movmatrix)))
  )
  rmat
)

yjc 发表于 2008-4-23 14:33:00

n你真是厉害,是大家学的榜样。镇扎实

啵浪鼓 发表于 2011-3-30 00:23:42

哎,好文字就是看不懂,楼主我顶你!
页: [1] 2 3
查看完整版本: 我的向量和矩阵学习心得