【从头写CAD】 转换矩阵类系列八,代码汇总

为了找出优化代码的方案,梳理矩阵类现有代码。现汇总转换矩阵所有代码在同一个文件中,同时调整了与矩阵类重载的代码的先后次序。完整代码如下:

/*矩阵类编程思路总说明:
   平面CAD对象主要包括点(point)、线(line 含线段、直线、射线,宽线、多段线)、平面形状(shap 含矩形、圆形、椭圆、文字、图块实体、外部参照实体及各种标注等)。我们先用点(point)来说明矩阵功能。
    点(P),可以用向量(1,x, y)表示。
     一、如果点发生平移时,转换矩阵(Move)为
       1       Dx    Dy
       0       1      0
       0       0      1
     即P.move(Dx,Dy)=(x+Dx,y+Dy)=P*Move;
     平移(Move)矩阵是本矩阵类(Matrix)的泛型特例,单独说明

     二、如果点发生旋转时(旋转角度为a),转换矩阵Rotate为
       1     0         0
       0     cos(a)    sin(a)
       0     -sin(a)   cos(a)
     即P.rotation(a)=(x * cos(a) - y * sin(a),x * sin(a) + y *cos(a))=P*M;
     旋转(Rotate)矩阵是本矩阵类(Matrix)的泛型特例,单独说明,为提高效率,角度类(Angle)参与矩阵乘法计算。

     三、如果点发生缩放时,比例为(Sx,Sy),转换矩阵(Scale)为
       1      0      0
       0      Sx     0
       0      0      Sy
     即P.rotation(a)=(x * Sx,y * Sy)=P*Scale;
     缩放(Scale)矩阵是本矩阵类(Matrix)的泛型特例,单独说明,为提高效率,实数(f64)参与矩阵乘法计算。

     四、平移、旋转、缩放的组合矩阵(M2D)可以表示为
       1     Dx    Dy
       0     Xx    Xy
       0     Yx    Yy
     即P.M=(1,x*Xx+y*Yx+1*Dx,x*Xy+y*Yy+1*Dy)=P*M2D;
    组合(M2D)矩阵是本矩阵类(Matrix)的泛型特例,单独说明。

     五、转换矩阵通过乘法运算的重载,实现其功能。该乘法支持结合律,如P*M1*M2*M3=P*(M1*M2*M3)
    根据上面叙述,总结出如下编程思路:
    1、平面几何转换,都可以使用转换矩阵实现,不需要在各几何体类中单独实现平移、旋转、缩放功能;
    2、多次平面几何转换,如P*M1*M2*M3,可以使用结合律,让多个矩阵合并成一个转换矩阵。
    3、考虑到纯平移、旋转或缩放转换用组合矩阵计算时,会出现大量已知的0或1参加计算,影响计算速度。因此定义了3个零大小的类Zero、One和NegOne用于表示0、1、-1,该定义在number.rs文件中实现。转换矩阵为泛型类,泛型定义在本文件实现,通过泛型特例实现的平移(Move)、旋转(Rotate)、缩放(Scale)、组合(M2D)等矩阵独立解说。
    4、为了汇总几何体与转换矩阵的计算(如 P*M),方便系统维护,几何体类的参数写成矩阵格式。初步意向如下,后面单独解说。
      (1)点(point)(x,y)可以认为是点(0,0)平移到(x,y)后形成的,即表示为:
         1       x      y
         0      0       0
         0      0       0
       (2) 线段(line)有起点(x1,y1)和终点(x2,y2),可以认为是起点(0,0),终点为(1,0)的线段经过变换得来的,即:
         1          x1         y1
         0          x2-x1      y2-y1
         0          0          0
       (3) 圆有圆心(Ox,Oy)、半径r(等价于圆过点(Ox+r,Oy) ),可以理解为圆心在(0,0),半径为1(等价于圆过点(1,0))的单位圆变换过来的,即:
         1        Ox      Oy
         0        r       0
         0        0       0
       (4) 椭圆有圆心(Ox,Oy)、长半轴长 Ra,短半轴长Rb,与圆类似,表示如下:
         1        Ox      Oy
         0        Ra      0
         0        0       Rb
       (5) 图块实体有插入点(x,y),x轴比例Sx、y轴比例Sy、旋转角度a,表示如下: 
         Sx*cos(a)       Sx*sin(a)          0
         -Sy*sin(a)      Sy*cos(a)          0
         x               y                  1
     六、 根据运算结果,增加一个类非切变矩阵(NonShear),结构如下
         1     Dx    Dy
         0     Xx    0
         0     0     Yy
 */
