00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <cmath>
00042 #include <iostream>
00043 #include <string>
00044
00045 #include <qgarlib/BoundingBox.H>
00046 #include <qgarlib/primitives.H>
00047 #include <qgarlib/QgarErrorDomain.H>
00048
00049
00050
00051 namespace qgar
00052 {
00053
00054
00055
00056
00057
00058
00059
00060
00061 BoundingBox::BoundingBox()
00062
00063 : _topLeft (0, 0),
00064 _bottomRight(0, 0)
00065
00066 {
00067
00068 }
00069
00070
00071
00072
00073 BoundingBox::BoundingBox(const BoundingBox& aBox)
00074
00075 : _topLeft (aBox._topLeft),
00076 _bottomRight(aBox._bottomRight)
00077
00078 {
00079
00080 }
00081
00082
00083
00084
00085 BoundingBox::BoundingBox(const IPoint& aPt1,
00086 const IPoint& aPt2)
00087 {
00088 setCorners(aPt1, aPt2);
00089 }
00090
00091
00092
00093
00094 BoundingBox::BoundingBox(int aX1, int aY1, int aX2, int aY2)
00095 {
00096 setCorners(aX1, aY1, aX2, aY2);
00097 }
00098
00099
00100
00101
00102 BoundingBox::BoundingBox(const IPoint& aTopLeft,
00103 int aLength,
00104 int aHeight)
00105 throw(QgarErrorDomain)
00106
00107 : _topLeft(aTopLeft),
00108 _bottomRight(aTopLeft.x() + aLength - 1,
00109 aTopLeft.y() + aHeight - 1)
00110
00111 {
00112
00113
00114
00115 if (aLength <= 0)
00116 {
00117 std::ostringstream os;
00118 os << "Bounding box length ("
00119 << aLength
00120 << ") must be greater than 0";
00121 throw QgarErrorDomain(__FILE__, __LINE__,
00122 "qgar::BoundingBox::BoundingBox(const qgar::IPoint&, int, int)",
00123 os.str());
00124 }
00125
00126 if (aHeight <= 0)
00127 {
00128 std::ostringstream os;
00129 os << "Bounding box height ("
00130 << aHeight
00131 << ") must be greater than 0";
00132 throw QgarErrorDomain(__FILE__, __LINE__,
00133 "qgar::BoundingBox::BoundingBox(const qgar::IPoint&, int, int)",
00134 os.str());
00135 }
00136 }
00137
00138
00139
00140
00141 BoundingBox::BoundingBox(int aLength,
00142 int aHeight,
00143 const IPoint& aBottomRight)
00144 throw(QgarErrorDomain)
00145
00146 : _topLeft(aBottomRight.x() - aLength + 1,
00147 aBottomRight.y() - aHeight + 1),
00148 _bottomRight(aBottomRight)
00149
00150 {
00151
00152
00153
00154 if (aLength <= 0)
00155 {
00156 std::ostringstream os;
00157 os << "Bounding box length ("
00158 << aLength
00159 << ") must be greater than 0";
00160 throw QgarErrorDomain(__FILE__, __LINE__,
00161 "qgar::BoundingBox::BoundingBox(int, int, const qgar::IPoint&)",
00162 os.str());
00163 }
00164
00165 if (aHeight <= 0)
00166 {
00167 std::ostringstream os;
00168 os << "Bounding box height ("
00169 << aHeight
00170 << ") must be greater than 0";
00171 throw QgarErrorDomain(__FILE__, __LINE__,
00172 "qgar::BoundingBox::BoundingBox(int, int, const qgar::IPoint&)",
00173 os.str());
00174 }
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 BoundingBox::~BoundingBox()
00184 {
00185
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 void
00197 BoundingBox::setTopLeft(const IPoint& aPt)
00198
00199 throw(QgarErrorDomain)
00200
00201 {
00202
00203 if ((aPt.x() > _topLeft.x()) || (aPt.y() > _bottomRight.y()))
00204 {
00205 std::ostringstream os;
00206 os << "New top left corner (" << aPt.x() << ',' << aPt.y()
00207 << ") does not fit current box: Top left("
00208 << _topLeft.x() << ',' << _topLeft.y()
00209 << "), bottom right("
00210 << _bottomRight.x() << ',' << _bottomRight.y()
00211 << ')';
00212 throw QgarErrorDomain(__FILE__, __LINE__,
00213 "void qgar::BoundingBox::setTopLeft(const qgar::IPoint&)",
00214 os.str());
00215 }
00216 _topLeft = aPt;
00217 }
00218
00219
00220
00221
00222 void
00223 BoundingBox::setTopLeft(int aX, int aY)
00224
00225 throw(QgarErrorDomain)
00226
00227 {
00228
00229 if ((aX > _topLeft.x()) || (aY > _bottomRight.y()))
00230 {
00231 std::ostringstream os;
00232 os << "New top left corner (" << aX << ',' << aY
00233 << ") does not fit current box: Top left("
00234 << _topLeft.x() << ',' << _topLeft.y()
00235 << "), bottom right("
00236 << _bottomRight.x() << ',' << _bottomRight.y()
00237 << ')';
00238 throw QgarErrorDomain(__FILE__, __LINE__,
00239 "void qgar::BoundingBox::setTopLeft(int, int)",
00240 os.str());
00241 }
00242
00243 _topLeft.setXY(aX, aY);
00244 }
00245
00246
00247
00248
00249 void
00250 BoundingBox::setXTopLeft(int aX)
00251
00252 throw(QgarErrorDomain)
00253
00254 {
00255
00256 if (aX > _bottomRight.x())
00257 {
00258 std::ostringstream os;
00259 os << "New top left corner (" << aX << ',' << _topLeft.y()
00260 << ") does not fit current box: Top left("
00261 << _topLeft.x() << ',' << _topLeft.y()
00262 << "), bottom right("
00263 << _bottomRight.x() << ',' << _bottomRight.y()
00264 << ')';
00265 throw QgarErrorDomain(__FILE__, __LINE__,
00266 "void qgar::BoundingBox::setXTopLeft(int)",
00267 os.str());
00268 }
00269
00270 _topLeft.setX(aX);
00271 }
00272
00273
00274
00275
00276 void
00277 BoundingBox::setYTopLeft(int aY)
00278
00279 throw(QgarErrorDomain)
00280
00281 {
00282
00283 if (aY > _bottomRight.y())
00284 {
00285 std::ostringstream os;
00286 os << "New top left corner (" << _topLeft.x() << ',' << aY
00287 << ") does not fit current box: Top left("
00288 << _topLeft.x() << ',' << _topLeft.y()
00289 << "), bottom right("
00290 << _bottomRight.x() << ',' << _bottomRight.y()
00291 << ')';
00292 throw QgarErrorDomain(__FILE__, __LINE__,
00293 "void qgar::BoundingBox::setYTopLeft(int)",
00294 os.str());
00295 }
00296
00297 _topLeft.setY(aY);
00298 }
00299
00300
00301
00302
00303 void
00304 BoundingBox::setBottomRight(const IPoint& aPt)
00305
00306 throw(QgarErrorDomain)
00307
00308 {
00309
00310 if ((aPt.x() < _topLeft.x()) || (aPt.y() < _bottomRight.y()))
00311 {
00312 std::ostringstream os;
00313 os << "New bottom right corner (" << aPt.x() << ',' << aPt.y()
00314 << ") does not fit current box: Top left("
00315 << _topLeft.x() << ',' << _topLeft.y()
00316 << "), bottom right("
00317 << _bottomRight.x() << ',' << _bottomRight.y()
00318 << ')';
00319 throw QgarErrorDomain(__FILE__, __LINE__,
00320 "void qgar::BoundingBox::BottomRight(const qgar::IPoint&)",
00321 os.str());
00322 }
00323 _bottomRight = aPt;
00324 }
00325
00326
00327
00328
00329 void
00330 BoundingBox::setBottomRight(int aX, int aY)
00331
00332 throw(QgarErrorDomain)
00333
00334 {
00335
00336 if ((aX < _topLeft.x()) || (aY < _bottomRight.y()))
00337 {
00338 std::ostringstream os;
00339 os << "New bottom right corner (" << aX << ',' << aY
00340 << ") does not fit current box: Top left("
00341 << _topLeft.x() << ',' << _topLeft.y()
00342 << "), bottom right("
00343 << _bottomRight.x() << ',' << _bottomRight.y()
00344 << ')';
00345 throw QgarErrorDomain(__FILE__, __LINE__,
00346 "void qgar::BoundingBox::setBottomRight(int, int)",
00347 os.str());
00348 }
00349 _bottomRight.setXY(aX, aY);
00350 }
00351
00352
00353
00354
00355 void
00356 BoundingBox::setXBottomRight(int aX)
00357
00358 throw(QgarErrorDomain)
00359
00360 {
00361
00362 if (aX < _topLeft.x())
00363 {
00364 std::ostringstream os;
00365 os << "New bottom right corner (" << aX << ',' << _bottomRight.y()
00366 << ") does not fit current box: Top left("
00367 << _topLeft.x() << ',' << _topLeft.y()
00368 << "), bottom right("
00369 << _bottomRight.x() << ',' << _bottomRight.y()
00370 << ')';
00371 throw QgarErrorDomain(__FILE__, __LINE__,
00372 "void qgar::BoundingBox::setXBottomRight(int)",
00373 os.str());
00374 }
00375
00376 _bottomRight.setX(aX);
00377 }
00378
00379
00380
00381
00382 void
00383 BoundingBox::setYBottomRight(int aY)
00384
00385 throw(QgarErrorDomain)
00386
00387 {
00388
00389 if (aY < _topLeft.y())
00390 {
00391 std::ostringstream os;
00392 os << "New bottom right corner (" << _bottomRight.x() << ',' << aY
00393 << ") does not fit current box: Top left("
00394 << _topLeft.x() << ',' << _topLeft.y()
00395 << "), bottom right("
00396 << _bottomRight.x() << ',' << _bottomRight.y()
00397 << ')';
00398 throw QgarErrorDomain(__FILE__, __LINE__,
00399 "void qgar::BoundingBox::setYBottomRight(int)",
00400 os.str());
00401 }
00402
00403 _bottomRight.setY(aY);
00404 }
00405
00406
00407
00408
00409 void
00410 BoundingBox::setCorners(const IPoint& aPt1, const IPoint& aPt2)
00411 {
00412 setCorners(aPt1.x(), aPt1.y(), aPt2.x(), aPt2.y());
00413 }
00414
00415
00416
00417
00418 void
00419 BoundingBox::setCorners(int aX1, int aY1, int aX2, int aY2)
00420 {
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 _topLeft.setXY ((aX1 > aX2) ? aX2 : aX1, (aY1 > aY2) ? aY2 : aY1);
00437 _bottomRight.setXY((aX1 > aX2) ? aX1 : aX2, (aY1 > aY2) ? aY1 : aY2);
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 bool
00450 BoundingBox::contains(int aX, int aY) const
00451 {
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 return
00468 (aX >= _topLeft.x())
00469 && (aX <= _bottomRight.x())
00470 && (aY >= _topLeft.y())
00471 && (aY <= _bottomRight.y());
00472 }
00473
00474
00475
00476
00477 bool
00478 BoundingBox::intersects(const BoundingBox& aBox) const
00479 {
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 return
00503 (aBox.xBottomRight() >= _topLeft.x())
00504 && (aBox.yBottomRight() >= _topLeft.y())
00505 && (aBox.xTopLeft() <= _bottomRight.x())
00506 && (aBox.yTopLeft() <= _bottomRight.y());
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 BoundingBox*
00518 BoundingBox::intersection(const BoundingBox& aBox) const
00519 {
00520 if (this->intersects(aBox))
00521 {
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 return
00538 new BoundingBox(std::max(_topLeft.x(), aBox.xTopLeft()),
00539 std::max(_topLeft.y(), aBox.yTopLeft()),
00540 std::min(_bottomRight.x(), aBox.xBottomRight()),
00541 std::min(_bottomRight.y(), aBox.yBottomRight()));
00542 }
00543 else
00544 {
00545 return (BoundingBox*)0;
00546 }
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 BoundingBox&
00558 BoundingBox::operator=(const BoundingBox& aBox)
00559 {
00560
00561 if (this != &aBox)
00562 {
00563 _topLeft = aBox._topLeft;
00564 _bottomRight = aBox._bottomRight;
00565 }
00566 return *this;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 bool
00578 BoundingBox::eq(const BoundingBox& aBox) const
00579 {
00580 return (_topLeft == aBox.topLeft())
00581 && (_bottomRight == aBox.bottomRight());
00582 }
00583
00584
00585
00586
00587 bool
00588 BoundingBox::notEq(const BoundingBox& aBox) const
00589 {
00590 return (_topLeft != aBox.topLeft())
00591 || (_bottomRight != aBox.bottomRight());
00592 }
00593
00594
00595
00596
00597
00598
00599
00600 std::istream&
00601 BoundingBox::read(std::istream& anInStream)
00602 {
00603 IPoint topL;
00604 IPoint bottomR;
00605 qgReadObjName(anInStream, "BoundingBox");
00606 qgReadObjData(anInStream, topL);
00607 qgReadObjData(anInStream, bottomR);
00608
00609 setCorners(topL, bottomR);
00610
00611 return anInStream;
00612 }
00613
00614
00615 std::ostream&
00616 BoundingBox::write(std::ostream& anOutStream) const
00617 {
00618 anOutStream << "BoundingBox("
00619 << _topLeft
00620 << ")("
00621 << _bottomRight
00622 << ')';
00623
00624 return anOutStream;
00625 }
00626
00627
00628
00629
00630
00631 }