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
00042
00043
00044
00045 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_AABB_2D_INL
00046 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_AABB_2D_INL
00047
00048
00049
00050 #include "aabb_2d.h"
00051 #include <cstdlib>
00052
00053
00054 namespace lass
00055 {
00056
00057 namespace prim
00058 {
00059
00060
00061
00062 template <typename T, class MMP>
00063 Aabb2D<T, MMP>::Aabb2D():
00064 min_(TNumTraits::max, TNumTraits::max),
00065 max_(TNumTraits::min, TNumTraits::min)
00066 {
00067 LASS_ASSERT(isEmpty());
00068 }
00069
00070
00071
00072
00073
00074 template <typename T, class MMP>
00075 Aabb2D<T, MMP>::Aabb2D(const TPoint& min, const TPoint& max):
00076 min_(min),
00077 max_(max)
00078 {
00079 MMP::checkMinMax(min_, max_);
00080 LASS_ASSERT(isValid());
00081 }
00082
00083
00084
00085
00086
00087 template <typename T, class MMP>
00088 Aabb2D<T, MMP>::Aabb2D(const TPoint& point):
00089 min_(point),
00090 max_(point)
00091 {
00092 LASS_ASSERT(isValid());
00093 }
00094
00095
00096
00097
00098
00099 template <typename T, class MMP>
00100 template <class MMP2>
00101 Aabb2D<T, MMP>::Aabb2D(const Aabb2D<T, MMP2>& other):
00102 min_(other.min()),
00103 max_(other.max())
00104 {
00105 LASS_ASSERT(isValid());
00106 }
00107
00108
00109
00110
00111
00112 template <typename T, class MMP>
00113 const typename Aabb2D<T, MMP>::TPoint&
00114 Aabb2D<T, MMP>::min() const
00115 {
00116 LASS_ASSERT(isValid());
00117 return min_;
00118 }
00119
00120
00121
00122
00123
00124 template <typename T, class MMP>
00125 const typename Aabb2D<T, MMP>::TPoint&
00126 Aabb2D<T, MMP>::max() const
00127 {
00128 LASS_ASSERT(isValid());
00129 return max_;
00130 }
00131
00132
00133
00134
00135
00136 template <typename T, class MMP>
00137 void Aabb2D<T, MMP>::setMin(const TPoint& min)
00138 {
00139 if (isEmpty())
00140 {
00141 min_ = min;
00142 max_ = min;
00143 }
00144 else
00145 {
00146 MMP::setMin(min_, max_, min);
00147 }
00148 LASS_ASSERT(isValid());
00149 }
00150
00151
00152
00153
00154
00155 template <typename T, class MMP>
00156 void Aabb2D<T, MMP>::setMax(const TPoint& max)
00157 {
00158 if (isEmpty())
00159 {
00160 min_ = max;
00161 max_ = max;
00162 }
00163 else
00164 {
00165 MMP::setMax(min_, max_, max);
00166 }
00167 LASS_ASSERT(isValid());
00168 }
00169
00170
00171
00172
00173
00174 template <typename T, class MMP>
00175 template <class MMP2>
00176 typename Aabb2D<T, MMP>::TSelf&
00177 Aabb2D<T, MMP>::operator=(const Aabb2D<T, MMP2>& other)
00178 {
00179 TSelf temp(other);
00180 swap(temp);
00181 return *this;
00182 }
00183
00184
00185
00186
00187
00188 template <typename T, class MMP>
00189 typename Aabb2D<T, MMP>::TSelf&
00190 Aabb2D<T, MMP>::operator+=(const TPoint& point)
00191 {
00192 min_ = pointwiseMin(min_, point);
00193 max_ = pointwiseMax(max_, point);
00194 LASS_ASSERT(isValid());
00195 return *this;
00196 }
00197
00198
00199
00200
00201
00202 template <typename T, class MMP>
00203 template <class MMP2>
00204 typename Aabb2D<T, MMP>::TSelf&
00205 Aabb2D<T, MMP>::operator+=(const Aabb2D<T, MMP2>& other)
00206 {
00207 min_ = pointwiseMin(min_, other.min());
00208 max_ = pointwiseMax(max_, other.max());
00209 LASS_ASSERT(isValid());
00210 return *this;
00211 }
00212
00213
00214
00215
00216
00217
00218 template <typename T, class MMP>
00219 void Aabb2D<T, MMP>::grow(TParam iDistance)
00220 {
00221 min_.x -= iDistance;
00222 max_.x += iDistance;
00223 min_.y -= iDistance;
00224 max_.y += iDistance;
00225 if (max_.x < min_.x || max_.y < min_.y)
00226 {
00227 clear();
00228 }
00229 LASS_ASSERT(isValid());
00230 }
00231
00232
00233
00234
00235
00236
00237
00238 template <typename T, class MMP>
00239 void Aabb2D<T, MMP>::scale(TParam iScale)
00240 {
00241 const TVector extra = size() * ((num::abs(iScale) - 1) / 2);
00242 min_ -= extra;
00243 max_ += extra;
00244 LASS_ASSERT(isValid());
00245 }
00246
00247
00248
00249
00250
00251
00252
00253 template <typename T, class MMP>
00254 const typename Aabb2D<T, MMP>::TPointH
00255 Aabb2D<T, MMP>::center() const
00256 {
00257 LASS_ASSERT(isValid());
00258 return min_ + max_;
00259 }
00260
00261
00262
00263
00264
00265 template <typename T, class MMP>
00266 const typename Aabb2D<T, MMP>::TVector
00267 Aabb2D<T, MMP>::size() const
00268 {
00269 LASS_ASSERT(isValid());
00270 return max_ - min_;
00271 }
00272
00273
00274
00275
00276
00277 template <typename T, class MMP>
00278 const typename Aabb2D<T, MMP>::TValue
00279 Aabb2D<T, MMP>::perimeter() const
00280 {
00281 LASS_ASSERT(isValid());
00282 const TVector result = size();
00283 return 2 * (result.x + result.y);
00284 }
00285
00286
00287
00288
00289
00290 template <typename T, class MMP>
00291 const typename Aabb2D<T, MMP>::TValue
00292 Aabb2D<T, MMP>::area() const
00293 {
00294 LASS_ASSERT(isValid());
00295 const TVector result = size();
00296 return result.x * result.y;
00297 }
00298
00299
00300
00301
00302
00303 template <typename T, class MMP>
00304 const Side Aabb2D<T, MMP>::classify(const TPoint& point) const
00305 {
00306 LASS_ASSERT(isValid());
00307
00308 if (point.x > min_.x && point.x < max_.x &&
00309 point.y > min_.y && point.y < max_.y)
00310 {
00311 return sInside;
00312 }
00313
00314 if (point.x < min_.x || point.x > max_.x ||
00315 point.y < min_.y || point.y > max_.y)
00316 {
00317 return sOutside;
00318 }
00319
00320 return sSurface;
00321 }
00322
00323
00324
00325
00326
00327
00328 template <typename T, class MMP>
00329 const bool Aabb2D<T, MMP>::contains(const TPoint& point) const
00330 {
00331 LASS_ASSERT(isValid());
00332 return point.x >= min_.x && point.x <= max_.x &&
00333 point.y >= min_.y && point.y <= max_.y;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343 template <typename T, class MMP>
00344 template <class MMP2>
00345 const bool Aabb2D<T, MMP>::contains(const Aabb2D<T, MMP2>& other) const
00346 {
00347 LASS_ASSERT(isValid() && other.isValid());
00348 return other.min().x >= min_.x && other.max().x <= max_.x
00349 && other.min().y >= min_.y && other.max().y <= max_.y;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 template <typename T, class MMP>
00374 template <class MMP2>
00375 const bool Aabb2D<T, MMP>::intersects(const Aabb2D<T, MMP2>& other) const
00376 {
00377 LASS_ASSERT(isValid() && other.isValid());
00378
00379
00380
00381
00382
00383
00384 LASS_ASSERT(center().weight() == 2 && other.center().weight() == 2);
00385 const TPointH doubleCenterToCenter = center() - other.center();
00386
00387 LASS_ASSERT(doubleCenterToCenter.weight() == 0);
00388 const typename TPointH::TVector doubleCenterDistance =
00389 doubleCenterToCenter.position().transform(num::abs);
00390
00391 const TVector doubleExtend = size() + other.size();
00392 return doubleCenterDistance.x <= doubleExtend.x && doubleCenterDistance.y <= doubleExtend.y;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 template <typename T, class MMP>
00417 template <class MMP2>
00418 const bool Aabb2D<T, MMP>::collides(const Aabb2D<T, MMP2>& other) const
00419 {
00420 LASS_ASSERT(isValid() && other.isValid());
00421
00422
00423
00424
00425
00426
00427 LASS_ASSERT(center().weight() == 2 && other.center().weight() == 2);
00428 const TPointH doubleCenterToCenter = center() - other.center();
00429
00430 LASS_ASSERT(doubleCenterToCenter.weight() == 0);
00431 const typename TPointH::TVector doubleCenterDistance =
00432 doubleCenterToCenter.position().transform(num::abs);
00433
00434 const TVector doubleExtend = size() + other.size();
00435 return doubleCenterDistance.x < doubleExtend.x && doubleCenterDistance.y < doubleExtend.y;
00436 }
00437
00438
00439
00440
00441
00442 template <typename T, class MMP>
00443 template <class RandomGenerator>
00444 const typename Aabb2D<T, MMP>::TPoint
00445 Aabb2D<T, MMP>::random(RandomGenerator& generator) const
00446 {
00447 LASS_ASSERT(isValid());
00448 num::DistributionUniform<TValue, RandomGenerator> uniform(generator);
00449 const TVector t(uniform(), uniform());
00450 const TPoint result(min_ + t * (max_ - min_));
00451 LASS_ASSERT(contains(result));
00452 return result;
00453 }
00454
00455
00456
00457
00458
00459 template <typename T, class MMP>
00460 void Aabb2D<T, MMP>::clear()
00461 {
00462 min_ = TPoint(TNumTraits::max, TNumTraits::max);
00463 max_ = TPoint(TNumTraits::min, TNumTraits::min);
00464 LASS_ASSERT(isValid() && isEmpty());
00465 }
00466
00467
00468
00469
00470
00471
00472
00473 template <typename T, class MMP>
00474 const bool Aabb2D<T, MMP>::isEmpty() const
00475 {
00476 LASS_ASSERT(isValid());
00477 return min_.x > max_.x;
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 template <typename T, class MMP>
00496 const bool Aabb2D<T, MMP>::isValid() const
00497 {
00498 return (min_.x <= max_.x && min_.y <= max_.y) || (min_.x > max_.x);
00499 }
00500
00501
00502
00503
00504
00505 template <typename T, class MMP>
00506 template <typename MMP2>
00507 void Aabb2D<T, MMP>::swap(Aabb2D<T, MMP2>& other)
00508 {
00509 std::swap(min_, other.min_);
00510 std::swap(max_, other.max_);
00511 LASS_ASSERT(isValid() && other.isValid());
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521 template <typename T, class MMPa, class MMPb> inline
00522 const Aabb2D<T, MMPa> operator+(const Aabb2D<T, MMPa>& a, const Aabb2D<T, MMPb>& b)
00523 {
00524 Aabb2D<T, MMPa> result(a);
00525 result += b;
00526 return result;
00527 }
00528
00529
00530
00531
00532
00533
00534 template <typename T, class MMP> inline
00535 const Aabb2D<T, MMP> operator+(const Aabb2D<T, MMP>& a, const Point2D<T>& b)
00536 {
00537 Aabb2D<T, MMP> result(a);
00538 result += b;
00539 return result;
00540 }
00541
00542
00543
00544
00545
00546
00547 template <typename T, class MMP> inline
00548 const Aabb2D<T, MMP> operator+(const Point2D<T>& a, const Aabb2D<T, MMP>& b)
00549 {
00550 Aabb2D<T, MMP> result(b);
00551 result += a;
00552 return result;
00553 }
00554
00555
00556
00557
00558
00559
00560 template <typename T>
00561 const Aabb2D<T> aabb(const Point2D<T>& point)
00562 {
00563 return Aabb2D<T>(point, point);
00564 }
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 template <typename T, class MMP> inline
00576 T distance(const Aabb2D<T, MMP>& a, const Point2D<T>& b)
00577 {
00578 LASS_ASSERT(!a.isEmpty());
00579 typedef typename Point2D<T>::TVector TVector;
00580 return pointwiseMax(pointwiseMax(a.min() - b, b - a.max()), TVector()).norm();
00581 }
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592 template <typename T, class MMPa, class MMPb> inline
00593 T distance(const Aabb2D<T, MMPa>& a, const Aabb2D<T, MMPb>& b)
00594 {
00595 LASS_ASSERT(!a.isEmpty() && !b.isEmpty());
00596 typedef typename Point2D<T>::TVector TVector;
00597 return pointwiseMax(pointwiseMax(a.min() - b.max(), b.min() - a.max()), TVector()).norm();
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 template <typename T, class MMPa, class MMPb, class MMPr>
00620 Result intersect(const Aabb2D<T, MMPa>& a, const Aabb2D<T, MMPb>& b, Aabb2D<T, MMPr>& result)
00621 {
00622 LASS_ASSERT(a.isValid() && b.isValid());
00623
00624 if (!a.intersects(b))
00625 {
00626 result = Aabb2D<T, MMPr>();
00627 return rNone;
00628 }
00629
00630
00631
00632
00633 result = Aabb2D<T, MMPr>(pointwiseMax(a.min(), b.min()), pointwiseMin(a.max(), b.max()));
00634 return rOne;
00635 }
00636
00637
00638
00639
00640
00641 template <typename T, typename MMPa, typename MMPb> inline
00642 const bool intersects(const Aabb2D<T, MMPa>& a, const Aabb2D<T, MMPb>& b)
00643 {
00644 return a.intersects(b);
00645 }
00646
00647
00648
00649
00650
00651 template <typename T, typename MMP> inline
00652 const bool intersects(const Aabb2D<T, MMP>& a, const Point2D<T>& b)
00653 {
00654 return a.contains(b);
00655 }
00656
00657
00658
00659
00660
00661 template <typename T, typename MMP> inline
00662 const bool intersects(const Point2D<T>& a, const Aabb2D<T, MMP>& b)
00663 {
00664 return b.contains(a);
00665 }
00666
00667
00668
00669
00670
00671 template <typename T, typename MMPa, typename MMPb> inline
00672 const bool collides(const Aabb2D<T, MMPa>& a, const Aabb2D<T, MMPb>& b)
00673 {
00674 return a.collides(b);
00675 }
00676
00677
00678
00679
00680
00681 template <typename T, typename MMP> inline
00682 const bool collides(const Aabb2D<T, MMP>& a, const Point2D<T>& b)
00683 {
00684 typedef typename Aabb2D<T, MMP>::TPoint TPoint;
00685 const TPoint& min = a.min();
00686 const TPoint& max = a.max();
00687 return min.x < b.x && b.x < max.x && min.y < b.y && b.y < max.y;
00688 }
00689
00690
00691
00692
00693
00694 template <typename T, typename MMP> inline
00695 const bool collides(const Point2D<T>& a, const Aabb2D<T, MMP>& b)
00696 {
00697 return collides(b, a);
00698 }
00699
00700
00701
00702
00703
00704 template <typename T, class MMP>
00705 std::ostream& operator<<(std::ostream& ioOStream, const Aabb2D<T, MMP>& aabb)
00706 {
00707 LASS_ENFORCE_STREAM(ioOStream) << "{m=" << aabb.min() << ", M=" << aabb.max() << "}";
00708 return ioOStream;
00709 }
00710
00711
00712
00713
00714
00715 template<typename T, class MMP>
00716 io::XmlOStream& operator<<(io::XmlOStream& ioOStream, const Aabb2D<T, MMP>& aabb)
00717 {
00718 LASS_ENFORCE_STREAM(ioOStream)
00719 << "<Aabb2D>\n"
00720 << "<min>" << aabb.min() << "</min>\n"
00721 << "<max>" << aabb.max() << "</max>\n"
00722 << "</Aabb2D>\n";
00723
00724 return ioOStream;
00725 }
00726
00727
00728
00729
00730
00731 template <typename T, class MMP>
00732 io::MatlabOStream& operator<<(io::MatlabOStream& ioOStream, const Aabb2D<T, MMP>& aabb)
00733 {
00734 typedef typename Aabb2D<T, MMP>::TPoint TPoint;
00735 const TPoint& min = aabb.min();
00736 const TPoint& max = aabb.max();
00737
00738 ioOStream << "lasthandle = patch(";
00739 ioOStream << "[" << min.x() << "," << max.x() << "," << max.x() << "," << min.x() << "],";
00740 ioOStream << "[" << min.y() << "," << min.y() << "," << max.y() << "," << max.y() << "],";
00741 ioOStream << ioOStream.color() << ",'EdgeColor'," << ioOStream.color() << ",";
00742
00743 if (ioOStream.flag("wireframe"))
00744 {
00745 ioOStream << "'FaceColor','none',";
00746 }
00747 else
00748 {
00749 ioOStream << "'FaceColor'," << ioOStream.color() << ",'FaceAlpha',0.25";
00750 }
00751 ioOStream << ");\n";
00752
00753 return ioOStream;
00754 }
00755
00756
00757
00758 }
00759
00760 }
00761
00762 #endif