/*
 * 编制人: $ource
 * 修改版次:0版完成版
 * 本版次创建时间: 2024年8月24日
 * 最后修改时间: 无
 * 待完善问题:无
 * 说明:
 * 转换矩阵Matrix有大量已知的0和1及-1参与计算。为标识这些特征,提高编译后代码效率,实现零大小的Zero、One、NegOne类型。
 */
#[derive(Debug,Copy,Clone)]
pub struct Zero{
}

#[derive(Debug,Copy,Clone)]
pub struct One{
}
#[derive(Debug,Copy,Clone)]
pub struct NegOne{
}


/*转换矩阵通用类Matrix
* 编制人: $ource
* 修改版次:0.2.0版完成版
* 本版次创建时间: 2024年8月16日
* 最后修改时间: 2024年8月26日
* 待完善问题:无
*/
use std::ops::{Mul,Div};
// 变换矩阵数据格式(TransformMatrix)
//  1 dx dy      1 Dx  Dy       1 m01 m02
//  0 sx ry      0 Xx  Xy       0 m11 m12
//  0 rx sy      0 Yx  Yy       0 m21 m22

#[derive(Clone,Copy)]
pub struct Matrix<Tdx:Clone+Copy,Tdy:Clone+Copy,Txx:Clone+Copy,Txy:Clone+Copy,Tyx:Clone+Copy,Tyy:Clone+Copy>{
   pub m01:Tdx,pub m02:Tdy,
   pub m11:Txx,pub m12:Txy,
   pub m21:Tyx, pub m22:Tyy
}

pub type M2D=Matrix<f64,f64,f64,f64,f64,f64>;//组合矩阵M2D
pub type NonShear=Matrix<f64,f64,f64,Zero,Zero,f64>;//非切变矩阵NonShear
pub type Rotate=Matrix<Zero,Zero,f64,f64,f64,f64>;//旋转矩阵Rotate
pub type Scale=Matrix<Zero,Zero,f64,Zero,Zero,f64>;//缩放矩阵Scale
pub type Move=Matrix<f64,f64,One,Zero,Zero,One>;//平移矩阵Move

/*
* 矩阵基本变换,组合矩阵类 M2D
** 编制人: $ource
* 修改版次及创建时间:0版完成版(2024年8月25日)
* 修改内容及时间:无
* 待完善问题:无
* 内容说明:组合矩阵是一个2X3 实数(f64)类型的矩阵,实现了“组合矩阵*组合矩阵”的乘法重载。矩阵格式如下
*   1    m01   m02
*   0    m11   m12
*   0    m21   m22
*/
impl M2D{
   pub fn new(dx:f64,dy:f64,xx:f64,xy:f64,yx:f64,yy:f64)->M2D{
       M2D{
           m01:dx,  m02:dy,
           m11:xx,  m12:xy,
           m21:yx,  m22:yy
       }
   }
}

impl Mul<M2D> for M2D{//“组合矩阵*组合矩阵”
   type Output = M2D;
   fn mul(self, tm:M2D) ->M2D{
       M2D{
           m01:self.m01 * tm.m11 + self.m02 * tm.m21 + tm.m01,m02:self.m01 * tm.m12 + self.m02 * tm.m22 + tm.m02,
           m11:self.m11 * tm.m11 + self.m12 * tm.m21         ,m12:self.m11 * tm.m12 + self.m12 * tm.m22,
           m21:self.m21 * tm.m11 + self.m22 * tm.m21         ,m22:self.m21 * tm.m12 + self.m22 * tm.m22
       }
   }
}

impl Mul<NonShear> for M2D{//“组合矩阵*非切变矩阵”
   type Output = M2D;
   fn mul(self, tm:NonShear) ->M2D{
       M2D{
           m01:self.m01 * tm.m11 + tm.m01, m02:self.m02 * tm.m22 + tm.m02,
           m11:self.m11 * tm.m11         , m12:self.m12 * tm.m22,
           m21:self.m21 * tm.m11         , m22:self.m22 * tm.m22
       }
   }
}

