00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "a2dprec.h"
00012
00013 #ifdef __BORLANDC__
00014 #pragma hdrstop
00015 #endif
00016
00017 #ifndef WX_PRECOMP
00018 #include "wx/wx.h"
00019 #endif
00020
00021 #include "wx/artbase/bbox.h"
00022
00023 a2dBoundingBox wxNonValidBbox;
00024
00025 a2dBoundingBox::a2dBoundingBox()
00026 {
00027 m_minx = m_miny = m_maxx = m_maxy = 0.0;
00028 m_validbbox = false;
00029 }
00030
00031
00032 a2dBoundingBox::a2dBoundingBox( const a2dBoundingBox &other )
00033 {
00034 m_minx = other.m_minx;
00035 m_miny = other.m_miny;
00036 m_maxx = other.m_maxx;
00037 m_maxy = other.m_maxy;
00038 m_validbbox = other.m_validbbox;
00039 }
00040
00041
00042 a2dBoundingBox::a2dBoundingBox( const a2dPoint2D& a )
00043 {
00044 m_validbbox = false;
00045 Expand( a.m_x, a.m_y );
00046 }
00047
00048 a2dBoundingBox::a2dBoundingBox( double x1, double y1, double x2, double y2 )
00049 {
00050 m_validbbox = false;
00051 Expand( x1, y1 );
00052 Expand( x2, y2 );
00053 }
00054
00055
00056 bool a2dBoundingBox::And( a2dBoundingBox *bbox, double Marge )
00057 {
00058 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00059 wxASSERT_MSG( bbox->m_validbbox, wxT( "invalid bbox" ) );
00060
00061 if ( ( ( m_minx - Marge ) > ( bbox->m_maxx + Marge ) ) ||
00062 ( ( m_maxx + Marge ) < ( bbox->m_minx - Marge ) ) ||
00063 ( ( m_maxy + Marge ) < ( bbox->m_miny - Marge ) ) ||
00064 ( ( m_miny - Marge ) > ( bbox->m_maxy + Marge ) ) )
00065 return false;
00066
00067
00068 if ( ( m_minx <= bbox->m_minx ) &&
00069 ( m_maxx >= bbox->m_maxx ) &&
00070 ( m_maxy >= bbox->m_maxy ) &&
00071 ( m_miny <= bbox->m_miny ) )
00072 {
00073 m_minx = bbox->m_minx;
00074 m_maxx = bbox->m_maxx;
00075 m_miny = bbox->m_miny;
00076 m_maxy = bbox->m_maxy;
00077 return true;
00078 }
00079
00080
00081 m_minx = wxMax( m_minx, bbox->m_minx );
00082 m_maxx = wxMin( m_maxx, bbox->m_maxx );
00083 m_miny = wxMax( m_miny, bbox->m_miny );
00084 m_maxy = wxMin( m_maxy, bbox->m_maxy );
00085 return true;
00086 }
00087
00088
00089 void a2dBoundingBox::Shrink( const double Marge )
00090 {
00091 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00092
00093 m_minx += Marge;
00094 m_maxx -= Marge;
00095 m_miny += Marge;
00096 m_maxy -= Marge;
00097 }
00098
00099
00100
00101 void a2dBoundingBox::Expand( const a2dBoundingBox &other )
00102 {
00103 if ( !m_validbbox )
00104 {
00105 *this = other;
00106 }
00107 else
00108 {
00109 m_minx = wxMin( m_minx, other.m_minx );
00110 m_maxx = wxMax( m_maxx, other.m_maxx );
00111 m_miny = wxMin( m_miny, other.m_miny );
00112 m_maxy = wxMax( m_maxy, other.m_maxy );
00113 }
00114 }
00115
00116
00117
00118 void a2dBoundingBox::Expand( const a2dPoint2D& a_point )
00119 {
00120 if ( !m_validbbox )
00121 {
00122 m_minx = m_maxx = a_point.m_x;
00123 m_miny = m_maxy = a_point.m_y;
00124 m_validbbox = true;
00125 }
00126 else
00127 {
00128 m_minx = wxMin( m_minx, a_point.m_x );
00129 m_maxx = wxMax( m_maxx, a_point.m_x );
00130 m_miny = wxMin( m_miny, a_point.m_y );
00131 m_maxy = wxMax( m_maxy, a_point.m_y );
00132 }
00133 }
00134
00135
00136 void a2dBoundingBox::Expand( double x, double y )
00137 {
00138 if ( !m_validbbox )
00139 {
00140 m_minx = m_maxx = x;
00141 m_miny = m_maxy = y;
00142 m_validbbox = true;
00143 }
00144 else
00145 {
00146 m_minx = wxMin( m_minx, x );
00147 m_maxx = wxMax( m_maxx, x );
00148 m_miny = wxMin( m_miny, y );
00149 m_maxy = wxMax( m_maxy, y );
00150 }
00151 }
00152
00153
00154
00155 void a2dBoundingBox::Expand( const a2dPoint2D& a, const a2dPoint2D& b )
00156 {
00157 Expand( a );
00158 Expand( b );
00159 }
00160
00161
00162 void a2dBoundingBox::Enlarge( const double marge )
00163 {
00164 if ( !m_validbbox )
00165 {
00166 m_minx = -marge;
00167 m_miny = -marge;
00168 m_maxx = marge;
00169 m_maxy = marge;
00170 m_validbbox = true;
00171 }
00172 else
00173 {
00174 m_minx -= marge;
00175 m_maxx += marge;
00176 m_miny -= marge;
00177 m_maxy += marge;
00178 }
00179 }
00180
00181
00182 void a2dBoundingBox::EnlargeXY( const double margeX, const double margeY )
00183 {
00184 if ( !m_validbbox )
00185 {
00186 m_minx = -margeX;
00187 m_miny = -margeY;
00188 m_maxx = margeX;
00189 m_maxy = margeY;
00190 m_validbbox = true;
00191 }
00192 else
00193 {
00194 m_minx -= margeX;
00195 m_maxx += margeX;
00196 m_miny -= margeY;
00197 m_maxy += margeY;
00198 }
00199 }
00200
00201
00202
00203
00204
00205 OVERLAP a2dBoundingBox::Intersect( const a2dBoundingBox &other, double Marge ) const
00206 {
00207 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00208 wxASSERT_MSG( other.m_validbbox, wxT( "invalid bbox" ) );
00209
00210
00211 if ( ( ( m_minx - Marge ) > ( other.m_maxx + Marge ) ) ||
00212 ( ( m_maxx + Marge ) < ( other.m_minx - Marge ) ) ||
00213 ( ( m_maxy + Marge ) < ( other.m_miny - Marge ) ) ||
00214 ( ( m_miny - Marge ) > ( other.m_maxy + Marge ) ) )
00215 return _OUT;
00216
00217
00218 if ( ( m_minx <= other.m_minx ) &&
00219 ( m_maxx >= other.m_maxx ) &&
00220 ( m_maxy >= other.m_maxy ) &&
00221 ( m_miny <= other.m_miny ) )
00222 return _IN;
00223
00224
00225 return _ON;
00226 }
00227
00228
00229
00230 bool a2dBoundingBox::LineIntersect( const a2dPoint2D& begin, const a2dPoint2D& end ) const
00231 {
00232 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00233
00234 return ( bool )
00235 !( ( ( begin.m_y > m_maxy ) && ( end.m_y > m_maxy ) ) ||
00236 ( ( begin.m_y < m_miny ) && ( end.m_y < m_miny ) ) ||
00237 ( ( begin.m_x > m_maxx ) && ( end.m_x > m_maxx ) ) ||
00238 ( ( begin.m_x < m_minx ) && ( end.m_x < m_minx ) ) );
00239 }
00240
00241
00242
00243 bool a2dBoundingBox::PointInBox( double x, double y, double Marge ) const
00244 {
00245 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00246
00247 if ( x >= ( m_minx - Marge ) && x <= ( m_maxx + Marge ) &&
00248 y >= ( m_miny - Marge ) && y <= ( m_maxy + Marge ) )
00249 return true;
00250 return false;
00251 }
00252
00253
00254
00255
00256 bool a2dBoundingBox::PointInBox( const a2dPoint2D& a, double Marge ) const
00257 {
00258 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00259
00260 return PointInBox( a.m_x, a.m_y, Marge );
00261 }
00262
00263
00264 bool a2dBoundingBox::PointOnBox( double x, double y, double Marge ) const
00265 {
00266 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00267
00268 if ( x >= ( m_minx - Marge ) && x <= ( m_maxx + Marge ) &&
00269 y >= ( m_miny - Marge ) && y <= ( m_maxy + Marge ) &&
00270 ( x <= ( m_minx + Marge ) || x >= ( m_maxx - Marge ) ||
00271 y <= ( m_miny + Marge ) || y >= ( m_maxy - Marge ) )
00272 )
00273 return true;
00274 return false;
00275 }
00276
00277 a2dPoint2D a2dBoundingBox::GetMin() const
00278 {
00279 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00280
00281 return a2dPoint2D( m_minx, m_miny );
00282 }
00283
00284
00285 a2dPoint2D a2dBoundingBox::GetMax() const
00286 {
00287 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00288
00289 return a2dPoint2D( m_maxx, m_maxy );
00290 }
00291
00292 bool a2dBoundingBox::GetValid() const
00293 {
00294 return m_validbbox;
00295 }
00296
00297 double a2dBoundingBox::GetMinX() const
00298 {
00299 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00300 return m_minx;
00301 }
00302
00303 double a2dBoundingBox::GetMinY() const
00304 {
00305 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00306 return m_miny;
00307 }
00308
00309 double a2dBoundingBox::GetMaxX() const
00310 {
00311 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00312 return m_maxx;
00313 }
00314
00315 double a2dBoundingBox::GetMaxY() const
00316 {
00317 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00318 return m_maxy;
00319 }
00320
00321 double a2dBoundingBox::GetWidth() const
00322 {
00323 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00324 return fabs( m_maxx -m_minx );
00325 }
00326
00327 double a2dBoundingBox::GetHeight() const
00328 {
00329 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00330 return fabs( m_maxy -m_miny );
00331 }
00332
00333 void a2dBoundingBox::SetMin( double px, double py )
00334 {
00335 m_minx = px;
00336 m_miny = py;
00337 if ( !m_validbbox )
00338 {
00339 m_maxx = px;
00340 m_maxy = py;
00341 m_validbbox = true;
00342 }
00343 }
00344
00345 void a2dBoundingBox::SetMax( double px, double py )
00346 {
00347 m_maxx = px;
00348 m_maxy = py;
00349 if ( !m_validbbox )
00350 {
00351 m_minx = px;
00352 m_miny = py;
00353 m_validbbox = true;
00354 }
00355 }
00356
00357 void a2dBoundingBox::SetValid( bool value )
00358 {
00359 m_validbbox = value;
00360 }
00361
00362
00363 const a2dBoundingBox& a2dBoundingBox::Translate( a2dPoint2D& offset )
00364 {
00365 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00366
00367 m_minx += offset.m_x;
00368 m_maxx += offset.m_x;
00369 m_miny += offset.m_y;
00370 m_maxy += offset.m_y;
00371 return *this;
00372 }
00373
00374 const a2dBoundingBox& a2dBoundingBox::Translate( double x, double y )
00375 {
00376 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00377
00378 m_minx += x;
00379 m_maxx += x;
00380 m_miny += y;
00381 m_maxy += y;
00382 return *this;
00383 }
00384
00385
00386
00387 void a2dBoundingBox::Reset()
00388 {
00389 m_minx = 0.0;
00390 m_maxx = 0.0;
00391 m_miny = 0.0;
00392 m_maxy = 0.0;
00393 m_validbbox = false;
00394 }
00395
00396
00397 void a2dBoundingBox::SetBoundingBox( const a2dPoint2D& a_point )
00398 {
00399 m_minx = a_point.m_x;
00400 m_maxx = a_point.m_x;
00401 m_miny = a_point.m_y;
00402 m_maxy = a_point.m_y;
00403 }
00404
00405 a2dBoundingBox& a2dBoundingBox::operator+( a2dBoundingBox &other )
00406 {
00407 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00408 wxASSERT_MSG( other.m_validbbox, wxT( "invalid bbox" ) );
00409
00410 Expand( other );
00411 return *this;
00412 }
00413
00414 const a2dBoundingBox& a2dBoundingBox::operator+=( const a2dBoundingBox& box )
00415 {
00416 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00417 wxASSERT_MSG( box.m_validbbox, wxT( "invalid bbox" ) );
00418
00419 Expand( box );
00420 return *this;
00421 }
00422
00423
00424 a2dBoundingBox& a2dBoundingBox::operator=( const a2dBoundingBox &other )
00425 {
00426
00427
00428
00429
00430 m_minx = other.m_minx;
00431 m_maxx = other.m_maxx;
00432 m_miny = other.m_miny;
00433 m_maxy = other.m_maxy;
00434 m_validbbox = other.m_validbbox;
00435 return *this;
00436 }
00437
00438 void a2dBoundingBox::MapBbox( const a2dAffineMatrix& matrix )
00439 {
00440 wxASSERT_MSG( m_validbbox, wxT( "invalid bbox" ) );
00441
00442 if ( matrix.IsIdentity() )
00443 return;
00444
00445 double x1, y1, x2, y2, x3, y3, x4, y4;
00446
00447 matrix.TransformPoint( m_minx, m_miny, x1, y1 );
00448 matrix.TransformPoint( m_minx, m_maxy, x2, y2 );
00449 matrix.TransformPoint( m_maxx, m_maxy, x3, y3 );
00450 matrix.TransformPoint( m_maxx, m_miny, x4, y4 );
00451
00452 m_minx = wxMin( x1, x2 );
00453 m_minx = wxMin( m_minx, x3 );
00454 m_minx = wxMin( m_minx, x4 );
00455
00456 m_maxx = wxMax( x1, x2 );
00457 m_maxx = wxMax( m_maxx, x3 );
00458 m_maxx = wxMax( m_maxx, x4 );
00459
00460 m_miny = wxMin( y1, y2 );
00461 m_miny = wxMin( m_miny, y3 );
00462 m_miny = wxMin( m_miny, y4 );
00463
00464 m_maxy = wxMax( y1, y2 );
00465 m_maxy = wxMax( m_maxy, y3 );
00466 m_maxy = wxMax( m_maxy, y4 );
00467 }
00468
00469 #ifdef _DEBUG
00470
00471 void a2dBoundingBox::Dump() const
00472 {
00473 wxLogDebug( _T( "boundingbox minx=%f, miny=%f maxx=%f maxy=%f" ), m_minx, m_miny, m_maxx, m_maxy );
00474 wxLogDebug( _T( "boundingbox width=%f, height=%f" ), GetWidth(), GetHeight() );
00475 }
00476
00477 #endif
00478
00479