1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.4 3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 // 16 // Affine transformations 17 // 18 //---------------------------------------------------------------------------- 19 #include "agg_trans_affine.h" 20 21 22 23 namespace agg 24 { 25 26 //------------------------------------------------------------------------ parl_to_parl(const double * src,const double * dst)27 const trans_affine& trans_affine::parl_to_parl(const double* src, 28 const double* dst) 29 { 30 sx = src[2] - src[0]; 31 shy = src[3] - src[1]; 32 shx = src[4] - src[0]; 33 sy = src[5] - src[1]; 34 tx = src[0]; 35 ty = src[1]; 36 invert(); 37 multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1], 38 dst[4] - dst[0], dst[5] - dst[1], 39 dst[0], dst[1])); 40 return *this; 41 } 42 43 //------------------------------------------------------------------------ rect_to_parl(double x1,double y1,double x2,double y2,const double * parl)44 const trans_affine& trans_affine::rect_to_parl(double x1, double y1, 45 double x2, double y2, 46 const double* parl) 47 { 48 double src[6]; 49 src[0] = x1; src[1] = y1; 50 src[2] = x2; src[3] = y1; 51 src[4] = x2; src[5] = y2; 52 parl_to_parl(src, parl); 53 return *this; 54 } 55 56 //------------------------------------------------------------------------ parl_to_rect(const double * parl,double x1,double y1,double x2,double y2)57 const trans_affine& trans_affine::parl_to_rect(const double* parl, 58 double x1, double y1, 59 double x2, double y2) 60 { 61 double dst[6]; 62 dst[0] = x1; dst[1] = y1; 63 dst[2] = x2; dst[3] = y1; 64 dst[4] = x2; dst[5] = y2; 65 parl_to_parl(parl, dst); 66 return *this; 67 } 68 69 //------------------------------------------------------------------------ multiply(const trans_affine & m)70 const trans_affine& trans_affine::multiply(const trans_affine& m) 71 { 72 double t0 = sx * m.sx + shy * m.shx; 73 double t2 = shx * m.sx + sy * m.shx; 74 double t4 = tx * m.sx + ty * m.shx + m.tx; 75 shy = sx * m.shy + shy * m.sy; 76 sy = shx * m.shy + sy * m.sy; 77 ty = tx * m.shy + ty * m.sy + m.ty; 78 sx = t0; 79 shx = t2; 80 tx = t4; 81 return *this; 82 } 83 84 85 //------------------------------------------------------------------------ invert()86 const trans_affine& trans_affine::invert() 87 { 88 double d = determinant_reciprocal(); 89 90 double t0 = sy * d; 91 sy = sx * d; 92 shy = -shy * d; 93 shx = -shx * d; 94 95 double t4 = -tx * t0 - ty * shx; 96 ty = -tx * shy - ty * sy; 97 98 sx = t0; 99 tx = t4; 100 return *this; 101 } 102 103 104 //------------------------------------------------------------------------ flip_x()105 const trans_affine& trans_affine::flip_x() 106 { 107 sx = -sx; 108 shy = -shy; 109 tx = -tx; 110 return *this; 111 } 112 113 //------------------------------------------------------------------------ flip_y()114 const trans_affine& trans_affine::flip_y() 115 { 116 shx = -shx; 117 sy = -sy; 118 ty = -ty; 119 return *this; 120 } 121 122 //------------------------------------------------------------------------ reset()123 const trans_affine& trans_affine::reset() 124 { 125 sx = sy = 1.0; 126 shy = shx = tx = ty = 0.0; 127 return *this; 128 } 129 130 //------------------------------------------------------------------------ is_identity(double epsilon) const131 bool trans_affine::is_identity(double epsilon) const 132 { 133 return is_equal_eps(sx, 1.0, epsilon) && 134 is_equal_eps(shy, 0.0, epsilon) && 135 is_equal_eps(shx, 0.0, epsilon) && 136 is_equal_eps(sy, 1.0, epsilon) && 137 is_equal_eps(tx, 0.0, epsilon) && 138 is_equal_eps(ty, 0.0, epsilon); 139 } 140 141 //------------------------------------------------------------------------ is_valid(double epsilon) const142 bool trans_affine::is_valid(double epsilon) const 143 { 144 return std::fabs(sx) > epsilon && std::fabs(sy) > epsilon; 145 } 146 147 //------------------------------------------------------------------------ is_equal(const trans_affine & m,double epsilon) const148 bool trans_affine::is_equal(const trans_affine& m, double epsilon) const 149 { 150 return is_equal_eps(sx, m.sx, epsilon) && 151 is_equal_eps(shy, m.shy, epsilon) && 152 is_equal_eps(shx, m.shx, epsilon) && 153 is_equal_eps(sy, m.sy, epsilon) && 154 is_equal_eps(tx, m.tx, epsilon) && 155 is_equal_eps(ty, m.ty, epsilon); 156 } 157 158 //------------------------------------------------------------------------ rotation() const159 double trans_affine::rotation() const 160 { 161 double x1 = 0.0; 162 double y1 = 0.0; 163 double x2 = 1.0; 164 double y2 = 0.0; 165 transform(&x1, &y1); 166 transform(&x2, &y2); 167 return std::atan2(y2-y1, x2-x1); 168 } 169 170 //------------------------------------------------------------------------ translation(double * dx,double * dy) const171 void trans_affine::translation(double* dx, double* dy) const 172 { 173 *dx = tx; 174 *dy = ty; 175 } 176 177 //------------------------------------------------------------------------ scaling(double * x,double * y) const178 void trans_affine::scaling(double* x, double* y) const 179 { 180 double x1 = 0.0; 181 double y1 = 0.0; 182 double x2 = 1.0; 183 double y2 = 1.0; 184 trans_affine t(*this); 185 t *= trans_affine_rotation(-rotation()); 186 t.transform(&x1, &y1); 187 t.transform(&x2, &y2); 188 *x = x2 - x1; 189 *y = y2 - y1; 190 } 191 192 193 } 194 195