impl Mul<Rotate> for M2D{//组合矩阵*旋转矩阵
   type Output = M2D;
   fn mul(self, tm:Rotate) ->M2D{
       M2D{
           m01:self.m01 * tm.m11 + self.m02 * tm.m21 ,m02:self.m01 * tm.m12 + self.m02 * tm.m22,
           m11:self.m11 * tm.m11 + self.m12 * tm.m21 ,m12:self.m11 * tm.m12 + self.m12 * tm.m22,
           m21:self.m21 * tm.m11 + self.m22 * tm.m21 ,m22:self.m21 * tm.m12 + self.m22 * tm.m22
       }
   }
}

impl Mul<Scale> for M2D{//组合矩阵*缩放矩阵
   type Output = M2D;
   fn mul(self, tm:Scale) ->M2D{
       M2D{
           m01:self.m01 * tm.m11, m02:self.m02 * tm.m22,
           m11:self.m11 * tm.m11, m12:self.m12 * tm.m22,
           m21:self.m21 * tm.m11, m22:self.m22 * tm.m22
       }
   }
}

impl Mul<Move> for M2D{//组合矩阵*平移矩阵
   type Output = M2D;
   fn mul(self, tm:Move) ->M2D{
       M2D{
           m01:self.m01 + tm.m01,m02:self.m02+ tm.m02,
           m11:self.m11         ,m12:self.m12,
           m21:self.m21         ,m22:self.m22
       }
   }
}

/*
* 矩阵变换,非切变类NonShear
** 编制人: $ource
* 修改版次及创建时间:0版完成版(2024年8月26日)
* 修改内容及时间:无
* 待完善问题:无
* 内容说明:非切变是“平移矩阵*缩放矩阵”的产物,分别实现了“非切变矩阵*各矩阵”的运算符重载。非切变矩阵格式如下。
      1      m01    m02
      0      m11    0
      0      0      m22
*/
impl NonShear{
   pub fn new(dx:f64,dy:f64,xx:f64,yy:f64)->NonShear{
       NonShear{
           m01:dx    , m02:dy,
           m11:xx    , m12:Zero{},
           m21:Zero{}, m22:yy
       }
   }
}

impl Mul<M2D> for NonShear{//“非切变矩阵*组合矩阵”
   type Output = M2D;
   fn mul(self, tm:M2D) ->M2D{
       M2D{
           m01:self.m01 * tm.m11 + self.m02 * tm.m21 + tm.m01, m02:self.m01 * tm.m12 + self.m02 * tm.m22 + tm.m02,
           m11:self.m11 * tm.m11                             , m12:self.m11 * tm.m12,
           m21:self.m22 * tm.m21                             , m22:self.m22 * tm.m22
       }
   }
}

impl Mul<NonShear> for NonShear{//“非切变矩阵*非切变矩阵”
   type Output = NonShear;
   fn mul(self, tm:NonShear) ->NonShear{
       NonShear::new(self.m01 * tm.m11 + tm.m01, self.m02 * tm.m22 + tm.m02,
                     self.m11 * tm.m11
                                                   , self.m22 * tm.m22
       )
   }
}

impl Mul<Rotate> for NonShear{//“非切变矩阵*旋转矩阵”
   type Output = M2D;
   fn mul(self, tm:Rotate) ->M2D{
       M2D{
           m01:self.m01 * tm.m11 + self.m02 * tm.m21, m02:self.m01 * tm.m12 + self.m02 * tm.m22,
           m11:self.m11 * tm.m11                    , m12:self.m11 * tm.m12,
           m21:self.m22 * tm.m21                    , m22:self.m22 * tm.m22
       }
   }
}

impl Mul<Scale> for NonShear{//非切变矩阵*缩放矩阵
   type Output = NonShear;
   fn mul(self, tm:Scale) ->NonShear{
       NonShear::new(self.m01 * tm.m11,self.m02 * tm.m22,
                     self.m11 * tm.m11
                                      ,self.m22 * tm.m22
       )
   }
}

