00001
00195 #ifndef INC_MI32_RECT_H
00196 #define INC_MI32_RECT_H
00197
00203
00204 #ifndef INC_MI32_POINT_H
00205 #include <mi32/point.h>
00206 #endif
00207
00208 #ifdef ALLOW_NAMESPACES
00209 #include <limits>
00210 #include <cmath>
00211 #else
00212 #include <limits.h>
00213 #include <float.h>
00214 #endif
00215
00216 #ifndef GENERATING_DOXYGEN_OUTPUT
00217
00218 #ifdef GEOMDLL
00219 #define GEOMLIBEXPORT MI_DLLEXPORT
00220 #define GEOMLIBCLASSEXPORT MI_DLLCLASSEXPORT
00221 #else
00222 #define GEOMLIBEXPORT MI_DLLIMPORT
00223 #define GEOMLIBCLASSEXPORT MI_DLLCLASSIMPORT
00224 #endif
00225
00226 GEOMLIBEXPORT void LRect2DGetCorners (const LRECT2D& rect, LPOINT2D *pts, bool ClosePoly, bool OrientCCW);
00227 GEOMLIBEXPORT bool DRect2DComputeEdgePoint (const DRECT2D& rect, const DPOINT2D& OutsidePt, DPOINT2D& EdgePt);
00228 GEOMLIBEXPORT void DRect2DGetCorners (const DRECT2D& rect, DPOINT2D *pts, bool ClosePoly, bool OrientCCW);
00229 GEOMLIBEXPORT void DRect2DGetCorners (const DRECT2D& rect, DPOINT3D *pts, bool ClosePoly, bool OrientCCW);
00230 GEOMLIBEXPORT double DRect2DGetDistance (const DRECT2D& trect, const DRECT2D& rect);
00231 GEOMLIBEXPORT double DRect2DGetMaxDistance (const DRECT2D& trect, const DRECT2D& rect);
00232 GEOMLIBEXPORT double DRect2DGetMaxDistanceSquared (const DRECT2D& trect, const DRECT2D& rect);
00233 GEOMLIBEXPORT bool DRect2DIsEquivalentTo (const DRECT2D& trect, const DRECT2D& rect, double thresold);
00234
00235 #endif //GENERATING_DOXYGEN_OUTPUT
00236
00237
00238
00240 struct WRECT2D {
00241 INT16 xinit;
00242 INT16 yinit;
00243 INT16 xlast;
00244 INT16 ylast;
00245
00247 WRECT2D (
00248 ): xinit(INT16_MAX), yinit(INT16_MAX), xlast(INT16_MIN), ylast(INT16_MIN) { }
00249
00251 WRECT2D (
00252 INT16 xi,
00253 INT16 yi,
00254 INT16 xl,
00255 INT16 yl
00256 ) : xinit(xi), yinit(yi), xlast(xl), ylast(yl) { }
00257
00259 bool Contains (
00260 INT16 x,
00261 INT16 y
00262 ) const { return (x >= xinit && x <= xlast && y >= yinit && y <= ylast); }
00263
00265 bool Contains (
00266 const WPOINT2D& pt
00267 ) const { return (pt.x >= xinit && pt.x <= xlast && pt.y >= yinit && pt.y <= ylast); }
00268
00270 bool Contains (
00271 const WRECT2D& rhs
00272 ) const { return (rhs.xinit >= xinit && rhs.xlast <= xlast && rhs.yinit >= yinit && rhs.ylast <= ylast); }
00273
00275 void Expand (
00276 const INT16 value
00277 ) { xinit -= value; yinit -= value; xlast += value; ylast += value; }
00278
00280 void Expand (
00281 const INT16 xval,
00282 const INT16 yval
00283 ) { xinit -= xval; yinit -= yval; xlast += xval; ylast += yval; }
00284
00286 void Extend (
00287 const INT16 xval,
00288 const INT16 yval
00289 ) {
00290 if (xval < xinit) xinit = xval;
00291 if (yval < yinit) yinit = yval;
00292 if (xval > xlast) xlast = xval;
00293 if (yval > ylast) ylast = yval;
00294 }
00295
00297 UINT16 GetHeight (
00298 ) const { return (ylast - yinit + 1); }
00299
00301 UINT16 GetWidth (
00302 ) const { return (xlast - xinit + 1); }
00303
00305 bool IsNonEmpty (
00306 ) const { return (xinit < xlast && yinit < ylast); }
00307
00309 bool IsValid (
00310 ) const { return (xinit <= xlast && yinit <= ylast); }
00311
00313 bool Overlaps (
00314 const WRECT2D& rhs
00315 ) const {
00316 return (!(rhs.xlast < xinit || rhs.xinit > xlast || rhs.ylast < yinit || rhs.yinit > ylast));
00317 }
00318
00320 void Set (
00321 INT16 x1,
00322 INT16 y1,
00323 INT16 x2,
00324 INT16 y2
00325 ) { xinit = x1; yinit = y1; xlast = x2; ylast = y2; }
00326
00331 void SetInvalid (
00332 ) { xinit = yinit = INT16_MAX; xlast = ylast = INT16_MIN; }
00333
00335 void SwapBytes (
00336 ) { ::SwapBytes(xinit); ::SwapBytes(xlast); ::SwapBytes(yinit); ::SwapBytes(ylast); }
00337
00338 #ifndef GENERATING_DOXYGEN_OUTPUT
00339
00340 CHECKSIZE(8);
00341 #endif
00342 };
00343
00344
00345
00347 struct LRECT2D {
00348
00349 INT32 xinit;
00350 INT32 yinit;
00351 INT32 xlast;
00352 INT32 ylast;
00353
00355 LRECT2D (
00356 ): xinit(INT32_MAX), yinit(INT32_MAX), xlast(INT32_MIN), ylast(INT32_MIN) { }
00357
00359 LRECT2D (
00360 INT32 xsize,
00361 INT32 ysize
00362 ) : xinit(0), yinit(0), xlast(xsize-1), ylast(ysize-1) { }
00363
00365 LRECT2D (
00366 const LPOINT2D pt
00367 ) : xinit(pt.x), yinit(pt.y), xlast(pt.x), ylast(pt.y) { }
00368
00370 LRECT2D (
00371 INT32 xi,
00372 INT32 yi,
00373 INT32 xl,
00374 INT32 yl
00375 ) : xinit(xi), yinit(yi), xlast(xl), ylast(yl) { }
00376
00378 bool Contains (
00379 INT32 x,
00380 INT32 y
00381 ) const { return (x >= xinit && x <= xlast && y >= yinit && y <= ylast); }
00382
00384 bool Contains (
00385 const LPOINT2D& pt
00386 ) const { return (pt.x >= xinit && pt.x <= xlast && pt.y >= yinit && pt.y <= ylast); }
00387
00389 bool Contains (
00390 const LRECT2D& rhs
00391 ) const { return (rhs.xinit >= xinit && rhs.xlast <= xlast && rhs.yinit >= yinit && rhs.ylast <= ylast); }
00392
00394 void Expand (
00395 const INT32 value
00396 ) { xinit -= value; yinit -= value; xlast += value; ylast += value; }
00397
00399 void Expand (
00400 const INT32 xval,
00401 const INT32 yval
00402 ) { xinit -= xval; yinit -= yval; xlast += xval; ylast += yval; }
00403
00405 void Extend (
00406 const LRECT2D& rect
00407 ) {
00408 if (rect.xinit < xinit) xinit = rect.xinit;
00409 if (rect.yinit < yinit) yinit = rect.yinit;
00410 if (rect.xlast > xlast) xlast = rect.xlast;
00411 if (rect.ylast > ylast) ylast = rect.ylast;
00412 }
00413
00415 void Extend (
00416 const LPOINT2D& pt
00417 ) {
00418 if (pt.x < xinit) xinit = pt.x;
00419 if (pt.x > xlast) xlast = pt.x;
00420 if (pt.y < yinit) yinit = pt.y;
00421 if (pt.y > ylast) ylast = pt.y;
00422 }
00423
00425 void Extend (
00426 const INT32 xval,
00427 const INT32 yval
00428 ) {
00429 if (xval < xinit) xinit = xval;
00430 if (yval < yinit) yinit = yval;
00431 if (xval > xlast) xlast = xval;
00432 if (yval > ylast) ylast = yval;
00433 }
00434
00436 INT32 GetArea (
00437 ) const { return (GetWidth() * GetHeight()); }
00438
00440 void GetBottomLeft (
00441 LPOINT2D& ret
00442 ) const { ret.x = xinit; ret.y = yinit; }
00443
00445 void GetBottomRight (
00446 LPOINT2D& ret
00447 ) const { ret.x = xlast; ret.y = yinit; }
00448
00450 DPOINT2D GetCenter (
00451 ) const { return (DPOINT2D((xlast + xinit)/2.0, (ylast + yinit)/2.0)); }
00452
00454 void GetCenter (
00455 DPOINT2D& ret
00456 ) const { ret.x = (xinit + xlast) / 2.0; ret.y = (yinit + ylast) / 2.0; }
00457
00459 void GetCorners (
00460 LPOINT2D *corners,
00461 bool ClosePoly = false,
00462 bool OrientCCW = false
00463 ) const { LRect2DGetCorners(*this, corners, ClosePoly, OrientCCW); }
00464
00466 int GetDimension (
00467 ) const {
00468 int count(0);
00469 if (xinit < xlast) count ++;
00470 if (yinit < ylast) count ++;
00471 return (count);
00472 }
00473
00475 UINT32 GetHeight (
00476 ) const { return (ylast - yinit + 1); }
00477
00479 LPOINT2D GetMaxXMaxY (
00480 ) const { return (LPOINT2D(xlast,ylast)); }
00481
00483 LPOINT2D GetMaxXMinY (
00484 ) const { return (LPOINT2D(xlast,yinit)); }
00485
00487 LPOINT2D GetMinXMaxY (
00488 ) const { return (LPOINT2D(xinit,ylast)); }
00489
00491 LPOINT2D GetMinXMinY (
00492 ) const { return (LPOINT2D(xinit,yinit)); }
00493
00495 void GetSize (
00496 LPOINT2D& ret
00497 ) const { ret.x = xlast - xinit; ret.y = ylast - yinit; }
00498
00500 void GetTopLeft (
00501 LPOINT2D& ret
00502 ) const { ret.x = xinit; ret.y = ylast; }
00503
00505 void GetTopRight (
00506 LPOINT2D& ret
00507 ) const { ret.x = xlast; ret.y = ylast; }
00508
00510 UINT32 GetWidth (
00511 ) const { return (xlast - xinit + 1); }
00512
00514 bool IniRead (
00515 INIHANDLE IniHandle,
00516 const char *IniGroup,
00517 const char *IniName
00518 ) { return (_iniRead(IniHandle,IniGroup,IniName,INITYPE_INT32,this,4) == 4); }
00519
00521 void IniWrite (
00522 INIHANDLE IniHandle,
00523 const char *IniGroup,
00524 const char *IniName
00525 ) const { _iniWrite(IniHandle,IniGroup,IniName,INITYPE_INT32,this,4); }
00526
00528 void Intersect (
00529 const LRECT2D& rect
00530 ) {
00531 if (rect.IsValid()) {
00532 if (rect.xinit > xinit) xinit = rect.xinit;
00533 if (rect.yinit > yinit) yinit = rect.yinit;
00534 if (rect.xlast < xlast) xlast = rect.xlast;
00535 if (rect.ylast < ylast) ylast = rect.ylast;
00536 }
00537 else {
00538 *this = rect;
00539 }
00540 return;
00541 }
00542
00544 bool IsNonEmpty (
00545 ) const { return (xinit < xlast && yinit < ylast); }
00546
00548 bool IsValid (
00549 ) const { return (xinit <= xlast && yinit <= ylast); }
00550
00552 void Limit (
00553 LPOINT2D& point
00554 ) const {
00555 if (point.x < xinit) point.x = xinit; else if (point.x > xlast) point.x = xlast;
00556 if (point.y < yinit) point.y = yinit; else if (point.y > ylast) point.y = ylast;
00557 }
00558
00560 void Limit (
00561 DPOINT2D& point
00562 ) const {
00563 if (point.x < xinit) point.x = xinit; else if (point.x > xlast) point.x = xlast;
00564 if (point.y < yinit) point.y = yinit; else if (point.y > ylast) point.y = ylast;
00565 }
00566
00568 bool Overlaps (
00569 const LRECT2D& rhs
00570 ) const {
00571 return (!(rhs.xlast < xinit || rhs.xinit > xlast || rhs.ylast < yinit || rhs.yinit > ylast));
00572 }
00573
00575 void Set (
00576 INT32 x1,
00577 INT32 y1,
00578 INT32 x2,
00579 INT32 y2
00580 ) { xinit = x1; yinit = y1; xlast = x2; ylast = y2; }
00581
00586 void SetInvalid (
00587 ) { xinit = yinit = INT32_MAX; xlast = ylast = INT32_MIN; }
00588
00590 void SwapBytes (
00591 ) { ::SwapBytes(xinit); ::SwapBytes(xlast); ::SwapBytes(yinit); ::SwapBytes(ylast); }
00592
00593 #ifndef GENERATING_DOXYGEN_OUTPUT
00594
00595 CHECKSIZE(16);
00596 #endif
00597 };
00598
00599 inline bool operator== (
00600 const LRECT2D& lhs,
00601 const LRECT2D& rhs
00602 ) {
00603 return (lhs.xinit == rhs.xinit && lhs.xlast == rhs.xlast && lhs.yinit == rhs.yinit && lhs.ylast == rhs.ylast);
00604 }
00605
00606 inline bool operator!= (
00607 const LRECT2D& lhs,
00608 const LRECT2D& rhs
00609 ) {
00610 return (!operator==(lhs,rhs));
00611 }
00612
00613
00614
00615
00617 struct LRECT3D : public LRECT2D {
00618
00619 INT32 zinit;
00620 INT32 zlast;
00621
00623 LRECT3D (
00624 ) : LRECT2D(), zinit(INT32_MAX), zlast(INT32_MIN) { }
00625
00627 LRECT3D (
00628 const LPOINT3D& pt
00629 ) : LRECT2D(pt), zinit(pt.z), zlast(pt.z) { }
00630
00634 LRECT3D (
00635 const LPOINT3D& pt1,
00636 const LPOINT3D& pt2
00637 ) {
00638 if (pt1.x < pt2.x) {
00639 xinit = pt1.x;
00640 xlast = pt2.x;
00641 }
00642 else {
00643 xinit = pt2.x;
00644 xlast = pt1.x;
00645 }
00646 if (pt1.y < pt2.y) {
00647 yinit = pt1.y;
00648 ylast = pt2.y;
00649 }
00650 else {
00651 yinit = pt2.y;
00652 ylast = pt1.y;
00653 }
00654 if (pt1.z < pt2.z) {
00655 zinit = pt1.z;
00656 zlast = pt2.z;
00657 }
00658 else {
00659 zinit = pt2.z;
00660 zlast = pt1.z;
00661 }
00662 }
00663
00665 LRECT3D (
00666 const LRECT2D& rect
00667 ) : LRECT2D(rect), zinit(0), zlast(0) { }
00668
00670 LRECT3D (
00671 const LRECT2D& rect,
00672 INT32 zmin,
00673 INT32 zmax
00674 ) : LRECT2D(rect), zinit(zmin), zlast(zmax) { }
00675
00677 LRECT3D& operator= (
00678 const LPOINT3D& pt
00679 ) {
00680 xinit = xlast = pt.x;
00681 yinit = ylast = pt.y;
00682 zinit = zlast = pt.z;
00683 return (*this);
00684 }
00685
00687 bool Contains (
00688 const LPOINT3D& pt
00689 ) const { return (LRECT2D::Contains(pt) && pt.z >= zinit && pt.z <= zlast); }
00690
00692 bool Contains (
00693 const LRECT3D& rhs
00694 ) const { return (LRECT2D::Contains(rhs) && rhs.zinit >= zinit && rhs.zlast <= zlast); }
00695
00697 void Expand (
00698 const INT32 value
00699 ) {
00700 LRECT2D::Expand(value);
00701 zinit -= value; zlast += value;
00702 return;
00703 }
00704
00706 void Expand (
00707 const INT32 xval,
00708 const INT32 yval
00709 ) { LRECT2D::Expand(xval, yval); }
00710
00712 void Extend (
00713 const INT32 xval,
00714 const INT32 yval
00715 ) { LRECT2D::Extend(xval, yval); }
00716
00718 void Extend (
00719 const INT32 xval,
00720 const INT32 yval,
00721 const INT32 zval
00722 ) {
00723 LRECT2D::Extend(xval, yval);
00724 if (zval < zinit) zinit = zval;
00725 if (zval > zlast) zlast = zval;
00726 return;
00727 }
00728
00730 void Extend (
00731 const LRECT3D& rect
00732 ) {
00733 LRECT2D::Extend(rect);
00734 if (rect.zinit < zinit) zinit = rect.zinit;
00735 if (rect.zlast > zlast) zlast = rect.zlast;
00736 return;
00737 }
00738
00740 void Extend (
00741 const LPOINT2D& pt
00742 ) { LRECT2D::Extend(pt); }
00743
00745 void Extend (
00746 const LPOINT3D& pt
00747 ) {
00748 LRECT2D::Extend(pt);
00749 if (pt.z < zinit) zinit = pt.z;
00750 if (pt.z > zlast) zlast = pt.z;
00751 return;
00752 }
00753
00755 DPOINT3D GetCenter (
00756 ) const { return (DPOINT3D((xinit+xlast)/2.0,(yinit+ylast)/2.0,(zinit+zlast)/2.0)); }
00757
00759 void GetCenter (
00760 DPOINT3D& ret
00761 ) const {
00762 ret.x = (xinit + xlast) / 2.0;
00763 ret.y = (yinit + ylast) / 2.0;
00764 ret.z = (zinit + zlast) / 2.0;
00765 }
00766
00768 INT32 GetDepth (
00769 ) const { return (zlast - zinit); }
00770
00772 int GetDimension (
00773 ) const {
00774 int count(LRECT2D::GetDimension());
00775 if (zinit < zlast) count ++;
00776 return (count);
00777 }
00778
00780 void GetMaximum (
00781 LPOINT3D& maximum
00782 ) const { maximum.x = xlast; maximum.y = ylast; maximum.z = zlast; }
00783
00785 void GetMinimum (
00786 LPOINT3D& minimum
00787 ) const { minimum.x = xinit; minimum.y = yinit; minimum.z = zinit; }
00788
00790 void GetSize (
00791 LPOINT3D& ret
00792 ) const {
00793 ret.x = xlast - xinit;
00794 ret.y = ylast - yinit;
00795 ret.z = zlast - zinit;
00796 }
00797
00799 INT32 GetVolume (
00800 ) const { return (LRECT2D::GetArea() * (zlast - zinit)); }
00801
00803 bool IniRead (
00804 INIHANDLE IniHandle,
00805 const char *IniGroup,
00806 const char *IniName
00807 ) { return (_iniRead(IniHandle,IniGroup,IniName,INITYPE_INT32,this,6) == 6); }
00808
00810 void IniWrite (
00811 INIHANDLE IniHandle,
00812 const char *IniGroup,
00813 const char *IniName
00814 ) const { _iniWrite(IniHandle,IniGroup,IniName,INITYPE_INT32,this,6); }
00815
00817 void Intersect (
00818 const LRECT3D& rect
00819 ) {
00820 if (rect.IsValid()) {
00821 LRECT2D::Intersect(rect);
00822 if (rect.zinit > zinit) zinit = rect.zinit;
00823 if (rect.zlast < zlast) zlast = rect.zlast;
00824 }
00825 else {
00826 *this = rect;
00827 }
00828 return;
00829 }
00830
00832 bool IsValid (
00833 ) const { return (LRECT2D::IsValid() && zinit <= zlast); }
00834
00836 bool Overlaps (
00837 const LRECT3D& rhs
00838 ) const { return (LRECT2D::Overlaps(rhs) && !(rhs.zlast < zinit || rhs.zinit > zlast)); }
00839
00841 void Set (
00842 INT32 x1,
00843 INT32 y1,
00844 INT32 x2,
00845 INT32 y2
00846 ) { xinit = x1; yinit = y1; xlast = x2; ylast = y2; zinit = zlast = 0; }
00847
00849 void Set (
00850 INT32 xmin,
00851 INT32 ymin,
00852 INT32 zmin,
00853 INT32 xmax,
00854 INT32 ymax,
00855 INT32 zmax
00856 ) { xinit = xmin; yinit = ymin; zinit = zmin; xlast = xmax; ylast = ymax; zlast = zmax; }
00857
00862 void SetInvalid (
00863 ) { LRECT2D::SetInvalid(); zinit = INT32_MAX; zlast = INT32_MIN; }
00864
00866 void SwapBytes (
00867 ) { ::SwapBytes(xinit); ::SwapBytes(xlast); ::SwapBytes(yinit); ::SwapBytes(ylast); ::SwapBytes(zinit); ::SwapBytes(zlast); }
00868
00869 #ifndef GENERATING_DOXYGEN_OUTPUT
00870
00871 CHECKSIZE(24);
00872 #endif
00873 };
00874
00875
00876
00878 struct DRECT2D {
00879
00880 double xinit;
00881 double yinit;
00882 double xlast;
00883 double ylast;
00884
00886 DRECT2D (
00887 ) : xinit(DBL_MAX), yinit(DBL_MAX), xlast(-DBL_MAX), ylast(-DBL_MAX) {
00888 }
00889
00891 DRECT2D (
00892 const FPOINT2D& pt
00893 ) : xinit(pt.x), yinit(pt.y), xlast(pt.x), ylast(pt.y) { }
00894
00896 DRECT2D (
00897 const DPOINT2D& pt
00898 ) : xinit(pt.x), yinit(pt.y), xlast(pt.x), ylast(pt.y) { }
00899
00903 DRECT2D (
00904 const DPOINT2D& pt1,
00905 const DPOINT2D& pt2
00906 ) { SetCorners(pt1,pt2); }
00907
00908 DRECT2D (
00909 double xi,
00910 double yi,
00911 double xl,
00912 double yl
00913 ) : xinit(xi), yinit(yi), xlast(xl), ylast(yl) { }
00914
00916 DRECT2D (
00917 const LRECT2D& rect
00918 ) : xinit(rect.xinit), yinit(rect.yinit), xlast(rect.xlast), ylast(rect.ylast) { }
00919
00921 DRECT2D& operator= (
00922 const DPOINT2D& pt
00923 ) { xinit = xlast = pt.x; yinit = ylast = pt.y; return (*this); }
00924
00926 DRECT2D& operator= (
00927 const LRECT2D& rhs
00928 ) { xinit = rhs.xinit; yinit = rhs.yinit; xlast = rhs.xlast; ylast = rhs.ylast; return (*this); }
00929
00931 void AlignToMultiple (
00932 double AlignSize,
00933 double RoundTolerance = .000001
00934 ) {
00935 xinit = floor(xinit / AlignSize + RoundTolerance) * AlignSize;
00936 yinit = floor(yinit / AlignSize + RoundTolerance) * AlignSize;
00937 xlast = ceil(xlast / AlignSize - RoundTolerance) * AlignSize;
00938 ylast = ceil(ylast / AlignSize - RoundTolerance) * AlignSize;
00939 return;
00940 }
00941
00943 void ClipTo (
00944 const DRECT2D& rect
00945 ) {
00946 if (xinit < rect.xinit) xinit = rect.xinit;
00947 if (yinit < rect.yinit) yinit = rect.yinit;
00948 if (xlast > rect.xlast) xlast = rect.xlast;
00949 if (ylast > rect.ylast) ylast = rect.ylast;
00950 return;
00951 }
00952
00957 bool ComputeEdgePoint (
00958 const DPOINT2D& OutsidePt,
00959 DPOINT2D& EdgePt
00960 ) const { return (DRect2DComputeEdgePoint(*this, OutsidePt, EdgePt)); }
00961
00963 bool Contains (
00964 double x,
00965 double y
00966 ) const { return (x >= xinit && x <= xlast && y >= yinit && y <= ylast); }
00967
00969 bool Contains (
00970 const DPOINT2D& pt
00971 ) const { return (pt.x >= xinit && pt.x <= xlast && pt.y >= yinit && pt.y <= ylast); }
00972
00974 bool Contains (
00975 const DRECT2D& rhs
00976 ) const { return (rhs.xinit >= xinit && rhs.xlast <= xlast && rhs.yinit >= yinit && rhs.ylast <= ylast); }
00977
00979 void Expand (
00980 const double value
00981 ) { xinit -= value; yinit -= value; xlast += value; ylast += value; }
00982
00984 void Expand (
00985 const double xval,
00986 const double yval
00987 ) { xinit -= xval; yinit -= yval; xlast += xval; ylast += yval; }
00988
00990 void Extend (
00991 const double xval,
00992 const double yval
00993 ) {
00994 if (xval < xinit) xinit = xval;
00995 if (yval < yinit) yinit = yval;
00996 if (xval > xlast) xlast = xval;
00997 if (yval > ylast) ylast = yval;
00998 return;
00999 }
01000
01002 void Extend (
01003 const DRECT2D& rect
01004 ) {
01005 if (rect.xinit < xinit) xinit = rect.xinit;
01006 if (rect.yinit < yinit) yinit = rect.yinit;
01007 if (rect.xlast > xlast) xlast = rect.xlast;
01008 if (rect.ylast > ylast) ylast = rect.ylast;
01009 return;
01010 }
01011
01013 void Extend (
01014 const DPOINT2D& pt
01015 ) {
01016 if (pt.x < xinit) xinit = pt.x;
01017 if (pt.x > xlast) xlast = pt.x;
01018 if (pt.y < yinit) yinit = pt.y;
01019 if (pt.y > ylast) ylast = pt.y;
01020 return;
01021 }
01022
01024 double GetArea (
01025 ) const { return ((xlast - xinit) * (ylast - yinit)); }
01026
01028 void GetBottomLeft (
01029 DPOINT2D& ret
01030 ) const { ret.x = xinit; ret.y = yinit; }
01031
01033 void GetBottomRight (
01034 DPOINT2D& ret
01035 ) const { ret.x = xlast; ret.y = yinit; }
01036
01038 DPOINT2D GetCenter (
01039 ) const { return (DPOINT2D((xlast + xinit)/2.0, (ylast + yinit)/2.0)); }
01040
01042 void GetCenter (
01043 DPOINT2D& ret
01044 ) const { ret.x = (xinit + xlast) / 2.0; ret.y = (yinit + ylast) / 2.0; }
01045
01047 void GetCorners (
01048 DPOINT2D *corners,
01049 bool ClosePoly = false,
01050 bool OrientCCW = false
01051 ) const { DRect2DGetCorners(*this, corners, ClosePoly, OrientCCW); }
01052
01054 void GetCorners (
01055 DPOINT3D *corners,
01056 bool ClosePoly = false,
01057 bool OrientCCW = false
01058 ) const { DRect2DGetCorners(*this, corners, ClosePoly, OrientCCW); }
01059
01061 int GetDimension (
01062 ) const {
01063 int count(0);
01064 if (xinit < xlast) count ++;
01065 if (yinit < ylast) count ++;
01066 return (count);
01067 }
01068
01071 double GetDistance (
01072 const DRECT2D& rect
01073 ) const { return (DRect2DGetDistance(*this, rect)); }
01074
01076 double GetHeight (
01077 ) const { return (ylast - yinit); }
01078
01082 double GetMaxDistance (
01083 const DRECT2D& rect
01084 ) const { return (DRect2DGetMaxDistance(*this, rect)); }
01085
01089 double GetMaxDistanceSquared (
01090 const DRECT2D& rect
01091 ) const { return (DRect2DGetMaxDistanceSquared(*this, rect)); }
01092
01094 DEPRECATED void GetRect (
01095 LRECT2D& rect
01096 ) const { GetRectRoundNoLimit(rect); }
01097
01099 void GetRectRoundLimited (
01100 LRECT2D& rect
01101 ) const {
01102 rect.xinit = static_cast<INT32>(FAST_ROUND_LIMITED(xinit));
01103 rect.yinit = static_cast<INT32>(FAST_ROUND_LIMITED(yinit));
01104 rect.xlast = static_cast<INT32>(FAST_ROUND_LIMITED(xlast));
01105 rect.ylast = static_cast<INT32>(FAST_ROUND_LIMITED(ylast));
01106 }
01107
01109 void GetRectRoundNoLimit (
01110 LRECT2D& rect
01111 ) const {
01112 rect.xinit = static_cast<INT32>(FAST_ROUND_NOLIMIT(xinit));
01113 rect.yinit = static_cast<INT32>(FAST_ROUND_NOLIMIT(yinit));
01114 rect.xlast = static_cast<INT32>(FAST_ROUND_NOLIMIT(xlast));
01115 rect.ylast = static_cast<INT32>(FAST_ROUND_NOLIMIT(ylast));
01116 }
01117
01119 void GetRectRoundPositive (
01120 LRECT2D& rect
01121 ) const {
01122 rect.xinit = static_cast<INT32>(FAST_ROUND_POSITIVE(xinit));
01123 rect.yinit = static_cast<INT32>(FAST_ROUND_POSITIVE(yinit));
01124 rect.xlast = static_cast<INT32>(FAST_ROUND_POSITIVE(xlast));
01125 rect.ylast = static_cast<INT32>(FAST_ROUND_POSITIVE(ylast));
01126 }
01127
01129 void GetRectTruncate (
01130 LRECT2D& rect
01131 ) const {
01132 rect.xinit = static_cast<INT32>(FAST_TRUNCATE(xinit));
01133 rect.yinit = static_cast<INT32>(FAST_TRUNCATE(yinit));
01134 rect.xlast = static_cast<INT32>(FAST_TRUNCATE(xlast));
01135 rect.ylast = static_cast<INT32>(FAST_TRUNCATE(ylast));
01136 }
01137
01139 void GetSize (
01140 DPOINT2D& ret
01141 ) const { ret.x = xlast - xinit; ret.y = ylast - yinit; }
01142
01144 void GetTopLeft (
01145 DPOINT2D& ret
01146 ) const { ret.x = xinit; ret.y = ylast; }
01147
01149 void GetTopRight (
01150 DPOINT2D& ret
01151 ) const { ret.x = xlast; ret.y = ylast; }
01152
01154 double GetWidth (
01155 ) const { return (xlast - xinit); }
01156
01158 bool IniRead (
01159 INIHANDLE IniHandle,
01160 const char *IniGroup,
01161 const char *IniName
01162 ) { return (_iniRead(IniHandle,IniGroup,IniName,INITYPE_DRECT2D,this,1) == 1); }
01163
01165 bool IniRead (
01166 INIHANDLE IniHandle,
01167 const char *IniGroup,
01168 const char *IniName,
01169 const DRECT2D& dft
01170 ) { if (IniRead(IniHandle,IniGroup,IniName)) return (true); else { *this = dft; return (false); } }
01171
01173 void IniWrite (
01174 INIHANDLE IniHandle,
01175 const char *IniGroup,
01176 const char *IniName
01177 ) const { _iniWrite(IniHandle,IniGroup,IniName,INITYPE_DRECT2D,this,1); }
01178
01180 void Intersect (
01181 const DRECT2D& rect
01182 ) {
01183 if (rect.IsValid()) {
01184 if (rect.xinit > xinit) xinit = rect.xinit;
01185 if (rect.yinit > yinit) yinit = rect.yinit;
01186 if (rect.xlast < xlast) xlast = rect.xlast;
01187 if (rect.ylast < ylast) ylast = rect.ylast;
01188 }
01189 else {
01190 *this = rect;
01191 }
01192 }
01193
01195 bool Intersects (
01196 const DRECT2D& rhs
01197 ) const { return (rhs.xlast > xinit && rhs.xinit < xlast && rhs.ylast > yinit && rhs.yinit < ylast); }
01198
01203 bool IsEquivalentTo (
01204 const DRECT2D& rhs,
01205 double threshold = 0.0
01206 ) const { return (DRect2DIsEquivalentTo(*this, rhs, threshold)); }
01207
01209 bool IsNonEmpty (
01210 ) const { return (xinit < xlast && yinit < ylast); }
01211
01213 bool IsValid (
01214 ) const { return (xinit <= xlast && yinit <= ylast); }
01215
01217 void Limit (
01218 DPOINT2D& point
01219 ) const {
01220 if (point.x < xinit) point.x = xinit; else if (point.x > xlast) point.x = xlast;
01221 if (point.y < yinit) point.y = yinit; else if (point.y > ylast) point.y = ylast;
01222 }
01223
01225 bool Overlaps (
01226 const DRECT2D& rhs
01227 ) const { return (!(rhs.xlast < xinit || rhs.xinit > xlast || rhs.ylast < yinit || rhs.yinit > ylast)); }
01228
01230 void Set (
01231 double x1,
01232 double y1,
01233 double x2,
01234 double y2
01235 ) { xinit = x1; yinit = y1; xlast = x2; ylast = y2; }
01236
01238 void SetCorners (
01239 const DPOINT2D pt1,
01240 const DPOINT2D pt2
01241 ) {
01242 if (pt1.x < pt2.x) { xinit = pt1.x; xlast = pt2.x; }
01243 else { xinit = pt2.x; xlast = pt1.x; }
01244 if (pt1.y < pt2.y) { yinit = pt1.y; ylast = pt2.y; }
01245 else { yinit = pt2.y; ylast = pt1.y; }
01246 }
01247
01252 void SetInvalid (
01253 ) { xinit = yinit = DBL_MAX; xlast = ylast = -DBL_MAX; }
01254
01256 void SwapBytes (
01257 ) { ::SwapBytes(xinit); ::SwapBytes(xlast); ::SwapBytes(yinit); ::SwapBytes(ylast); }
01258
01259 #ifndef GENERATING_DOXYGEN_OUTPUT
01260
01261 CHECKSIZE(32);
01262 #endif
01263 };
01264
01265 inline bool operator== (
01266 const DRECT2D& lhs,
01267 const DRECT2D& rhs
01268 ) {
01269 return (lhs.xinit == rhs.xinit && lhs.xlast == rhs.xlast && lhs.yinit == rhs.yinit && lhs.ylast == rhs.ylast);
01270 }
01271
01272 inline bool operator!= (
01273 const DRECT2D& lhs,
01274 const DRECT2D& rhs
01275 ) {
01276 return (!operator==(lhs,rhs));
01277 }
01278
01279 inline void SwapBytes (
01280 DRECT2D& rect
01281 ) {
01282 rect.SwapBytes();
01283 }
01284
01286 inline int IniRead (INIHANDLE hdl, const char *group, const char *field, DRECT2D& value) { return (_iniRead(hdl,group,field,INITYPE_DRECT2D,&value,1)); }
01287
01289 inline int IniRead (INIHANDLE hdl, const char *group, const char *field, DRECT2D& value, const DRECT2D& dft) { value = dft; return (IniRead(hdl,group,field,value)); }
01290
01292 inline int IniWrite (INIHANDLE hdl, const char *group, const char *field, const DRECT2D& value) { return (_iniWrite(hdl,group,field,INITYPE_DRECT2D,&value,1)); }
01293
01294
01295
01296
01298 struct DRECT3D : public DRECT2D {
01299
01300 double zinit;
01301 double zlast;
01302
01304 DRECT3D (
01305 ) : DRECT2D(), zinit(DBL_MAX), zlast(-DBL_MAX) { }
01306
01308 DRECT3D (
01309 const FPOINT3D& pt
01310 ) : DRECT2D(pt), zinit(pt.z), zlast(pt.z) { }
01311
01313 DRECT3D (
01314 const DPOINT3D& pt
01315 ) : DRECT2D(pt), zinit(pt.z), zlast(pt.z) { }
01316
01320 DRECT3D (
01321 const DPOINT3D& pt1,
01322 const DPOINT3D& pt2
01323 ) {
01324 if (pt1.x < pt2.x) {
01325 xinit = pt1.x;
01326 xlast = pt2.x;
01327 }
01328 else {
01329 xinit = pt2.x;
01330 xlast = pt1.x;
01331 }
01332 if (pt1.y < pt2.y) {
01333 yinit = pt1.y;
01334 ylast = pt2.y;
01335 }
01336 else {
01337 yinit = pt2.y;
01338 ylast = pt1.y;
01339 }
01340 if (pt1.z < pt2.z) {
01341 zinit = pt1.z;
01342 zlast = pt2.z;
01343 }
01344 else {
01345 zinit = pt2.z;
01346 zlast = pt1.z;
01347 }
01348 }
01349
01351 DRECT3D (
01352 const DRECT2D& rect
01353 ) : DRECT2D(rect), zinit(0.0), zlast(0.0) { }
01354
01356 DRECT3D (
01357 const DRECT2D& rect,
01358 double zmin,
01359 double zmax
01360 ) : DRECT2D(rect), zinit(zmin), zlast(zmax) { }
01361
01363 DRECT3D& operator= (
01364 const DPOINT3D& pt
01365 ) {
01366 xinit = xlast = pt.x;
01367 yinit = ylast = pt.y;
01368 zinit = zlast = pt.z;
01369 return (*this);
01370 }
01371
01373 bool Contains (
01374 const DPOINT3D& pt
01375 ) const { return (DRECT2D::Contains(pt) && pt.z >= zinit && pt.z <= zlast); }
01376
01378 bool Contains (
01379 const DRECT3D& rhs
01380 ) const { return (DRECT2D::Contains(rhs) && rhs.zinit >= zinit && rhs.zlast <= zlast); }
01381
01383 void Expand (
01384 const double value
01385 ) {
01386 DRECT2D::Expand(value);
01387 zinit -= value; zlast += value;
01388 return;
01389 }
01390
01392 void Expand (
01393 const double xval,
01394 const double yval
01395 ) { DRECT2D::Expand(xval, yval); }
01396
01398 void Extend (
01399 const double xval,
01400 const double yval
01401 ) { DRECT2D::Extend(xval, yval); }
01402
01404 void Extend (
01405 const double xval,
01406 const double yval,
01407 const double zval
01408 ) {
01409 DRECT2D::Extend(xval, yval);
01410 if (zval < zinit) zinit = zval;
01411 if (zval > zlast) zlast = zval;
01412 return;
01413 }
01414
01416 void Extend (
01417 const DRECT3D& rect
01418 ) {
01419 DRECT2D::Extend(rect);
01420 if (rect.zinit < zinit) zinit = rect.zinit;
01421 if (rect.zlast > zlast) zlast = rect.zlast;
01422 return;
01423 }
01424
01426 void Extend (
01427 const DPOINT2D& pt
01428 ) { DRECT2D::Extend(pt); }
01429
01431 void Extend (
01432 const DPOINT3D& pt
01433 ) {
01434 DRECT2D::Extend(pt);
01435 if (pt.z < zinit) zinit = pt.z;
01436 if (pt.z > zlast) zlast = pt.z;
01437 return;
01438 }
01439
01441 DPOINT3D GetCenter (
01442 ) const { return (DPOINT3D((xinit+xlast)/2.0,(yinit+ylast)/2.0,(zinit+zlast)/2.0)); }
01443
01445 void GetCenter (
01446 DPOINT3D& ret
01447 ) const {
01448 ret.x = (xinit + xlast) / 2.0;
01449 ret.y = (yinit + ylast) / 2.0;
01450 ret.z = (zinit + zlast) / 2.0;
01451 return;
01452 }
01453
01455 double GetDepth (
01456 ) const { return (zlast - zinit); }
01457
01459 int GetDimension (
01460 ) const {
01461 int count(DRECT2D::GetDimension());
01462 if (zinit < zlast) count ++;
01463 return (count);
01464 }
01465
01467 void GetMaximum (
01468 DPOINT3D& maximum
01469 ) const { maximum.x = xlast; maximum.y = ylast; maximum.z = zlast; }
01470
01472 void GetMinimum (
01473 DPOINT3D& minimum
01474 ) const { minimum.x = xinit; minimum.y = yinit; minimum.z = zinit; }
01475
01477 void GetSize (
01478 DPOINT3D& ret
01479 ) const {
01480 ret.x = xlast - xinit;
01481 ret.y = ylast - yinit;
01482 ret.z = zlast - zinit;
01483 return;
01484 }
01485
01487 double GetVolume (
01488 ) const { return (DRECT2D::GetArea() * (zlast - zinit)); }
01489
01491 bool IniRead (
01492 INIHANDLE IniHandle,
01493 const char *IniGroup,
01494 const char *IniName
01495 ) { return (_iniRead(IniHandle,IniGroup,IniName,INITYPE_Double,this,6) == 6); }
01496
01498 void IniWrite (
01499 INIHANDLE IniHandle,
01500 const char *IniGroup,
01501 const char *IniName
01502 ) const { _iniWrite(IniHandle,IniGroup,IniName,INITYPE_Double,this,6); }
01503
01505 void Intersect (
01506 const DRECT3D& rect
01507 ) {
01508 if (rect.IsValid()) {
01509 DRECT2D::Intersect(rect);
01510 if (rect.zinit > zinit) zinit = rect.zinit;
01511 if (rect.zlast < zlast) zlast = rect.zlast;
01512 }
01513 else {
01514 *this = rect;
01515 }
01516 return;
01517 }
01518
01520 bool IsValid (
01521 ) const { return (DRECT2D::IsValid() && zinit <= zlast); }
01522
01524 bool Overlaps (
01525 const DRECT3D& rhs
01526 ) const { return (DRECT2D::Overlaps(rhs) && !(rhs.zlast < zinit || rhs.zinit > zlast)); }
01527
01529 void Set (
01530 double x1,
01531 double y1,
01532 double x2,
01533 double y2
01534 ) { xinit = x1; yinit = y1; xlast = x2; ylast = y2; zinit = zlast = 0.0; }
01535
01537 void Set (
01538 double xmin,
01539 double ymin,
01540 double zmin,
01541 double xmax,
01542 double ymax,
01543 double zmax
01544 ) { xinit = xmin; yinit = ymin; zinit = zmin; xlast = xmax; ylast = ymax; zlast = zmax; }
01545
01551 void SetInvalid (
01552 ) { DRECT2D::SetInvalid(); zinit = DBL_MAX; zlast = -DBL_MAX; }
01553
01555 void SwapBytes (
01556 ) { ::SwapBytes(xinit); ::SwapBytes(xlast); ::SwapBytes(yinit); ::SwapBytes(ylast); ::SwapBytes(zinit); ::SwapBytes(zlast); }
01557
01558 #ifndef GENERATING_DOXYGEN_OUTPUT
01559
01560 CHECKSIZE(48);
01561 #endif
01562 };
01563
01564 inline bool operator== (
01565 const DRECT3D& lhs,
01566 const DRECT3D& rhs
01567 ) {
01568 return (lhs.xinit == rhs.xinit && lhs.xlast == rhs.xlast && lhs.yinit == rhs.yinit && lhs.ylast == rhs.ylast && lhs.zinit == rhs.zinit && lhs.zlast == rhs.zlast);
01569 }
01570
01571 inline bool operator!= (
01572 const DRECT3D& lhs,
01573 const DRECT3D& rhs
01574 ) {
01575 return (!operator==(lhs,rhs));
01576 }
01577
01578 inline void SwapBytes (
01579 DRECT3D& rect
01580 ) {
01581 rect.SwapBytes();
01582 }
01583
01584
01585
01586
01587 #endif