00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "a2dprec.h"
00013 #include "wx/general/genmod.h"
00014
00015 #if wxART2D_USE_CVGIO
00016 #include "wx/xmlparse/genxmlpars.h"
00017 #endif //wxART2D_USE_CVGIO
00018
00019 #ifdef __BORLANDC__
00020 #pragma hdrstop
00021 #endif
00022
00023 #ifndef WX_PRECOMP
00024 #include "wx/wx.h"
00025 #endif
00026
00027 #include "wx/artbase/afmatrix.h"
00028 #include <math.h>
00029 #include <ctype.h>
00030
00031 #if defined(__VISUALC__)
00032
00033
00034
00035 #ifdef _MSC_VER
00036 #pragma warning(disable: 4660)
00037 #endif
00038
00039 template a2dPropertyIdTyped<a2dPoint2D, a2dPoint2DProperty>;
00040 template a2dPropertyIdTyped<a2dAffineMatrix, a2dMatrixProperty>;
00041
00042 #ifdef _MSC_VER
00043 #pragma warning(default: 4660)
00044 #endif
00045
00046 #endif
00047
00048 IMPLEMENT_DYNAMIC_CLASS( a2dMatrixProperty, a2dNamedProperty )
00049 IMPLEMENT_DYNAMIC_CLASS( a2dPoint2DProperty, a2dNamedProperty )
00050
00051 a2dAffineMatrix a2dIDENTITY_MATRIX;
00052
00053 a2dAffineMatrix::a2dAffineMatrix( double xt, double yt, double scalex, double scaley, double degrees )
00054 {
00055 if ( degrees )
00056 {
00057 double angle = wxDegToRad( -degrees );
00058 double c = cos( angle );
00059 double s = sin( angle );
00060
00061 m_matrix[0][0] = c * scalex;
00062 m_matrix[1][0] = -s * scaley;
00063 m_matrix[2][0] = xt;
00064 m_matrix[0][1] = s * scalex;
00065 m_matrix[1][1] = c * scaley;
00066 m_matrix[2][1] = yt;
00067
00068 }
00069 else
00070 {
00071 m_matrix[0][0] = scalex;
00072 m_matrix[1][0] = 0;
00073 m_matrix[2][0] = xt;
00074 m_matrix[0][1] = 0;
00075 m_matrix[1][1] = scaley;
00076 m_matrix[2][1] = yt;
00077 }
00078
00079 m_isIdentity = IsIdentity1();
00080 }
00081
00082 a2dAffineMatrix::a2dAffineMatrix( double sx, double shx, double shy, double sy, double tx, double ty )
00083 {
00084 m_matrix[0][0] = sx;
00085 m_matrix[1][0] = shy;
00086 m_matrix[2][0] = tx;
00087 m_matrix[0][1] = shx;
00088 m_matrix[1][1] = sy;
00089 m_matrix[2][1] = ty;
00090 m_isIdentity = IsIdentity1();
00091 }
00092
00093 a2dAffineMatrix::a2dAffineMatrix( void )
00094 {
00095 Identity();
00096 }
00097
00098 a2dAffineMatrix::a2dAffineMatrix( const a2dAffineMatrix& mat )
00099 {
00100 memcpy( m_matrix, mat.m_matrix, 6 * sizeof( double ) );
00101 m_isIdentity = mat.m_isIdentity;
00102
00103
00104 }
00105
00106 double a2dAffineMatrix::GetValue( int col, int row ) const
00107 {
00108 if ( row < 0 || row > 1 || col < 0 || col > 2 )
00109 return 0.0;
00110
00111 return m_matrix[col][row];
00112 }
00113
00114 void a2dAffineMatrix::SetValue( int col, int row, double value )
00115 {
00116 if ( row < 0 || row > 1 || col < 0 || col > 2 )
00117 return;
00118
00119 m_matrix[col][row] = value;
00120 m_isIdentity = IsIdentity1();
00121 }
00122
00123 void a2dAffineMatrix::operator = ( const a2dAffineMatrix& mat )
00124 {
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 memcpy( m_matrix, mat.m_matrix, 6 * sizeof( double ) );
00136
00137 m_isIdentity = mat.m_isIdentity;
00138 }
00139
00140 A2DARTBASEDLLEXP bool operator == ( const a2dAffineMatrix& a, const a2dAffineMatrix& b )
00141 {
00142 if ( a.m_isIdentity && b.m_isIdentity )
00143 return true;
00144
00145 if ( memcmp( a.m_matrix, b.m_matrix, sizeof( a.m_matrix ) ) )
00146 return false;
00147
00148 return true;
00149 }
00150
00151 A2DARTBASEDLLEXP bool operator != ( const a2dAffineMatrix& a, const a2dAffineMatrix& b )
00152 {
00153 return ( ! ( a == b ) );
00154 }
00155
00156
00157 bool a2dAffineMatrix::operator== ( const a2dAffineMatrix& a )
00158 {
00159 if ( m_isIdentity && a.m_isIdentity )
00160 return true;
00161
00162 if ( memcmp( m_matrix, a.m_matrix, sizeof( m_matrix ) ) )
00163 return false;
00164
00165 return true;
00166 }
00167
00168 bool a2dAffineMatrix::operator!= ( const a2dAffineMatrix& a )
00169 {
00170 return ( ! ( *this == a ) );
00171 }
00172
00173
00174 double& a2dAffineMatrix::operator()( int col, int row )
00175 {
00176 if ( row < 0 || row > 1 || col < 0 || col > 2 )
00177 return m_matrix[0][0];
00178
00179 return m_matrix[col][row];
00180 }
00181
00182 double a2dAffineMatrix::operator()( int col, int row ) const
00183 {
00184 if ( row < 0 || row > 1 || col < 0 || col > 2 )
00185 return 0.0;
00186
00187 return m_matrix[col][row];
00188 }
00189
00190
00191 inline double wxCalculateDet( double a11, double a21, double a12, double a22 )
00192 {
00193 return a11 * a22 - a12 * a21;
00194 }
00195
00196
00197 bool a2dAffineMatrix::Invert( void )
00198 {
00199 if ( m_isIdentity )
00200 return true;
00201
00202 double inverseMatrix[3][2];
00203 double det = m_matrix[0][0] * m_matrix[1][1] - m_matrix[0][1] * m_matrix[1][0];
00204
00205 if( det )
00206 {
00207
00208 inverseMatrix[0][0] = m_matrix[1][1];
00209 inverseMatrix[0][1] = -m_matrix[0][1];
00210
00211
00212 inverseMatrix[1][0] = -m_matrix[1][0];
00213 inverseMatrix[1][1] = m_matrix[0][0];
00214
00215 inverseMatrix[2][0] = m_matrix[1][0] * m_matrix[2][1] - m_matrix[2][0] * m_matrix[1][1];
00216 inverseMatrix[2][1] = -( m_matrix[0][0] * m_matrix[2][1] - m_matrix[2][0] * m_matrix[0][1] );
00217
00218 inverseMatrix[0][0] /= det; inverseMatrix[1][0] /= det; inverseMatrix[2][0] /= det;
00219 inverseMatrix[0][1] /= det; inverseMatrix[1][1] /= det; inverseMatrix[2][1] /= det;
00220
00221 int i, j;
00222 for ( i = 0; i < 3; i++ )
00223 {
00224 for ( j = 0; j < 2; j++ )
00225 {
00226 m_matrix[i][j] = inverseMatrix[i][j];
00227 }
00228 }
00229
00230 m_isIdentity = IsIdentity1();
00231 return true;
00232 }
00233 else if( m_matrix[0][0] && !m_matrix[1][0] && !m_matrix[0][1] && !m_matrix[1][1] )
00234 {
00235
00236 m_matrix[0][0] = 1 / m_matrix[0][0];
00237 m_matrix[2][0] = -m_matrix[0][0] * m_matrix[2][0];
00238 m_matrix[2][1] = -m_matrix[2][1];
00239 return true;
00240 }
00241 else if( !m_matrix[0][0] && !m_matrix[1][0] && !m_matrix[0][1] && m_matrix[1][1] )
00242 {
00243
00244 m_matrix[1][1] = 1 / m_matrix[1][1];
00245 m_matrix[2][1] = -m_matrix[1][1] * m_matrix[2][1];
00246 m_matrix[2][0] = -m_matrix[2][0];
00247 return true;
00248 }
00249 else
00250 {
00251 return false;
00252 }
00253 }
00254
00255
00256 bool a2dAffineMatrix::Identity( void )
00257 {
00258 m_matrix[0][0] = m_matrix[1][1] = 1.0;
00259 m_matrix[1][0] = m_matrix[2][0] = m_matrix[0][1] = m_matrix[2][1] = 0.0;
00260 m_isIdentity = true;
00261
00262 return true;
00263 }
00264
00265
00266
00267
00268
00269
00270 bool a2dAffineMatrix::Scale( double scale )
00271 {
00272 int i, j;
00273 for ( i = 0; i < 3; i++ )
00274 {
00275 for ( j = 0; j < 2; j++ )
00276 {
00277 m_matrix[i][j] *= scale;
00278 }
00279 }
00280 m_isIdentity = IsIdentity1();
00281
00282 return true;
00283 }
00284
00285
00286
00287
00288
00289
00290 bool a2dAffineMatrix::RemoveScale()
00291 {
00292 if ( m_isIdentity )
00293 return true;
00294 double scale = sqrt( fabs( m_matrix[0][0] * m_matrix[1][1] - m_matrix[0][1] * m_matrix[1][0] ) );
00295 if( scale )
00296 {
00297 int i, j;
00298 for ( i = 0; i < 2; i++ )
00299 {
00300 for ( j = 0; j < 2; j++ )
00301 {
00302 m_matrix[i][j] /= scale;
00303 }
00304 }
00305 for ( j = 0; j < 2; j++ )
00306 {
00307 double scaleJ = sqrt( m_matrix[0][j] * m_matrix[0][j] + m_matrix[1][j] * m_matrix[1][j] );
00308 wxASSERT_MSG( scaleJ != 0, wxT( "matrix scaleJ == 0 !" ) );
00309 m_matrix[0][j] /= scaleJ;
00310 m_matrix[1][j] /= scaleJ;
00311 }
00312 m_isIdentity = IsIdentity1();
00313
00314 return true;
00315 }
00316 wxASSERT_MSG( scale != 0, wxT( "matrix determinant == 0 !" ) );
00317 return false;
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327 a2dAffineMatrix& a2dAffineMatrix::Scale( const double &xs, const double &ys, const double &xc, const double &yc )
00328 {
00329 double r00, r10, r20, r01, r11, r21;
00330
00331 if ( m_isIdentity )
00332 {
00333 double tx = xc * ( 1 - xs );
00334 double ty = yc * ( 1 - ys );
00335 r00 = xs;
00336 r10 = 0;
00337 r20 = tx;
00338 r01 = 0;
00339 r11 = ys;
00340 r21 = ty;
00341 }
00342 else if ( xc != 0 || yc != 0 )
00343 {
00344 double tx = xc * ( 1 - xs );
00345 double ty = yc * ( 1 - ys );
00346 r00 = xs * m_matrix[0][0];
00347 r10 = xs * m_matrix[1][0];
00348 r20 = xs * m_matrix[2][0] + tx;
00349 r01 = ys * m_matrix[0][1];
00350 r11 = ys * m_matrix[1][1];
00351 r21 = ys * m_matrix[2][1] + ty;
00352 }
00353 else
00354 {
00355 r00 = xs * m_matrix[0][0];
00356 r10 = xs * m_matrix[1][0];
00357 r20 = xs * m_matrix[2][0];
00358 r01 = ys * m_matrix[0][1];
00359 r11 = ys * m_matrix[1][1];
00360 r21 = ys * m_matrix[2][1];
00361 }
00362
00363 m_matrix[0][0] = r00;
00364 m_matrix[1][0] = r10;
00365 m_matrix[2][0] = r20;
00366 m_matrix[0][1] = r01;
00367 m_matrix[1][1] = r11;
00368 m_matrix[2][1] = r21;
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 m_isIdentity = IsIdentity1();
00387
00388 return *this;
00389 }
00390
00391
00392
00393
00394
00395
00396 a2dAffineMatrix& a2dAffineMatrix::Mirror( bool y, bool x )
00397 {
00398 a2dAffineMatrix temp;
00399 if ( x )
00400 {
00401 temp.m_matrix[0][0] = -1;
00402 temp.m_isIdentity = false;
00403 }
00404 if ( y )
00405 {
00406 temp.m_matrix[1][1] = -1;
00407 temp.m_isIdentity = false;
00408 }
00409
00410 *this = temp * ( *this );
00411 m_isIdentity = IsIdentity1();
00412 return *this;
00413 }
00414
00415
00416
00417
00418
00419
00420 bool a2dAffineMatrix::Translate( double dx, double dy )
00421 {
00422 m_matrix[2][0] += dx;
00423 m_matrix[2][1] += dy;
00424 m_isIdentity = IsIdentity1();
00425 return true;
00426 }
00427
00428
00429
00430
00431
00432 bool a2dAffineMatrix::Rotate( double degrees )
00433 {
00434 if ( degrees == 0 )
00435 return true;
00436
00437 Rotate( -degrees, 0, 0 );
00438 return true;
00439 }
00440
00441 bool a2dAffineMatrix::SkewX( double degrees )
00442 {
00443 if ( degrees == 0 )
00444 return true;
00445
00446 double angle = degrees * wxPI / 180.0;
00447 double t = tan( angle );
00448
00449 a2dAffineMatrix skew;
00450
00451 skew.m_matrix[1][0] = t;
00452 skew.m_isIdentity = false;
00453
00454 *this = skew * ( *this );
00455
00456 m_isIdentity = IsIdentity1();
00457 return true;
00458 }
00459
00460 bool a2dAffineMatrix::SkewY( double degrees )
00461 {
00462 if ( degrees == 0 )
00463 return true;
00464
00465 double angle = degrees * wxPI / 180.0;
00466 double t = tan( angle );
00467
00468 a2dAffineMatrix skew;
00469
00470 skew.m_matrix[0][1] = t;
00471 skew.m_isIdentity = false;
00472
00473 *this = skew * ( *this );
00474
00475 m_isIdentity = IsIdentity1();
00476 return true;
00477 }
00478
00479
00480
00481
00482
00483
00484 a2dAffineMatrix& a2dAffineMatrix::Rotate( const double °rees, const double &x, const double &y )
00485 {
00486 if ( degrees == 0 )
00487 return * this;
00488
00489 double angle = wxDegToRad( degrees );
00490 double c = cos( angle );
00491 double s = sin( angle );
00492 double r00, r10, r20, r01, r11, r21;
00493
00494 if ( m_isIdentity )
00495 {
00496 double tx = x * ( 1 - c ) + y * s;
00497 double ty = y * ( 1 - c ) - x * s;
00498 r00 = c ;
00499 r10 = -s;
00500 r20 = tx;
00501 r01 = s;
00502 r11 = c;
00503 r21 = ty;
00504 }
00505 else if ( x != 0 || y != 0 )
00506 {
00507 double tx = x * ( 1 - c ) + y * s;
00508 double ty = y * ( 1 - c ) - x * s;
00509 r00 = c * m_matrix[0][0] - s * m_matrix[0][1];
00510 r10 = c * m_matrix[1][0] - s * m_matrix[1][1];
00511 r20 = c * m_matrix[2][0] - s * m_matrix[2][1] + tx;
00512 r01 = c * m_matrix[0][1] + s * m_matrix[0][0];
00513 r11 = c * m_matrix[1][1] + s * m_matrix[1][0];
00514 r21 = c * m_matrix[2][1] + s * m_matrix[2][0] + ty;
00515 }
00516 else
00517 {
00518 r00 = c * m_matrix[0][0] - s * m_matrix[0][1];
00519 r10 = c * m_matrix[1][0] - s * m_matrix[1][1];
00520 r20 = c * m_matrix[2][0] - s * m_matrix[2][1];
00521 r01 = c * m_matrix[0][1] + s * m_matrix[0][0];
00522 r11 = c * m_matrix[1][1] + s * m_matrix[1][0];
00523 r21 = c * m_matrix[2][1] + s * m_matrix[2][0];
00524 }
00525
00526 m_matrix[0][0] = r00;
00527 m_matrix[1][0] = r10;
00528 m_matrix[2][0] = r20;
00529 m_matrix[0][1] = r01;
00530 m_matrix[1][1] = r11;
00531 m_matrix[2][1] = r21;
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 m_isIdentity = IsIdentity1();
00554
00555 return *this;
00556 }
00557
00558
00559 void a2dAffineMatrix::TransformPoint( double x, double y, double& tx, double& ty ) const
00560 {
00561 if ( m_isIdentity )
00562 {
00563 tx = x; ty = y; return;
00564 }
00565
00566 tx = x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0];
00567 ty = x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1];
00568 }
00569
00570
00571 void a2dAffineMatrix::TransformPoint( double& tx, double& ty ) const
00572 {
00573 if ( m_isIdentity )
00574 return;
00575
00576 tx = tx * m_matrix[0][0] + ty * m_matrix[1][0] + m_matrix[2][0];
00577 ty = tx * m_matrix[0][1] + ty * m_matrix[1][1] + m_matrix[2][1];
00578 }
00579
00580 void a2dAffineMatrix::TransformPoint( a2dPoint2D *point ) const
00581 {
00582 if ( m_isIdentity )
00583 return;
00584
00585 double x = point->m_x * m_matrix[0][0] + point->m_y * m_matrix[1][0] + m_matrix[2][0];
00586 point->m_y = point->m_x * m_matrix[0][1] + point->m_y * m_matrix[1][1] + m_matrix[2][1];
00587 point->m_x = x;
00588 }
00589
00590 void a2dAffineMatrix::TransformPoint( const a2dPoint2D& src, a2dPoint2D *dest ) const
00591 {
00592 if ( m_isIdentity )
00593 {
00594 *dest = src;
00595 return;
00596 }
00597
00598 dest->m_x = src.m_x * m_matrix[0][0] + src.m_y * m_matrix[1][0] + m_matrix[2][0];
00599 dest->m_y = src.m_x * m_matrix[0][1] + src.m_y * m_matrix[1][1] + m_matrix[2][1];
00600 }
00601
00602 void a2dAffineMatrix::TransformVector( double dx, double dy, double &tdx, double &tdy ) const
00603 {
00604 if ( m_isIdentity )
00605 {
00606 tdx = dx; tdy = dy; return;
00607 }
00608
00609
00610
00611
00612 tdx = dx * m_matrix[0][0] + dy * m_matrix[1][0];
00613 tdy = dx * m_matrix[0][1] + dy * m_matrix[1][1];
00614 }
00615
00616 double a2dAffineMatrix::TransformDistance( double distance ) const
00617 {
00618 if ( m_isIdentity )
00619 return distance;
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 return wxMin( sqrt( m_matrix[0][0] * m_matrix[0][0] + m_matrix[0][1] * m_matrix[0][1] ) * distance,
00633 sqrt( m_matrix[1][0] * m_matrix[1][0] + m_matrix[1][1] * m_matrix[1][1] ) * distance );
00634 }
00635
00636 void a2dAffineMatrix::TransformDistance( double& dx, double& dy ) const
00637 {
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 double xt = dx * m_matrix[0][0] + dy * m_matrix[1][0];
00650 double yt = dx * m_matrix[0][1] + dy * m_matrix[1][1];
00651 dx = xt;
00652 dy = yt;
00653 }
00654
00655 a2dAffineMatrix& a2dAffineMatrix::operator*=( const a2dAffineMatrix& mat )
00656 {
00657 if ( mat.m_isIdentity )
00658 return * this;
00659 if ( m_isIdentity )
00660 {
00661 *this = mat;
00662 return *this;
00663 }
00664 else
00665 {
00666 a2dAffineMatrix result;
00667 for ( int i = 0; i < 2; i++ )
00668 {
00669 double sum;
00670
00671 sum = m_matrix[0][i] * mat.m_matrix[0][0];
00672 sum += m_matrix[1][i] * mat.m_matrix[0][1];
00673 result.m_matrix[0][i] = sum;
00674
00675 sum = m_matrix[0][i] * mat.m_matrix[1][0];
00676 sum += m_matrix[1][i] * mat.m_matrix[1][1];
00677 result.m_matrix[1][i] = sum;
00678
00679 sum = m_matrix[0][i] * mat.m_matrix[2][0];
00680 sum += m_matrix[1][i] * mat.m_matrix[2][1];
00681 sum += m_matrix[2][i];
00682 result.m_matrix[2][i] = sum;
00683 }
00684 *this = result;
00685 }
00686
00687 m_isIdentity = IsIdentity1();
00688 return *this;
00689
00690 }
00691
00692 a2dAffineMatrix a2dAffineMatrix::operator*( const a2dAffineMatrix& mat ) const
00693 {
00694 if ( mat.m_isIdentity )
00695 return * this;
00696 if ( m_isIdentity )
00697 {
00698 return mat;
00699 }
00700 else
00701 {
00702 a2dAffineMatrix result;
00703 for ( int i = 0; i < 2; i++ )
00704 {
00705 double sum;
00706
00707 sum = m_matrix[0][i] * mat.m_matrix[0][0];
00708 sum += m_matrix[1][i] * mat.m_matrix[0][1];
00709 result.m_matrix[0][i] = sum;
00710
00711 sum = m_matrix[0][i] * mat.m_matrix[1][0];
00712 sum += m_matrix[1][i] * mat.m_matrix[1][1];
00713 result.m_matrix[1][i] = sum;
00714
00715 sum = m_matrix[0][i] * mat.m_matrix[2][0];
00716 sum += m_matrix[1][i] * mat.m_matrix[2][1];
00717 sum += m_matrix[2][i];
00718 result.m_matrix[2][i] = sum;
00719 }
00720 result.m_isIdentity = result.IsIdentity1();
00721 return result;
00722 }
00723 }
00724
00725
00726 a2dAffineMatrix a2dAffineMatrix::operator-( const a2dAffineMatrix& b )
00727 {
00728 a2dAffineMatrix
00729 ret;
00730 ret.m_matrix[0][0] = m_matrix[0][0] - b.m_matrix[0][0];
00731 ret.m_matrix[0][1] = m_matrix[0][1] - b.m_matrix[0][1];
00732 ret.m_matrix[1][0] = m_matrix[1][0] - b.m_matrix[1][0];
00733 ret.m_matrix[1][1] = m_matrix[1][1] - b.m_matrix[1][1];
00734 ret.m_matrix[2][0] = m_matrix[2][0] - b.m_matrix[2][0];
00735 ret.m_matrix[2][1] = m_matrix[2][1] - b.m_matrix[2][1];
00736
00737 return ret;
00738 }
00739
00740
00741 A2DARTBASEDLLEXP a2dAffineMatrix operator-( const a2dAffineMatrix& a, const a2dAffineMatrix& b )
00742 {
00743 a2dAffineMatrix
00744 ret;
00745 ret.m_matrix[0][0] = a.m_matrix[0][0] - b.m_matrix[0][0];
00746 ret.m_matrix[0][1] = a.m_matrix[0][1] - b.m_matrix[0][1];
00747 ret.m_matrix[1][0] = a.m_matrix[1][0] - b.m_matrix[1][0];
00748 ret.m_matrix[1][1] = a.m_matrix[1][1] - b.m_matrix[1][1];
00749 ret.m_matrix[2][0] = a.m_matrix[2][0] - b.m_matrix[2][0];
00750 ret.m_matrix[2][1] = a.m_matrix[2][1] - b.m_matrix[2][1];
00751
00752 return ret;
00753 }
00754
00755 double a2dAffineMatrix::Get_scaleX() const
00756 {
00757 if ( IsIdentity() )
00758 return 1;
00759
00760 double rot_angle = atan2( m_matrix[0][1], m_matrix[0][0] ) * 180 / wxPI;
00761 a2dAffineMatrix inverse;
00762 inverse.Rotate( -rot_angle, m_matrix[2][0], m_matrix[2][1] );
00763
00764 a2dAffineMatrix h = *this;
00765 h *= inverse;
00766
00767
00768 double scale_factor;
00769 scale_factor = h.GetValue( 0, 0 );
00770
00771 if ( scale_factor < 0 )
00772 scale_factor = -scale_factor;
00773
00774 return scale_factor;
00775 }
00776
00777 double a2dAffineMatrix::Get_scaleY() const
00778 {
00779 if ( IsIdentity() )
00780 return 1;
00781
00782 double rot_angle = atan2( m_matrix[0][1], m_matrix[0][0] ) * 180 / wxPI;
00783 a2dAffineMatrix inverse;
00784 inverse.Rotate( -rot_angle, m_matrix[2][0], m_matrix[2][1] );
00785
00786 a2dAffineMatrix h = *this;
00787 h *= inverse;
00788
00789
00790 double scale_factor;
00791 scale_factor = h.GetValue( 1, 1 );
00792
00793 if ( scale_factor < 0 )
00794 scale_factor = -scale_factor;
00795
00796 return scale_factor;
00797 }
00798
00799 double a2dAffineMatrix::GetRotation() const
00800 {
00801 if ( IsIdentity() )
00802 return 0.0;
00803
00804 double temp1 = m_matrix[0][0];
00805 double temp2 = m_matrix[0][1];
00806
00807
00808 double rot_angle = atan2( temp2, temp1 ) * 180 / wxPI;
00809 if ( rot_angle == -180.0 )
00810 rot_angle = 180.0;
00811
00812 return rot_angle;
00813 }
00814
00815 void a2dAffineMatrix::SetRotation( double rotation )
00816 {
00817 double x = m_matrix[2][0];
00818 double y = m_matrix[2][1];
00819 if ( !IsIdentity() )
00820 Rotate( -GetRotation(), x, y );
00821
00822 Rotate( rotation, x, y );
00823 }
00824
00825 double a2dAffineMatrix::GetDeterminant() const
00826 {
00827 return m_matrix[0][0] * m_matrix[1][1] - m_matrix[1][0] * m_matrix[0][1];
00828 }
00829
00830 double a2dAffineMatrix::GetDeterminant1() const
00831 {
00832 return m_matrix[2][0] * m_matrix[1][1] - m_matrix[1][0] * m_matrix[2][1];
00833 }
00834
00835 double a2dAffineMatrix::GetDeterminant2() const
00836 {
00837 return m_matrix[0][0] * m_matrix[2][1] - m_matrix[2][0] * m_matrix[0][1];
00838 }
00839
00840 double a2dAffineMatrix::GetMaximum() const
00841 {
00842 return
00843 wxMax(
00844 wxMax( fabs( m_matrix[0][0] ), fabs( m_matrix[1][1] ) ),
00845 wxMax( fabs( m_matrix[1][0] ), fabs( m_matrix[0][1] ) )
00846 );
00847 }
00848
00849 double a2dAffineMatrix::GetMaximum1() const
00850 {
00851 return
00852 wxMax(
00853 wxMax( fabs( m_matrix[2][0] ), fabs( m_matrix[1][1] ) ),
00854 wxMax( fabs( m_matrix[1][0] ), fabs( m_matrix[2][1] ) )
00855 );
00856 }
00857
00858 double a2dAffineMatrix::GetMaximum2() const
00859 {
00860 return
00861 wxMax(
00862 wxMax( fabs( m_matrix[0][0] ), fabs( m_matrix[2][1] ) ),
00863 wxMax( fabs( m_matrix[2][0] ), fabs( m_matrix[0][1] ) )
00864 );
00865 }
00866
00867 void a2dAffineMatrix::DebugDump( const wxChar* text, double w, double h ) const
00868 {
00869 wxLogDebug( text );
00870 wxLogDebug( wxT( "a00=%12.6lf, a01=%12.6lf" ), m_matrix[0][0], m_matrix[0][1] );
00871 wxLogDebug( wxT( "a10=%12.6lf, a11=%12.6lf" ), m_matrix[1][0], m_matrix[1][1] );
00872 wxLogDebug( wxT( "a20=%12.6lf. a21=%12.6lf" ), m_matrix[2][0], m_matrix[2][1] );
00873 wxLogDebug( wxT( "w =%12.6lf, h =%12.6lf" ), w, h );
00874 wxLogDebug( wxT( "cx =%12.6lf, cy =%12.6lf" ),
00875 0.5 * ( m_matrix[0][0] * w + m_matrix[1][0] * h ) + m_matrix[2][0],
00876 0.5 * ( m_matrix[0][1] * w + m_matrix[1][1] * h ) + m_matrix[2][1]
00877 );
00878 wxLogDebug( wxT( "lx =%12.6lf, ly =%12.6lf" ),
00879 w * sqrt( m_matrix[0][0] * m_matrix[0][0] + m_matrix[0][1] * m_matrix[0][1] ),
00880 h * sqrt( m_matrix[1][0] * m_matrix[1][0] + m_matrix[1][1] * m_matrix[1][1] )
00881 );
00882 wxLogDebug( wxT( "\n" ) );
00883 }
00884
00885
00886 const a2dAffineMatrix a2dAffineMatrix::sm_Identity;
00887
00888
00889
00890 A2DARTBASEDLLEXP bool ParseCvgTransForm( a2dAffineMatrix& matrix, const wxString& str, wxString& error )
00891 {
00892 if ( str == wxT( "" ) )
00893 return false;
00894
00895 wxString numstr;
00896 double matrixcoef[6];
00897 int nr_matrixcoef;
00898
00899 wxString keywstr;
00900 size_t i;
00901 for ( i = 0; i < str.Len(); i++ )
00902 {
00903
00904 while ( wxIsspace( str[i] ) ) i++;
00905
00906 nr_matrixcoef = 0;
00907 keywstr.Clear();
00908
00909 while ( i < str.Len() && isalpha ( str[i] ) )
00910 {
00911 keywstr += str.GetChar( i );
00912 i++;
00913 }
00914
00915
00916 while ( wxIsspace( str[i] ) ) i++;
00917
00918 if ( str[i] != wxT( '(' ) )
00919 {
00920 error = _( "CVG parsing error: missing" );
00921 return false;
00922 }
00923 i++;
00924
00925 while ( wxIsspace( str[i] ) ) i++;
00926
00927 while ( i < str.Len() && str[i] != wxT( ')' ) )
00928 {
00929 numstr.Clear();
00930 while ( i < str.Len() && ( isdigit( str[i] ) || str[i] == wxT( '+' ) || str[i] == wxT( '-' ) || str[i] == wxT( '.' ) || str[i] == wxT( 'e' ) || str[i] == wxT( 'E' ) ) )
00931 {
00932 numstr += str.GetChar( i );
00933 i++;
00934 }
00935 numstr.ToDouble( &matrixcoef[nr_matrixcoef] );
00936 nr_matrixcoef++;
00937 while ( i < str.Len() && ( wxIsspace( str[i] ) || str[i] == wxT( ',' ) ) ) i++;
00938 }
00939
00940 if ( str[i] != wxT( ')' ) )
00941 {
00942 error = _( "CVG parsing error: missing" );
00943 return false;
00944 }
00945 i++;
00946
00947 if ( keywstr == wxT( "matrix" ) )
00948 {
00949 if ( nr_matrixcoef != 6 )
00950 {
00951 error.Printf( _( "CVG : wrong number of arguments %s " ), keywstr.c_str() );
00952 return false;
00953 }
00954 matrix.SetValue( 0, 0, matrixcoef[0] );
00955 matrix.SetValue( 0, 1, matrixcoef[1] );
00956 matrix.SetValue( 1, 0, matrixcoef[2] );
00957 matrix.SetValue( 1, 1, matrixcoef[3] );
00958 matrix.SetValue( 2, 0, matrixcoef[4] );
00959 matrix.SetValue( 2, 1, matrixcoef[5] );
00960 }
00961 else if ( keywstr == wxT( "translate" ) )
00962 {
00963 if ( nr_matrixcoef == 1 )
00964 matrix.Translate( matrixcoef[0] , 0 );
00965 else if ( nr_matrixcoef != 2 )
00966 {
00967 error.Printf( _( "CVG : wrong number of arguments %s " ), keywstr.c_str() );
00968 return false;
00969 }
00970 else
00971 matrix.Translate( matrixcoef[0] , matrixcoef[1] );
00972 }
00973 else if ( keywstr == wxT( "scale" ) )
00974 {
00975 if ( nr_matrixcoef == 1 )
00976 matrix.Scale( matrixcoef[0], 1.0, matrix.GetValue( 2, 0 ), matrix.GetValue( 2, 1 ) );
00977 else if ( nr_matrixcoef != 2 )
00978 {
00979 error.Printf( _( "CVG : wrong number of arguments %s " ), keywstr.c_str() );
00980 return false;
00981 }
00982 else
00983 matrix.Scale( matrixcoef[0], matrixcoef[1], matrix.GetValue( 2, 0 ), matrix.GetValue( 2, 1 ) );
00984 }
00985 else if ( keywstr == wxT( "rotate" ) )
00986 {
00987 if ( nr_matrixcoef != 1 )
00988 {
00989 error.Printf( _( "CVG : wrong number of arguments %s " ), keywstr.c_str() );
00990 return false;
00991 }
00992 matrix.Rotate( matrixcoef[0] );
00993 }
00994 else if ( keywstr == wxT( "skewX" ) )
00995 {
00996 if ( nr_matrixcoef != 1 )
00997 {
00998 error.Printf( _( "CVG : wrong number of arguments %s " ), keywstr.c_str() );
00999 return false;
01000 }
01001 matrix.SkewX( matrixcoef[0] );
01002 }
01003 else if ( keywstr == wxT( "skewY" ) )
01004 {
01005 if ( nr_matrixcoef != 1 )
01006 {
01007 error.Printf( _( "CVG : wrong number of arguments %s " ), keywstr.c_str() );
01008 return false;
01009 }
01010 matrix.SkewY( matrixcoef[0] );
01011 }
01012 else if ( keywstr == wxT( "flipX" ) )
01013 {
01014 if ( nr_matrixcoef != 0 )
01015 {
01016 error.Printf( _( "CVG : wrong number of arguments %s " ), keywstr.c_str() );
01017 return false;
01018 }
01019 matrix.Mirror( true, false );
01020 }
01021 else if ( keywstr == wxT( "flipY" ) )
01022 {
01023 if ( nr_matrixcoef != 0 )
01024 {
01025 error.Printf( _( "CVG : wrong number of arguments %s " ), keywstr.c_str() );
01026 return false;
01027 }
01028 matrix.Mirror( false, true );
01029 }
01030 else
01031 {
01032 error.Printf( _( "CVG : invalid transform %s " ), keywstr.c_str() );
01033 return false;
01034 }
01035 }
01036 return true;
01037 }
01038
01039
01040
01041
01042
01043 a2dMatrixProperty::a2dMatrixProperty(): a2dNamedProperty()
01044 {}
01045
01046 a2dMatrixProperty::a2dMatrixProperty( const a2dPropertyIdMatrix* id, const a2dAffineMatrix& value )
01047 : a2dNamedProperty( id )
01048 {
01049 m_value = value;
01050 }
01051
01052 a2dMatrixProperty::a2dMatrixProperty( const a2dMatrixProperty* ori )
01053 : a2dNamedProperty( *ori )
01054 {
01055 m_value = ori->m_value;
01056 }
01057
01058 a2dMatrixProperty::~a2dMatrixProperty()
01059 {}
01060
01061 a2dMatrixProperty::a2dMatrixProperty( const a2dMatrixProperty &other )
01062 : a2dNamedProperty( other )
01063 {
01064 m_value = other.m_value;
01065 }
01066
01067 a2dNamedProperty* a2dMatrixProperty::Clone( a2dObject::CloneOptions WXUNUSED( options ) ) const
01068 {
01069 return new a2dMatrixProperty( *this );
01070 };
01071
01072 void a2dMatrixProperty::Assign( const a2dNamedProperty &other )
01073 {
01074 a2dMatrixProperty * propcast = wxStaticCast( &other, a2dMatrixProperty );
01075 m_value = propcast->m_value;
01076 }
01077
01078 #if wxART2D_USE_CVGIO
01079 void a2dMatrixProperty::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
01080 {
01081 a2dNamedProperty::DoSave( parent, out, xmlparts, towrite );
01082 if ( xmlparts == a2dXmlSer_attrib )
01083 {
01084 wxString s;
01085 s.Printf ( _T( "matrix( %g %g %g %g %g %g )" ),
01086 m_value.GetValue( 0, 0 ), m_value.GetValue( 0, 1 ),
01087 m_value.GetValue( 1, 0 ), m_value.GetValue( 1, 1 ),
01088 m_value.GetValue( 2, 0 ), m_value.GetValue( 2, 1 )
01089 );
01090 out.WriteAttribute( wxT( "transform" ), s );
01091 }
01092 else
01093 {}
01094 }
01095
01096 void a2dMatrixProperty::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
01097 {
01098 a2dNamedProperty::DoLoad( parent, parser, xmlparts );
01099 if ( xmlparts == a2dXmlSer_attrib )
01100 {
01101 wxString str = parser.GetAttributeValue( wxT( "transform" ) );
01102 wxString error;
01103 if ( !str.IsEmpty() && !::ParseCvgTransForm( m_value, str, error ) )
01104 {
01105 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "CVG : invalid transform %s at line %d" ), str.c_str(), parser.GetCurrentLineNumber() );
01106 }
01107 }
01108 else
01109 {}
01110 }
01111 #endif //wxART2D_USE_CVGIO
01112
01113 void a2dMatrixProperty::SetValue( const a2dAffineMatrix& value )
01114 {
01115 m_value = value;
01116 }
01117
01118 wxString a2dMatrixProperty::StringRepresentation() const
01119 {
01120 wxString s;
01121 s.Printf ( wxT( "%s = matrix( %g %g %g %g %g %g )" ), m_id->GetName().c_str(),
01122 m_value.GetValue( 0, 0 ), m_value.GetValue( 0, 1 ),
01123 m_value.GetValue( 1, 0 ), m_value.GetValue( 1, 1 ),
01124 m_value.GetValue( 2, 0 ), m_value.GetValue( 2, 1 )
01125 );
01126
01127 return s;
01128 }
01129
01130 wxString a2dMatrixProperty::StringValueRepresentation() const
01131 {
01132 wxString s;
01133 s.Printf ( _T( "matrix( %g %g %g %g %g %g )" ),
01134 m_value.GetValue( 0, 0 ), m_value.GetValue( 0, 1 ),
01135 m_value.GetValue( 1, 0 ), m_value.GetValue( 1, 1 ),
01136 m_value.GetValue( 2, 0 ), m_value.GetValue( 2, 1 )
01137 );
01138
01139 return s;
01140 }
01141
01142 a2dMatrixProperty *a2dMatrixProperty::CreatePropertyFromString( const a2dPropertyIdMatrix* id, const wxString &value )
01143 {
01144 wxString error;
01145 a2dAffineMatrix result;
01146 if ( ::ParseCvgTransForm( result, value , error ) )
01147 return new a2dMatrixProperty( id, result );
01148 else
01149 return 0;
01150 }
01151
01152
01153
01154
01155
01156 a2dPoint2DProperty::a2dPoint2DProperty(): a2dNamedProperty()
01157 {}
01158
01159 a2dPoint2DProperty::a2dPoint2DProperty( const a2dPropertyIdPoint2D* id, const a2dPoint2D& value, int index, bool afterinversion )
01160 : a2dNamedProperty( id )
01161 {
01162 m_value = value;
01163 m_index = index;
01164 m_afterinversion = afterinversion;
01165 }
01166
01167 a2dPoint2DProperty::a2dPoint2DProperty( const a2dPoint2DProperty* ori )
01168 : a2dNamedProperty( *ori )
01169 {
01170 m_value = ori->m_value;
01171 m_index = ori->m_index;
01172 m_afterinversion = ori->m_afterinversion;
01173 }
01174
01175 a2dPoint2DProperty::~a2dPoint2DProperty()
01176 {}
01177
01178 a2dPoint2DProperty::a2dPoint2DProperty( const a2dPoint2DProperty &other )
01179 : a2dNamedProperty( other )
01180 {
01181 m_value = other.m_value;
01182 m_index = other.m_index;
01183 m_afterinversion = other.m_afterinversion;
01184 }
01185
01186 a2dNamedProperty* a2dPoint2DProperty::Clone( a2dObject::CloneOptions WXUNUSED( options ) ) const
01187 {
01188 return new a2dPoint2DProperty( *this );
01189 };
01190
01191 void a2dPoint2DProperty::Assign( const a2dNamedProperty &other )
01192 {
01193 a2dPoint2DProperty * propcast = wxStaticCast( &other, a2dPoint2DProperty );
01194 m_value = propcast->m_value;
01195 m_index = propcast->m_index;
01196 m_afterinversion = propcast->m_afterinversion;
01197 }
01198
01199 a2dPoint2DProperty *a2dPoint2DProperty::CreatePropertyFromString( const a2dPropertyIdPoint2D* WXUNUSED( id ), const wxString& WXUNUSED( value ) )
01200 {
01201 return 0;
01202 }
01203
01204 #if wxART2D_USE_CVGIO
01205 void a2dPoint2DProperty::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
01206 {
01207 a2dNamedProperty::DoSave( parent, out, xmlparts, towrite );
01208 if ( xmlparts == a2dXmlSer_attrib )
01209 {
01210 out.WriteAttribute( wxT( "point2d" ), StringValueRepresentation() );
01211 }
01212 else
01213 {}
01214 }
01215
01216 void a2dPoint2DProperty::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
01217 {
01218 a2dNamedProperty::DoLoad( parent, parser, xmlparts );
01219 if ( xmlparts == a2dXmlSer_attrib )
01220 {
01221 wxString str = parser.GetAttributeValue( wxT( "point2d" ) );
01222 wxString error;
01223 if ( !str.IsEmpty() )
01224 {
01225 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "CVG : invalid point2d %s at line %d" ), str.c_str(), parser.GetCurrentLineNumber() );
01226 }
01227 }
01228 else
01229 {}
01230 }
01231 #endif //wxART2D_USE_CVGIO
01232
01233 void a2dPoint2DProperty::SetValue( double x, double y, int index, bool afterinversion )
01234 {
01235 m_value.m_x = x;
01236 m_value.m_y = y;
01237 m_index = index;
01238 m_afterinversion = afterinversion;
01239 }
01240
01241 void a2dPoint2DProperty::SetValue( const a2dPoint2D& P, int index, bool afterinversion )
01242 {
01243 m_value = P;
01244 m_index = index;
01245 m_afterinversion = afterinversion;
01246 }
01247
01248 wxString a2dPoint2DProperty::StringRepresentation() const
01249 {
01250 wxString s;
01251 s.Printf ( wxT( "%s = point2d( %f, %f, %d )" ), m_id->GetName().c_str(), m_value.m_x, m_value.m_y, m_index );
01252
01253 if ( m_afterinversion == true )
01254 s << wxT( "true" );
01255 else
01256 s << wxT( "false" );
01257
01258 return s;
01259 }
01260
01261 wxString a2dPoint2DProperty::StringValueRepresentation() const
01262 {
01263 wxString s;
01264 s.Printf ( _T( "point2d( %f, %f, %d )" ), m_value.m_x, m_value.m_y, m_index );
01265
01266 if ( m_afterinversion == true )
01267 s << wxT( "true" );
01268 else
01269 s << wxT( "false" );
01270
01271 return s;
01272 }