impl Mul<Move> for NonShear{//“非切变矩阵*平移矩阵”
   type Output = NonShear;
   fn mul(self, tm:Move) ->NonShear{
       NonShear::new(self.m01 + tm.m01, self.m01 + tm.m02,
                    self.m11 
                                     , self.m22
       )
   }
}
/*
* 矩阵基本变换,旋转类Rotate
** 编制人: $ource
* 修改版次及创建时间:0版完成版(2024年8月26日)
* 修改内容及时间:无
* 待完善问题:无
* 内容说明:旋转是矩阵基本功能,分别实现了“组合矩阵*各矩阵”的运算符重载。旋转矩阵格式如下。
   1     0         0
   0     cos(a)    sin(a)
   0     -sin(a)   cos(a)
*/
use super::angle::Angle;
impl Rotate{
   pub fn new(xx:f64,xy:f64,yx:f64,yy:f64)->Rotate{
       Rotate{
           m01:Zero{},  m02:Zero{},
           m11:xx,  m12:xy,
           m21:yx, m22:yy
       }
   }

   pub fn from(ang:Angle)->Rotate{
       let ang_x=ang.unit_x();
       let ang_y=ang.unit_y();
       Rotate::new(ang_x,ang_y,-ang_y,ang_x)
   }
}

impl Mul<M2D> for Rotate{//旋转矩阵*组合矩阵
   type Output = M2D;
   fn mul(self, tm:M2D) ->M2D{
       M2D{
           m01:tm.m01                               , m02:tm.m02,
           m11:self.m11 * tm.m11 + self.m12 * tm.m21, m12:self.m11 * tm.m12 + self.m12 * tm.m22,
           m21:self.m21 * tm.m11 + self.m22 * tm.m21         ,m22:self.m21 * tm.m12 + self.m22 * tm.m22
       }
   }
}

impl Mul<NonShear> for Rotate{//“旋转矩阵*非切变矩阵”
   type Output = M2D;
   fn mul(self, tm:NonShear) ->M2D{
       M2D{
           m01:tm.m01           , m02:tm.m02,
           m11:self.m11 * tm.m11, m12:self.m12 * tm.m22,
           m21:self.m21 * tm.m11, m22:self.m22 * tm.m22
       }
   }
}

impl Mul<Rotate> for Rotate{//旋转矩阵*旋转矩阵
   type Output = Rotate;
   fn mul(self, tm:Rotate) ->Rotate{
       Rotate::new(
           self.m11 * tm.m11 + self.m12 * tm.m21, self.m11 * tm.m12 + self.m12 * tm.m22,
           self.m21 * tm.m11 + self.m22 * tm.m21, self.m21 * tm.m12 + self.m22 * tm.m22
       )
   }
}

impl Mul<Scale> for Rotate{//旋转矩阵*缩放矩阵
   type Output = Rotate;
   fn mul(self, tm:Scale) ->Rotate{
       Rotate::new(
           self.m11 * tm.m11, self.m12 * tm.m22,
           self.m21 * tm.m11,self.m22 * tm.m22
       )
   }
}

impl Mul<Move> for Rotate{//旋转矩阵*平移矩阵
   type Output = M2D;
   fn mul(self, tm:Move) ->M2D{
       M2D{
           m01:tm.m01, m02:tm.m02,
           m11:self.m11, m12:self.m12,
           m21:self.m21,m22:self.m22
       }
   }
}

/*
* 矩阵基本变换,缩放类Scale
** 编制人: $ource
* 修改版次及创建时间:0版完成版(2024年8月26日)
* 修改内容及时间:无
* 待完善问题:无
* 内容说明:缩放是矩阵基本功能,分别实现了“组合矩阵*各矩阵”的运算符重载。缩放矩阵格式如下。
      1      0      0
      0      Sx     0
      0      0      Sy
*/
impl Scale{
   pub fn new(sx:f64,sy:f64)->Scale{
       Scale{
           m01:Zero{},  m02:Zero{},
           m11:sx    , m12:Zero{},
           m21:Zero{}, m22:sy
       }
   }

   pub fn from(scale:f64)->Scale{
       Scale::new(scale,scale)
   }
}

