wxArt2D
afmatrix.h
Go to the documentation of this file.
1 /*! \file wx/artbase/afmatrix.h
2  \brief affine matrix class
3 
4  Affine matrixes are used for placing objects in a drawing at a position and angle etc.
5 
6  \author Klaas Holwerda Chris Breeze, Julian Smart
7  \date Created 01/02/97
8 
9  Copyright: (c) Julian Smart and Markus Holzem
10 
11  Licence: wxWidgets licence
12 
13  Affine Matrix calculation.
14 
15  RCS-ID: $Id: afmatrix.h,v 1.14 2009/08/20 18:59:13 titato Exp $
16 */
17 
18 #ifndef _WX_MATRIXH__
19 #define _WX_MATRIXH__
20 
21 #include "wx/geometry.h"
22 #include "wx/artbase/artglob.h"
23 
24 //! A 2x3 affine matrix class for 2D transformations
25 /*!
26  A 2x3 matrix to do 2D transformations.
27 
28  It follows a 'column vector' convention, more or less. A point P=(x,y) is
29  treated as the transpose of [x, y, 1], and transformation is accomplished
30  by pre-multiplication by the transformation matrix M:
31  \verbatim
32  [ sx shx tx ] [x]
33  [x',y'] = [ shy sy ty ] * [y] = [sx*x+shx*y+tx, shy*x+sy*y+ty]
34  [1]
35  \endverbatim
36  It is only "more-or-less" so because accessors of this class use a convention
37  of (col,row), which is backwards from normal mathematical notation. The
38  actual memory layout is double[3][2], which means it's stored column-major:
39  {sx, shy, shx, sy, tx, ty}.
40 
41  It can be used to map data to window coordinates.
42  But also for manipulating your own 2D data.
43  Because this class is specialy designed to do 2D transformations a lot of things
44  could be optimized for this particlular purpose.
45  For example drawing a picture (composed of several primitives)
46  at a certain coordinate and angle within another parent picture.
47  At all times m_isIdentity is set if the matrix itself is an Identity matrix.
48  m_isIdentity is used where possible to optimize calculations.
49 
50  \ingroup drawer
51  \ingroup general
52 */
53 class A2DARTBASEDLLEXP a2dAffineMatrix
54 {
55 public:
56 
57  //! constructor
58  /*!
59  Initialize matrix.
60 
61  First a translation is proceed after this a scalling at that position followed by a rotation at that position.
62 
63  \param xt translation in x
64  \param yt translation in y
65  \param scalex scaling in x
66  \param scaley scaling in y
67  \param degrees rotation clockwise
68  */
69  a2dAffineMatrix( double xt, double yt, double scalex = 1, double scaley = 1, double degrees = 0 );
70 
71  a2dAffineMatrix( double sx, double shx, double shy, double sy, double tx, double ty );
72 
73  //! constructor (makes an identity matrix)
74  a2dAffineMatrix( void );
75 
76  //! constructor using other matrix
77  a2dAffineMatrix( const a2dAffineMatrix& mat );
78 
79  //!get the value in the matrix at col,row
80  /*!
81  rows are horizontal (second index of m_matrix member)
82  columns are vertical (first index of m_matrix member)
83  */
84  double GetValue( int col, int row ) const;
85 
86  //!set the value in the matrix at col,row
87  /*!
88  rows are horizontal (second index of m_matrix member)
89  columns are vertical (first index of m_matrix member)
90  */
91  void SetValue( int col, int row, double value );
92 
93  //! make the same
94  void operator= ( const a2dAffineMatrix& mat );
95 
96  //! are they eqaul
97  friend A2DARTBASEDLLEXP bool operator == ( const a2dAffineMatrix& a, const a2dAffineMatrix& b );
98 
99  //! are they NOT eqaul
100  friend A2DARTBASEDLLEXP bool operator != ( const a2dAffineMatrix& a, const a2dAffineMatrix& b );
101 
102  //! are they eqaul
103  bool operator== ( const a2dAffineMatrix& a );
104 
105  //! are they NOT eqaul
106  bool operator!= ( const a2dAffineMatrix& a );
107 
108  //!multiply matrix m with this
109  a2dAffineMatrix& operator*=( const a2dAffineMatrix& m );
110 
111  //!multiply this by matrix m and return result
112  a2dAffineMatrix operator*( const a2dAffineMatrix& m ) const;
113 
114  //!subtract two matrices
116 
117  //!subtract two matrices
118  friend A2DARTBASEDLLEXP a2dAffineMatrix operator-( const a2dAffineMatrix& a, const a2dAffineMatrix& b );
119 
120  static inline a2dAffineMatrix Mul( const a2dAffineMatrix& m1, const a2dAffineMatrix& m2 ) { return m1 * m2; }
121 
122  /*!
123  rows are horizontal (second index of m_matrix member)
124  columns are vertical (first index of m_matrix member)
125  */
126  double& operator()( int col, int row );
127 
128  /*!
129  rows are horizontal (second index of m_matrix member)
130  columns are vertical (first index of m_matrix member)
131  */
132  double operator()( int col, int row ) const;
133 
134  //! Invert matrix
135  bool Invert( void );
136 
137  //! Make into identity matrix
138  bool Identity( void );
139 
140  //! Return a static identity matrix as reference
141  static const a2dAffineMatrix& GetIdentityMatrix() {return sm_Identity; }
142 
143  //! Is the matrix the identity matrix?
144  /*! Only returns a flag, which is set whenever an operation
145  is done.
146  */
147  inline bool IsIdentity( void ) const { return m_isIdentity; }
148 
149  //! This does an actual check.
150  inline bool IsIdentity1( void ) const ;
151 
152  //! Is the matrix only a translation?
153  /*! checks the matrix to see if it only does a traslation.
154  */
155  inline bool IsTranslate( void ) const;
156 
157  inline bool IsTranslateScaleIso( void ) const;
158 
159  //!Scale by scale (isotropic scaling i.e. the same in x and y):
160  /*!ex:
161  \verbatim
162  | scale 0 0 |
163  matrix' = | 0 scale 0 | x matrix
164  | 0 0 scale |
165  \endverbatim
166  */
167  bool Scale( double scale );
168 
169  //! Remove Scale:
170  /*! ex:
171  \verbatim
172  | 1/sqrt(det) 0 0 |
173  matrix' = | 0 1/sqrt(det) 0 | x matrix
174  | 0 0 1 |
175  \endverbatim
176  */
177  bool RemoveScale();
178 
179  //!Scale with center point and x/y scale
180  /*!ex:
181  \verbatim
182  | xs 0 xc(1-xs) |
183  matrix' = | 0 ys yc(1-ys) | x matrix
184  | 0 0 1 |
185  \endverbatim
186  */
187  a2dAffineMatrix& Scale( const double& xs, const double& ys, const double& xc, const double& yc );
188 
189  //! mirror a matrix in x, y
190  /*!ex:
191  \verbatim
192  | -1 0 0 |
193  matrix' = | 0 -1 0 | x matrix
194  | 0 0 1 |
195  \endverbatim
196  */
197  a2dAffineMatrix& Mirror( bool y = true, bool x = false );
198 
199  //! Translate by dx, dy:
200  /*!ex:
201  \verbatim
202  | 1 0 dx |
203  matrix' = | 0 1 dy | x matrix
204  | 0 0 1 |
205  \endverbatim
206  */
207  bool Translate( double x, double y );
208 
209  //! Rotate clockwise by the given number of degrees:
210  /*!
211  Rotates clockwise: If you call <code>Rotate(20); Rotate(10);</code> the absolute
212  rotation is 30 degrees (if the initially rotation was 0)
213 
214  \see SetRotation
215 
216  \ex:
217  \verbatim
218  | cos sin 0 |
219  matrix' = | -sin cos 0 | x matrix
220  | 0 0 1 |
221  \endverbatim
222  */
223  bool Rotate( double angle );
224 
225  //! Skew Xaxis:
226  /*!ex:
227  \verbatim
228  | 1 tan(a) 0 |
229  matrix' = | 0 1 0 | x matrix
230  | 0 0 1 |
231  \endverbatim
232  */
233  bool SkewX( double degrees );
234 
235  //! Skew Yaxis:
236  /*!ex:
237  \verbatim
238  | 1 0 0 |
239  matrix' = | tan(a) 1 0 | x matrix
240  | 0 0 1 |
241  \endverbatim
242  */
243  bool SkewY( double degrees );
244 
245  //!Rotate counter clockwise with point of rotation
246  /*!ex:
247  \verbatim
248  | cos(r) -sin(r) x(1-cos(r))+y(sin(r)|
249  matrix' = | sin(r) cos(r) y(1-cos(r))-x(sin(r)| x matrix
250  | 0 0 1 |
251  \endverbatim
252  */
253  a2dAffineMatrix& Rotate( const double& r, const double& x, const double& y );
254 
255  //! Transform a point
256  void TransformPoint( double x, double y, double& tx, double& ty ) const;
257 
258  //! Transform a point
259  void TransformPoint( double& tx, double& ty ) const;
260 
261  //! Transform a point
262  void TransformPoint( a2dPoint2D* point ) const;
263 
264  //! Transform a point
265  void TransformPoint( const a2dPoint2D& src, a2dPoint2D* dest ) const;
266 
267  //! Transform a vector
268  /*!
269  This transforms a free vector. It is equivalent to transforming
270  the two points (px,py) and (px+dx,py+dy) and then subtracting the
271  former from the latter. In effect this means it ignores the
272  translation portion of the matrix, and just multiplies by the core 2x2
273  linear transform.
274  */
275  void TransformVector( double dx, double dy, double& tdx, double& tdy ) const;
276 
277  //! Transform a distance
278  /*!
279  This transforms a relative distance.
280  A horizontal and vertical line starting at the origin, and distance long,
281  is transformed. The length of the line with the minimum distance in the transformed space is returned.
282 
283  \param distance distance to transform
284 
285  \return transformed distance
286  */
287  double TransformDistance( double distance ) const;
288 
289  //! Transform a distance
290  void TransformDistance( double& dx, double& dy ) const;
291 
292  //! return scaling in X
293  double Get_scaleX() const;
294 
295  //! return scaling in Y
296  double Get_scaleY() const;
297 
298  //! return rotation
299  /*!
300  Returns the absolute rotation in the range –179.999... to 180 degrees
301  \see SetRotation
302  */
303  double GetRotation() const;
304 
305  //! set rotation
306  /*!
307  In opposite to Rotate this method sets an absolute rotation.
308  \see Rotate
309  */
310  void SetRotation( double rotation );
311 
312  //! get the translation vector as a point
313  a2dPoint2D GetTranslation() const { return a2dPoint2D( m_matrix[2][0], m_matrix[2][1] ); }
314 
315  //! Calculate the determinat of the linear transformation
316  double GetDeterminant() const;
317  //! Calculate the determinat of the shift vector and the transformed y-axis vector
318  double GetDeterminant1() const;
319  //! Calculate the determinat of the transformed x-axis vector and the shift vector
320  double GetDeterminant2() const;
321  //! Calculate the maximum absolute of the elemnts entering GetDeterminant
322  double GetMaximum() const;
323  //! Calculate the maximum absolute of the elemnts entering GetDeterminant1
324  double GetMaximum1() const;
325  //! Calculate the maximum absolute of the elemnts entering GetDeterminant2
326  double GetMaximum2() const;
327 
328  //! Dump the Matrix to a debug window
329  void DebugDump( const wxChar* text, double w, double h ) const;
330 
331 
332 public:
333 
334  //! array store the six double for the affine matrix
335  double m_matrix[3][2];
336 
337  //! true if identity matrix
339 
340 protected:
341  //! A static identity matrix in case an identity matrix is to be returned as reference
343 };
344 
345 //! Is the matrix the identity matrix?
346 //! Each operation checks whether the result is still the identity matrix and sets a flag.
347 inline bool a2dAffineMatrix::IsIdentity1( void ) const
348 {
349  return
350  ( m_matrix[0][0] == 1.0 &&
351  m_matrix[1][1] == 1.0 &&
352  m_matrix[1][0] == 0.0 &&
353  m_matrix[2][0] == 0.0 &&
354  m_matrix[0][1] == 0.0 &&
355  m_matrix[2][1] == 0.0
356  );
357 }
358 
359 inline bool a2dAffineMatrix::IsTranslate( void ) const
360 {
361  return
362  ( m_matrix[0][0] == 1.0 &&
363  m_matrix[1][1] == 1.0 &&
364  m_matrix[1][0] == 0.0 &&
365  m_matrix[0][1] == 0.0
366  );
367 }
368 
369 inline bool a2dAffineMatrix::IsTranslateScaleIso( void ) const
370 {
371  return
372  ( m_matrix[0][0] != 0.0 &&
373  m_matrix[1][1] != 0.0 &&
374  ( m_matrix[0][0] == m_matrix[1][1] || m_matrix[0][0] == -m_matrix[1][1] ) &&
375  m_matrix[1][0] == 0.0 &&
376  m_matrix[0][1] == 0.0
377  );
378 }
379 
380 //! global a2dAffineMatrix to set/pass the identity matrix.
381 A2DARTBASEDLLEXP_DATA( extern a2dAffineMatrix ) a2dIDENTITY_MATRIX;
382 
383 //! function to parse a string in SVG/CVG format and return the resulting matrix
384 /*!
385  \param matrix the resulting matrix.
386  \param str the string to parse
387  \param error error returned if not right
388 
389  \return true if correct string.
390 */
391 extern A2DARTBASEDLLEXP bool ParseCvgTransForm( a2dAffineMatrix& matrix, const wxString& str, wxString& error );
392 
393 //----------------------------------------------------------------------------
394 // a2dMatrixProperty
395 //----------------------------------------------------------------------------
396 
397 
398 //! declarations required for a2dMatrixProperty
399 class A2DARTBASEDLLEXP a2dMatrixProperty;
400 #if defined(WXART2D_USINGDLL)
401 template class A2DARTBASEDLLEXP a2dPropertyIdTyped<a2dAffineMatrix, a2dMatrixProperty>;
402 #endif
403 typedef a2dPropertyIdTyped<a2dAffineMatrix, a2dMatrixProperty> a2dPropertyIdMatrix;
404 
405 
406 //! property to hold a a2dAffineMatrix
407 /*!
408  \ingroup property
409 */
410 class A2DARTBASEDLLEXP a2dMatrixProperty: public a2dNamedProperty
411 {
412 public:
413 
414  a2dMatrixProperty();
415 
416  a2dMatrixProperty( const a2dPropertyIdMatrix* id, const a2dAffineMatrix& value = a2dIDENTITY_MATRIX );
417 
418  a2dMatrixProperty( const a2dMatrixProperty* ori );
419 
420  a2dMatrixProperty( const a2dMatrixProperty& other );
421 
422  virtual ~a2dMatrixProperty();
423 
424  a2dNamedProperty* Clone( a2dObject::CloneOptions options ) const;
425 
426  virtual void Assign( const a2dNamedProperty& other );
427 
428  void SetValue( const a2dAffineMatrix& value );
429 
430  a2dAffineMatrix& GetValue() { return m_value; }
431  const a2dAffineMatrix& GetValue() const { return m_value; }
432 
433  a2dAffineMatrix* GetValuePtr() { return & m_value; }
434 
435  virtual wxString StringRepresentation() const;
436 
437  virtual wxString StringValueRepresentation() const;
438 
439  //! Construct a new property object from a string
440  //! If this is not appropriate, this may return NULL
441  static a2dMatrixProperty* CreatePropertyFromString( const a2dPropertyIdMatrix* id, const wxString& value );
442 
443 #if wxART2D_USE_CVGIO
444  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
445  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
446 #endif //wxART2D_USE_CVGIO
447 
448  DECLARE_DYNAMIC_CLASS( a2dMatrixProperty )
449 
450 protected:
451 
452  a2dAffineMatrix m_value;
453 
454 private:
455  virtual a2dNamedProperty* DoClone( a2dObject::CloneOptions options, a2dRefMap* refs ) const { return NULL; };
456 };
457 
458 //! declarations required for a2dPoint2DProperty
459 class A2DARTBASEDLLEXP a2dPoint2DProperty;
460 #if defined(WXART2D_USINGDLL)
461 template class A2DARTBASEDLLEXP a2dPropertyIdTyped<a2dPoint2D, a2dPoint2DProperty>;
462 #endif
463 typedef a2dPropertyIdTyped<a2dPoint2D, a2dPoint2DProperty> a2dPropertyIdPoint2D;
464 
465 //! property to hold a a2dPoint2D plus an index in e.g a polygon.
466 /*!
467  A wxPoint2d is held within this property, next to that an indedx into an array/list can be set.
468  Also an afterinversion can used by Objects to transform first or not when using a point.
469 
470  This property is used in polygon editing to achieve undo, but you can use it for anything needing a point as property.
471 
472  \ingroup property
473 */
474 class A2DARTBASEDLLEXP a2dPoint2DProperty: public a2dNamedProperty
475 {
476 public:
477 
478  //! constructor
479  a2dPoint2DProperty();
480 
481  //! constructor
482  a2dPoint2DProperty( const a2dPropertyIdPoint2D* id, const a2dPoint2D& value, int index = 0, bool afterinversion = false );
483 
484  //! constructor
485  a2dPoint2DProperty( const a2dPoint2DProperty* ori );
486 
487  //! constructor
488  a2dPoint2DProperty( const a2dPoint2DProperty& other );
489 
490  //! destructor
491  virtual ~a2dPoint2DProperty();
492 
493  //! clone
494  a2dNamedProperty* Clone( a2dObject::CloneOptions options ) const;
495 
496  virtual void Assign( const a2dNamedProperty& other );
497 
498  //! Construct a new property object from a string
499  //! If this is not appropriate, this may return NULL
500  static a2dPoint2DProperty* CreatePropertyFromString( const a2dPropertyIdPoint2D* id, const wxString& value );
501 
502  //! set the property information to this
503  void SetValue( double x, double y, int index = 0, bool afterinversion = false );
504 
505  //! set the property information to this
506  void SetValue( const a2dPoint2D& P, int index = 0, bool afterinversion = false );
507 
508  //! get the point
509  a2dPoint2D& GetValue() { return m_value; }
510  const a2dPoint2D& GetValue() const { return m_value; }
511 
512  //! get the point its address
513  a2dPoint2D* GetValuePtr() { return & m_value; }
514 
515  //! get property setting for m_index
516  wxInt32 GetIndex() { return m_index; }
517 
518  //! get property setting for m_afterinversion
519  bool GetAfterinversion() { return m_afterinversion; }
520 
521  //! a string form presentation for this property
522  virtual wxString StringRepresentation() const;
523 
524  //! a string value presentation for this property
525  virtual wxString StringValueRepresentation() const;
526 
527 #if wxART2D_USE_CVGIO
528  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
529  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
530 #endif //wxART2D_USE_CVGIO
531 
532  DECLARE_DYNAMIC_CLASS( a2dPoint2DProperty )
533 
534 protected:
535 
536  //! the point that is held within this property
537  a2dPoint2D m_value;
538 
539  //! Can be used as position to insert a point into a polygon
540  wxInt32 m_index;
541 
542  //! when adding this point to an object with a matrix, first inverse transform it to the position
543  //! without the matrix.
544  bool m_afterinversion;
545 
546 private:
547  virtual a2dNamedProperty* DoClone( a2dObject::CloneOptions options, a2dRefMap* refs ) const { return NULL; };
548 };
549 
550 #endif
551 
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
(In) Visible property that can be added to Docview Objects.
Definition: gen.h:1785
double m_matrix[3][2]
array store the six double for the affine matrix
Definition: afmatrix.h:335
property to hold a a2dAffineMatrix
Definition: afmatrix.h:410
class to map references to objects stored in XML, in order to make the connection later on...
Definition: gen.h:3462
bool IsIdentity1(void) const
This does an actual check.
Definition: afmatrix.h:347
Ref Counted base object.
Definition: gen.h:1045
a2dPoint2D & GetValue()
get the point
Definition: afmatrix.h:509
static const a2dAffineMatrix & GetIdentityMatrix()
Return a static identity matrix as reference.
Definition: afmatrix.h:141
bool IsIdentity(void) const
Is the matrix the identity matrix?
Definition: afmatrix.h:147
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:819
bool ParseCvgTransForm(a2dAffineMatrix &matrix, const wxString &str, wxString &error)
function to parse a string in SVG/CVG format and return the resulting matrix
Definition: afmatrix.cpp:890
a2dAffineMatrix a2dIDENTITY_MATRIX
global a2dAffineMatrix to set/pass the identity matrix.
Definition: afmatrix.cpp:51
property to hold a a2dPoint2D plus an index in e.g a polygon.
Definition: afmatrix.h:474
bool m_isIdentity
true if identity matrix
Definition: afmatrix.h:338
static const a2dAffineMatrix sm_Identity
A static identity matrix in case an identity matrix is to be returned as reference.
Definition: afmatrix.h:342
classes for initializing the artbase modules, and set paths to be used for fonts etc.
bool IsTranslate(void) const
Is the matrix only a translation?
Definition: afmatrix.h:359
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:862
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
bool GetAfterinversion()
get property setting for m_afterinversion
Definition: afmatrix.h:519
a2dAffineMatrix operator-(const a2dAffineMatrix &a, const a2dAffineMatrix &b)
matrixes subtract
Definition: afmatrix.cpp:741
This template class is for property ids with a known data type.
Definition: id.h:477
a2dPoint2D * GetValuePtr()
get the point its address
Definition: afmatrix.h:513
list of a2dObject&#39;s
Definition: gen.h:3157
CloneOptions
options for cloning
Definition: gen.h:1200
a2dPoint2D GetTranslation() const
get the translation vector as a point
Definition: afmatrix.h:313
wxInt32 GetIndex()
get property setting for m_index
Definition: afmatrix.h:516
afmatrix.h Source File -- Sun Oct 12 2014 17:04:12 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation