00001 // $Id: trans2d.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 // 2D Matrix transformation classes 00100 00101 #include "camtypes.h" 00102 //#include "docrect.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00103 //#include "matrix.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00104 //#include "trans2d.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 00107 CC_IMPLEMENT_DYNAMIC(Trans2DMatrix, TransInvertable) 00108 00109 // Declare smart memory handling in Debug builds 00110 #define new CAM_DEBUG_NEW 00111 00112 00113 00114 /******************************************************************************************** 00115 > void Trans2DMatrix::InitDecomposedTransforms() 00116 00117 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00118 Created: 4/6//95 00119 Purpose: ensure all member vars are init'ed 00120 ********************************************************************************************/ 00121 00122 void Trans2DMatrix::InitDecomposedTransforms() 00123 { 00124 Scale = 0; // 0 indicates cached values invalid 00125 Aspect = 1; 00126 Rotation = 0; 00127 Skew = 0; 00128 Translation = DocCoord(0,0); 00129 } 00130 00131 00132 /******************************************************************************************** 00133 > Trans2DMatrix::Trans2DMatrix( ) 00134 00135 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00136 Created: 1/2/95 00137 Purpose: Builds a 2D Tranform object of the identiry matrix (ie it has no effect) 00138 ********************************************************************************************/ 00139 00140 Trans2DMatrix::Trans2DMatrix( ) 00141 { 00142 SetTransform(); 00143 } 00144 00145 void Trans2DMatrix::SetTransform() 00146 { 00147 // Build the translation matrix 00148 TransMatrix = Matrix(); 00149 00150 // Set the flags 00151 TransLines = FALSE; 00152 TransFills = TRUE; 00153 InitDecomposedTransforms(); 00154 } 00155 00156 00157 /******************************************************************************************** 00158 00159 > Trans2DMatrix::Trans2DMatrix( DocCoord CentreOfRot, ANGLE RotateBy ) 00160 00161 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00162 Created: 7/3/94 00163 Inputs: CentreOfRot - The centre of rotation 00164 RotateBy - The angle of the rotation that this transform object will perform 00165 Purpose: Creates a 2D Matrix transform object that will perform a rotation about the 00166 given point by the given number of degrees. 00167 00168 ********************************************************************************************/ 00169 00170 Trans2DMatrix::Trans2DMatrix(DocCoord CentreOfRot, ANGLE RotateBy) 00171 { 00172 SetTransform(CentreOfRot,RotateBy); 00173 } 00174 00175 void Trans2DMatrix::SetTransform(DocCoord CentreOfRot, ANGLE RotateBy) 00176 { 00177 // Build the matricies we need 00178 Matrix RotateIt(RotateBy); 00179 Matrix TransFromOrigin( CentreOfRot.x, CentreOfRot.y ); 00180 00181 // need to translate the centre of rotation to the origin 00182 TransMatrix = Matrix( -CentreOfRot.x, -CentreOfRot.y ); 00183 00184 // rotate about the origin 00185 TransMatrix *= RotateIt; 00186 00187 // translate back to the centre of rotation 00188 TransMatrix *= TransFromOrigin; 00189 00190 // Set the flags 00191 TransLines = FALSE; 00192 TransFills = TRUE; 00193 InitDecomposedTransforms(); 00194 } 00195 00196 /******************************************************************************************** 00197 00198 > Trans2DMatrix::Trans2DMatrix( INT32 TransX, INT32 TransY) 00199 00200 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00201 Created: 7/3/94 00202 Inputs: TransX - The X translation 00203 TransY - The Y translation 00204 Purpose: Builds a 2D Tranform object that will perform a translation by an offset 00205 Transx, TransY. 00206 00207 ********************************************************************************************/ 00208 00209 Trans2DMatrix::Trans2DMatrix(INT32 TransX, INT32 TransY) 00210 { 00211 SetTransform(TransX,TransY); 00212 } 00213 00214 void Trans2DMatrix::SetTransform(INT32 TransX, INT32 TransY) 00215 { 00216 // Build the translation matrix 00217 TransMatrix = Matrix(TransX, TransY); 00218 00219 // Set the flags 00220 TransLines = FALSE; 00221 TransFills = TRUE; 00222 InitDecomposedTransforms(); 00223 } 00224 00225 00226 00227 /******************************************************************************************** 00228 00229 > Trans2DMatrix::Trans2DMatrix( Matrix& NewMatrix ) 00230 00231 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00232 Created: 10/02/94 00233 Inputs: NewMatrix - The transformation matrix that you wish to apply 00234 Purpose: constructor 00235 00236 ********************************************************************************************/ 00237 00238 Trans2DMatrix::Trans2DMatrix( const Matrix &NewMatrix ) 00239 { 00240 SetTransform(NewMatrix); 00241 } 00242 00243 void Trans2DMatrix::SetTransform(const Matrix& NewMatrix) 00244 { 00245 // Take a copy of the matrix 00246 TransMatrix = NewMatrix; 00247 00248 // Set the flags 00249 TransLines = FALSE; 00250 TransFills = TRUE; 00251 InitDecomposedTransforms(); 00252 } 00253 00254 00255 00256 /******************************************************************************************** 00257 00258 > Trans2DMatrix::Trans2DMatrix(const Trans2DMatrix& Other) 00259 00260 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00261 Created: 6/9/94 00262 Inputs: Other - The other trans2dmatrix to copy 00263 Purpose: Copy constructor 00264 00265 ********************************************************************************************/ 00266 00267 Trans2DMatrix::Trans2DMatrix(const Trans2DMatrix& Other) 00268 { 00269 SetTransform(Other); 00270 } 00271 00272 void Trans2DMatrix::SetTransform(const Trans2DMatrix& Other) 00273 { 00274 // Copy all the elements from the other trans2dmatrix to this new one. 00275 TransMatrix = Other.TransMatrix; 00276 TransLines = Other.TransLines; 00277 TransFills = Other.TransFills; 00278 InitDecomposedTransforms(); 00279 } 00280 00281 /******************************************************************************************** 00282 00283 > void Trans2DMatrix::Transform( DocCoord* Coords, INT32 NumCoords ) 00284 00285 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00286 Created: 10/02/94 00287 Inputs: Coords - Pointer to an array of coodinates to transform 00288 NumCoords - the number of coodinates in the array 00289 Outputs: Coords - The coordinates in the array will have been transformed 00290 Purpose: Transform the coordinates in the array using the matrix in the transform 00291 object 00292 00293 ********************************************************************************************/ 00294 00295 void Trans2DMatrix::Transform( DocCoord* Coords, INT32 NumCoords ) 00296 { 00297 // Get the matrix to transform all the coords passed in 00298 TransMatrix.transform( (Coord*)Coords, NumCoords ); 00299 InitDecomposedTransforms(); 00300 } 00301 00302 00303 /******************************************************************************************** 00304 00305 > void Trans2DMatrix::Invert() 00306 00307 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00308 Created: 10/02/94 00309 Purpose: Inverts the transformation matrix held by this transform object. future calls 00310 to the transform() member function will cause it to transform coordinates 00311 back to their original positions. ie, call Transform(), call Invert() and 00312 call Transform() again should give you the same set of coords as you started 00313 with 00314 00315 ********************************************************************************************/ 00316 void Trans2DMatrix::Invert() 00317 { 00318 // Invert the transformation matrix 00319 TransMatrix = TransMatrix.Inverse(); 00320 00321 InitDecomposedTransforms(); 00322 } 00323 00324 00325 /******************************************************************************************** 00326 > BOOL Trans2DMatrix::IsTranslation() 00327 00328 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00329 Created: 09/12/2004 00330 Purpose: Determine whether the transformation is a simple translation 00331 ********************************************************************************************/ 00332 00333 BOOL Trans2DMatrix::IsTranslation() 00334 { 00335 return TransMatrix.IsTranslation(); 00336 } 00337 00338 00339 /******************************************************************************************** 00340 00341 > INT32 GetWorkingQuadrant() 00342 00343 Author: Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com> 00344 Created: 07/07/00 00345 Purpose: To find out which quadrant the current matrix is working in. 00346 OR To help find out if the matrix is flipping an object and in which way. 00347 00348 1 | 2 00349 --------- 00350 4 | 3 00351 00352 Quadrant 1: A > 0 && D > 0 00353 Quadrant 2: A < 0 && D > 0 00354 Quadrant 4: A > 0 && D < 0 00355 Quadrant 3: A < 0 && D < 0 00356 00357 The return value is the quadrant in which the matrix is working in. 00358 00359 ********************************************************************************************/ 00360 INT32 Trans2DMatrix::GetWorkingQuadrant() 00361 { 00362 FIXED16 ZERO = 0; 00363 FIXED16 ABCD[4]; 00364 INT32 XY[2]; 00365 00366 TransMatrix.GetComponents(&ABCD[0],&XY[0]); 00367 00368 if(ABCD[3] >= ZERO) 00369 { 00370 // either 1 or 2 00371 if(ABCD[0] >= ZERO) 00372 return 1; 00373 else 00374 return 2; 00375 } 00376 else 00377 { 00378 // either 3 or 4 00379 if(ABCD[0] >= ZERO) 00380 return 4; 00381 else 00382 return 3; 00383 } 00384 00385 return 1; 00386 } 00387 00388 /******************************************************************************************** 00389 00390 > Trans2DMatrix& Trans2DMatrix::operator*=(const Trans2DMatrix& op) 00391 00392 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00393 Created: 07/11/94 00394 Inputs: Trans2DMatrix to be multiplied 00395 Outputs: None. 00396 Returns: result of multiplication. 00397 Purpose: Overloads the *= operator for Trans2DMatrix. 00398 Errors: None. 00399 00400 ********************************************************************************************/ 00401 /* 00402 Technical notes: 00403 00404 ********************************************************************************************/ 00405 00406 00407 Trans2DMatrix& Trans2DMatrix::operator*=(const Trans2DMatrix& op) 00408 { 00409 TransMatrix*=op.TransMatrix; 00410 InitDecomposedTransforms(); 00411 return *this; 00412 } 00413 00414 00415 00416 /******************************************************************************************** 00417 00418 > Trans2DMatrix& Trans2DMatrix::operator=(const Trans2DMatrix& rhs) 00419 00420 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00421 Created: 2/1/95 00422 Inputs: Trans2DMatrix to be copied into this object 00423 Outputs: None. 00424 Returns: result of assignment 00425 Purpose: Overloads the = operator for Trans2DMatrix 00426 Errors: None. 00427 00428 ********************************************************************************************/ 00429 00430 Trans2DMatrix& Trans2DMatrix::operator=(const Trans2DMatrix& rhs) 00431 { 00432 TransMatrix = rhs.TransMatrix; 00433 00434 //Graham 12/8/96: Added these because, well, you need them 00435 //Fixes bug 4938 00436 TransLines = rhs.TransLines; 00437 TransFills = rhs.TransFills; 00438 00439 InitDecomposedTransforms(); 00440 return *this; 00441 } 00442 00443 00444 /******************************************************************************************** 00445 > void Trans2DMatrix::EnsureDecomposedTransformsCached() 00446 00447 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00448 Created: 4/6/95 00449 Purpose: ensures the decomposed transforms are cached 00450 ********************************************************************************************/ 00451 00452 void Trans2DMatrix::EnsureDecomposedTransformsCached() 00453 { 00454 if (Scale==0) 00455 { 00456 GetpMatrix()->Decompose(&Scale, &Aspect, &Rotation, &Skew, &Translation, &ScaleY); 00457 Rotation = (Rotation*180)/PI; 00458 Skew = (Skew *180)/PI; // convert to degrees!? 00459 } 00460 } 00461 00462 00463 /******************************************************************************************** 00464 > FIXED16 Trans2DMatrix::GetScale() 00465 00466 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00467 Created: 4/6/95 00468 Purpose: get the transform's scale component 00469 ********************************************************************************************/ 00470 00471 FIXED16 Trans2DMatrix::GetScale() 00472 { 00473 EnsureDecomposedTransformsCached(); 00474 return Scale; 00475 } 00476 00477 00478 /******************************************************************************************** 00479 > FIXED16 Trans2DMatrix::GetAspect() 00480 00481 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00482 Created: 4/6/95 00483 Purpose: get the transform's Aspect component 00484 ********************************************************************************************/ 00485 00486 FIXED16 Trans2DMatrix::GetAspect() 00487 { 00488 EnsureDecomposedTransformsCached(); 00489 return Aspect; 00490 } 00491 00492 00493 /******************************************************************************************** 00494 > ANGLE Trans2DMatrix::GetRotation() 00495 00496 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00497 Created: 4/6/95 00498 Purpose: get the transform's Rotation component 00499 ********************************************************************************************/ 00500 00501 ANGLE Trans2DMatrix::GetRotation() 00502 { 00503 EnsureDecomposedTransformsCached(); 00504 return Rotation; 00505 } 00506 00507 00508 /******************************************************************************************** 00509 > ANGLE Trans2DMatrix::GetSkew() 00510 00511 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00512 Created: 4/6/95 00513 Purpose: get the transform's Skew component 00514 ********************************************************************************************/ 00515 00516 ANGLE Trans2DMatrix::GetSkew() 00517 { 00518 EnsureDecomposedTransformsCached(); 00519 return Skew; 00520 } 00521 00522 00523 /******************************************************************************************** 00524 > DocCoord Trans2DMatrix::GetTranslation() 00525 00526 Author: Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com> 00527 Created: 4/6/95 00528 Purpose: get the transform's Translation component 00529 ********************************************************************************************/ 00530 00531 DocCoord Trans2DMatrix::GetTranslation() 00532 { 00533 EnsureDecomposedTransformsCached(); 00534 return Translation; 00535 } 00536 00537 00538 00539 /******************************************************************************************** 00540 > FIXED16 Trans2DMatrix::GetScalar() 00541 00542 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00543 Created: 4/6/95 00544 Purpose: get the transform's directionless scale component 00545 (used for scaling line widths, bevel widths, brush widths, etc.) 00546 For compatibility reasons this is defined to be the Y scale factor of the 00547 matrix! 00548 ********************************************************************************************/ 00549 00550 FIXED16 Trans2DMatrix::GetScalar() 00551 { 00552 EnsureDecomposedTransformsCached(); 00553 return ScaleY; 00554 } 00555 00556 00557 /******************************************************************************************** 00558 > virtual BOOL Trans2DMatrix::IsInvertable() 00559 00560 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00561 Created: 2/1/96 00562 Inputs: - 00563 Outputs: - 00564 Returns: TRUE if this transform can be inverted; FALSE if not. 00565 Purpose: To see if this transform is really invertable 00566 SeeAlso: TransformBase::IsInvertable 00567 ********************************************************************************************/ 00568 BOOL Trans2DMatrix::IsInvertable() 00569 { 00570 if (TransMatrix.Type == TRANS_IDENTITY) 00571 return TRUE; 00572 00573 // The inverse has failed if we get an identity matrix 00574 Matrix Inversed = TransMatrix.Inverse(); 00575 00576 return (Inversed.Type != TRANS_IDENTITY); 00577 }