impl Mul<M2D> for Scale{//缩放矩阵*组合矩阵
   type Output = M2D;
   fn mul(self, tm:M2D) ->M2D{
       M2D{
           m01:tm.m01           , m02:tm.m02,
           m11:self.m11 * tm.m11, m12:self.m11 * tm.m12,
           m21:self.m22 * tm.m21,m22:self.m22 * tm.m22
       }
   }
}

impl Mul<NonShear> for Scale{//缩放矩阵*非切变矩阵
   type Output = NonShear;
   fn mul(self, tm:NonShear) ->NonShear{
       NonShear::new(tm.m01           , tm.m02,
                     self.m11 * tm.m11
                                      ,self.m22 * tm.m22
       )
   }
}

impl Mul<Rotate> for Scale{//缩放矩阵*旋转矩阵
   type Output = Rotate;
   fn mul(self, tm:Rotate) ->Rotate{
       Rotate::new(self.m11+tm.m11, self.m11*tm.m12, self.m22*tm.m21, self.m22*tm.m22)
   }
}

impl Mul<Scale> for Scale{//缩放矩阵*缩放矩阵
   type Output = Scale;
   fn mul(self, tm:Scale) ->Scale{
       Scale::new(self.m11 * tm.m11, self.m22 * tm.m22)
   }
}

impl Mul<Move> for Scale{//缩放矩阵*平移矩阵
   type Output = NonShear;
   fn mul(self, tm:Move) ->NonShear{
       NonShear::new(tm.m01,tm.m02,self.m11,self.m22)
   }
}

/*
* 矩阵基本变换,平移类Move
** 编制人: $ource
* 修改版次及创建时间:0版完成版(2024年8月25日)
* 修改内容及时间:无
* 待完善问题:无
* 内容说明:平移是矩阵基本功能,分别实现了“组合矩阵*各矩阵”的运算符重载。平移矩阵格式如下。
*   1    m01   m02
*   0    1     0
*   0    0     1
*/
impl Move{
   pub fn new(dx:f64,dy:f64)->Move{
       Move{
           m01:dx   ,  m02:dy,
           m11:One{},  m12:Zero{},
           m21:Zero{}, m22:One{}
       }
   }
}

impl Mul<M2D> for Move{//平移矩阵*组合矩阵
   type Output = M2D;
   fn mul(self, tm:M2D) ->M2D{
       M2D{
           m01:self.m01 * tm.m11 + self.m02 * tm.m21 + tm.m01,m02:self.m01 * tm.m12 + self.m02 * tm.m22 + tm.m02,
           m11:tm.m11                                        ,m12:tm.m12,
           m21:tm.m21                                        ,m22:tm.m22
       }
   }
}

impl Mul<NonShear> for Move{//“平移矩阵*非切变矩阵”
   type Output =NonShear;
   fn mul(self, tm:NonShear) ->NonShear{
       NonShear::new(self.m01 * tm.m11 + tm.m01, self.m02 * tm.m22 + tm.m02,
                     tm.m11
                                                   , tm.m22
       )
   }
}

impl Mul<Scale> for Move{//平移矩阵*缩放矩阵
   type Output = NonShear;
   fn mul(self, tm:Scale) ->NonShear{
       NonShear::new(self.m01 * tm.m11,self.m02 * tm.m22,tm.m11,tm.m22)
   }
}

impl Mul<Rotate> for Move{//平移矩阵*旋转矩阵
   type Output = M2D;
   fn mul(self, tm:Rotate) ->M2D{
       M2D{
           m01:self.m01 * tm.m11 + self.m02 * tm.m21,m02:self.m01 * tm.m12 + self.m02 * tm.m22,
           m11:tm.m11                               ,m12:tm.m12,
           m21:tm.m21                               ,m22:tm.m22
       }
   }
}

impl Mul<Move> for Move{//平移矩阵*平移矩阵
   type Output = Move;
   fn mul(self, tm:Move) ->Move{
       Move::new(self.m01 + tm.m01,self.m02+ tm.m02)
   }
}

impl Div<Move> for Move{//平移矩阵/平移矩阵
   type Output = Move;
   fn div(self, tm:Move) ->Move{
       Move::new(self.m01 - tm.m01,self.m02- tm.m02)
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值