mi32/rect.h

Go to the documentation of this file.
00001 /**
00002  * \file rect.h <mi32/rect.h>
00003  * \brief Definitions for 2D and 3D rectangle structures
00004  *
00005  * \if NODOC
00006  * $Id: rect.h_v 1.42 2003/11/28 16:45:16 scowan Exp $
00007  *
00008  * $Log: rect.h_v $
00009  * Revision 1.42  2003/11/28 16:45:16  scowan
00010  * Added is equiv to method.
00011  *
00012  * Revision 1.41  2003/11/12 13:20:00  mju
00013  * Add drect3d.getMinimum/Maximum.
00014  *
00015  * Revision 1.40  2003/09/15 13:49:56  fileserver!dwilliss
00016  * Doxygen
00017  *
00018  * Revision 1.39  2003/04/15 13:34:06  mju
00019  * Add IniRead/Write methods.
00020  *
00021  * Revision 1.38  2003/02/21 15:19:44  mju
00022  * Add SwapBytes method.
00023  *
00024  * Revision 1.37  2003/02/04 20:24:31  vdronov
00025  * ctor for DRECTXD from FPOINTXD
00026  *
00027  * Revision 1.36  2002/12/04 16:27:47  dwilliss
00028  * Fixed a compiler warning
00029  *
00030  * Revision 1.35  2002/08/19 17:56:04  mju
00031  * Change GetArea() to do getwidth*getheight.
00032  *
00033  * Revision 1.34  2002/08/19 17:35:37  mju
00034  * In LRECT2D ctor init to 'empty' rectangle.
00035  *
00036  * Revision 1.33  2002/08/13 14:23:01  scowan
00037  * Added more distance methods.
00038  *
00039  * Revision 1.32  2002/07/02 20:17:04  scowan
00040  * Added get corners for 3d point array.
00041  *
00042  * Revision 1.31  2002/06/13 21:50:24  scowan
00043  * Added compute edge method.
00044  *
00045  * Revision 1.30  2002/01/22 18:52:36  scowan
00046  * Nothing.
00047  *
00048  * Revision 1.29  2001/12/11 17:44:34  scowan
00049  * Added swap bytes functions for rects.
00050  *
00051  * Revision 1.28  2001/09/26 17:26:09  scowan
00052  * Fixed equality operator.
00053  *
00054  * Revision 1.26  2001/02/07 23:01:20  scowan
00055  * Added 3D extend method.
00056  *
00057  * Revision 1.25  2001/01/17 14:45:37  mju
00058  * Add LRECT2D:Extend(x,y).
00059  *
00060  * Revision 1.24  2000/12/20 21:44:42  mju
00061  * Add Limit() method.
00062  *
00063  * Revision 1.23  2000/11/28 15:26:41  scowan
00064  * Added more methods.
00065  *
00066  * Revision 1.22  2000/11/07 15:58:47  scowan
00067  * Added casting that I believe Dave finds so unnecessary.
00068  *
00069  * Revision 1.21  2000/11/06 15:28:16  asavant
00070  * equality/inequality operators should return bool
00071  *
00072  * Revision 1.20  2000/11/03 21:15:13  mju
00073  * Add equality/inequality operators.
00074  *
00075  * Revision 1.19  2000/09/20 22:28:52  dwilliss
00076  * Added a few methods
00077  *
00078  * Revision 1.18  2000/08/02 14:22:02  dwilliss
00079  * LRECT2D didn't have a SetInvalid() method.
00080  *
00081  * Revision 1.17  2000/07/11 19:37:00  sparsons
00082  * Genitor documentation.
00083  *
00084  * Revision 1.16  2000/03/07 20:43:43  scowan
00085  * *** empty log message ***
00086  *
00087  * Revision 1.15  2000/01/26 15:51:44  mju
00088  * Don't use STL as MSVC won't inline it.
00089  *
00090  * Revision 1.14  2000/01/07 20:54:49  mju
00091  * Fix DRECT2D::GetTopRight.
00092  *
00093  * Revision 1.13  1999/12/23 00:58:23  scowan
00094  * Yet more methods.
00095  *
00096  * Revision 1.12  1999/12/22 16:52:23  mju
00097  * Add SetInvalid() for DRECT2D/3D.
00098  *
00099  * Revision 1.11  1999/12/15 17:19:53  mju
00100  * Add options for GetCorners and make non-inline.
00101  *
00102  * Revision 1.10  1999/12/15 16:41:06  mju
00103  * Restore DRECT3D::GetCenter which returns DPOINT3D.
00104  *
00105  * Revision 1.9  1999/12/15 15:55:44  mju
00106  * All reference for all "Get" methods that return non-scalar.
00107  * Eliminate return-by-value for all Get methods except GetCenter.
00108  * Add GetCorners() for RECT2D types.
00109  *
00110  * Revision 1.8  1999/12/02 23:23:43  mju
00111  * Add ClipTo method.
00112  *
00113  * Revision 1.7  1999/10/05 21:57:59  dwilliss
00114  * Seems to me like LRECT2D should have same methods as DRECT2D, no?
00115  *
00116  * Revision 1.6  1999/09/07 13:51:40  mju
00117  * Add constructors and methods for LRECT2D.
00118  *
00119  * Revision 1.5  1999/05/19  13:51:54  mju
00120  * Add Expand method with different X/Y values.
00121  * Add DRECT2D construction/assignment from LRECT2D.
00122  *
00123  * Revision 1.4  1999/05/12  16:50:02  mju
00124  * Add DRECT3D ctor that takes DRECT2D and z min/max values.
00125  *
00126  * Revision 1.3  1999/05/07  21:21:05  mju
00127  * Header restruct.
00128  *
00129  * Revision 1.1  1999/05/05  17:30:09  mju
00130  * Initial revision
00131  * \endif
00132 **/
00133 
00134 #ifndef  INC_MI32_RECT_H
00135 #define  INC_MI32_RECT_H
00136 
00137 //!*****************************************************************************
00138 //!      The structures defined here must not change in size as they are stored
00139 //!      in many existing data files, as well as passed to DLLs.  The members
00140 //!      must remain public and their names may not be changed for any reason.
00141 //!*****************************************************************************
00142 
00143 #ifndef  INC_MI32_STDDEFNS_H
00144 #include <mi32/stddefns.h>
00145 #endif
00146 
00147 #ifndef  INC_MI32_INIDEFNS_H
00148 #include <mi32/inidefns.h>
00149 #endif
00150 
00151 #ifdef ALLOW_NAMESPACES
00152    #include <limits>
00153    #include <cmath>
00154 #else
00155    #include <limits.h>
00156    #include <math.h>
00157    #include <float.h>
00158 #endif
00159 
00160 #ifndef  INC_MI32_POINT_H
00161 #include <mi32/point.h>
00162 #endif
00163 
00164 //-------------------------------------------------------------------------------------------------------------------
00165 
00166 //! 2D rectangle using 16-bit integer coordinates.
00167 struct WRECT2D {
00168    INT16 xinit;                     //!< Minimum X coordinate (inclusive)
00169    INT16 yinit;                     //!< Minimum Y coordinate (inclusive)
00170    INT16 xlast;                     //!< Maximum X coordinate (inclusive)
00171    INT16 ylast;                     //!< Maximum Y coordinate (inclusive)
00172 
00173    //! Make compiler validate structure size.
00174    CHECKSIZE(8);                       
00175    };
00176 
00177 //-------------------------------------------------------------------------------------------------------------------
00178 
00179 //! 2D rectangle using 32-bit integer coordinates.
00180 struct LRECT2D {
00181 
00182    INT32 xinit;                     //!< Minimum X coordinate (inclusive)
00183    INT32 yinit;                     //!< Minimum Y coordinate (inclusive)
00184    INT32 xlast;                     //!< Maximum X coordinate (inclusive)
00185    INT32 ylast;                     //!< Maximum Y coordinate (inclusive)
00186 
00187    //! Default constructor, initializes to invalid (empty) rectangle.
00188    LRECT2D (                           
00189       ): xinit(INT32_MAX), yinit(INT32_MAX), xlast(INT32_MIN), ylast(INT32_MIN) { }
00190 
00191    //! Construct rectangle of specified size.
00192    LRECT2D (                           
00193       INT32 xsize,
00194       INT32 ysize
00195       ) : xinit(0), yinit(0), xlast(xsize-1), ylast(ysize-1) { }
00196 
00197    //! Construction from X/Y ranges.
00198    LRECT2D (                           
00199       INT32 xi,
00200       INT32 yi,
00201       INT32 xl,
00202       INT32 yl
00203       ) : xinit(xi), yinit(yi), xlast(xl), ylast(yl) { }
00204 
00205    //! Check if contains specified point.
00206    bool Contains (                     
00207       INT32 x,
00208       INT32 y
00209       ) const { return (x >= xinit && x <= xlast && y >= yinit && y <= ylast); }
00210 
00211    //! Check if contains specified point.
00212    bool Contains (                     
00213       const LPOINT2D& pt
00214       ) const { return (pt.x >= xinit && pt.x <= xlast && pt.y >= yinit && pt.y <= ylast); }
00215 
00216    //! Check if contains specified rectangle.
00217    bool Contains (                     
00218       const LRECT2D& rhs
00219       ) const { return (rhs.xinit >= xinit && rhs.xlast <= xlast && rhs.yinit >= yinit && rhs.ylast <= ylast); }
00220 
00221    //! Expand the rectangle by 'value' amount.
00222    void Expand (                       
00223       const INT32 value
00224       ) { xinit -= value; yinit -= value; xlast += value; ylast += value; }
00225    
00226    //! Expand the rectangle by 'value' amount.
00227    void Expand (                       
00228       const INT32 xval,
00229       const INT32 yval
00230       ) { xinit -= xval; yinit -= yval; xlast += xval; ylast += yval; }
00231 
00232    //! Extend rectangle to encompass both rectangles.
00233    void Extend (                       
00234       const LRECT2D& rect
00235       ) {
00236       if (rect.xinit < xinit) xinit = rect.xinit;
00237       if (rect.yinit < yinit) yinit = rect.yinit;
00238       if (rect.xlast > xlast) xlast = rect.xlast;
00239       if (rect.ylast > ylast) ylast = rect.ylast;
00240       }
00241 
00242    //! Extend rectangle to include specified LPOINT2D point.
00243    void Extend (
00244       const LPOINT2D& pt
00245       ) {
00246       if (pt.x < xinit) xinit = pt.x;
00247       if (pt.x > xlast) xlast = pt.x;
00248       if (pt.y < yinit) yinit = pt.y;
00249       if (pt.y > ylast) ylast = pt.y;
00250       }
00251 
00252    //! Extend rectangle to include specified X,Y point.
00253    void Extend (
00254       const INT32 xval,
00255       const INT32 yval
00256       ) {
00257       if (xval < xinit) xinit = xval;
00258       if (yval < yinit) yinit = yval;
00259       if (xval > xlast) xlast = xval;
00260       if (yval > ylast) ylast = yval;
00261       }
00262 
00263    //! Compute area of rectangle (Could be negative if invalid rectangle).
00264    INT32 GetArea (
00265       ) const { return (GetWidth() * GetHeight()); }
00266 
00267    //! Return bottom left corner.
00268    void GetBottomLeft (                
00269       LPOINT2D& ret
00270       ) const { ret.x = xinit; ret.y = yinit; }
00271 
00272    //! Get bottom right corner.
00273    void GetBottomRight (               
00274       LPOINT2D& ret
00275       ) const { ret.x = xlast; ret.y = yinit; }
00276 
00277    //! Return center point of rectangle.
00278    DPOINT2D GetCenter (                
00279       ) const { return (DPOINT2D((xlast + xinit)/2.0, (ylast + yinit)/2.0)); }
00280 
00281    //! Get center point of rectangle.
00282    void GetCenter (                    
00283       DPOINT2D& ret
00284       ) const { ret.x = (xinit + xlast) / 2.0; ret.y = (yinit + ylast) / 2.0; }
00285 
00286    //! Get corners as array.
00287    void GetCorners (                   
00288       LPOINT2D *corners,               //!< Array of points to fill in
00289       bool ClosePoly = false,          //!< Return "closed" polygon, corners[4] = corners[0]
00290       bool OrientCCW = false           //!< Orient points in counterclockwise order for right-hand cartesian
00291       ) const;
00292 
00293    //! Compute number of non zero dimensions (0, 1, or 2).
00294    int GetDimension (                  
00295       ) const {
00296       int count(0);
00297       if (xinit < xlast) count ++;
00298       if (yinit < ylast) count ++;
00299       return (count);
00300       }
00301 
00302    //! Return height (Y size) of rectangle.
00303    UINT32 GetHeight (                  
00304       ) const { return (ylast - yinit + 1); }
00305 
00306    //! Get size of rectangle.
00307    void GetSize (                      
00308       LPOINT2D& ret
00309       ) const { ret.x = xlast - xinit; ret.y = ylast - yinit; }
00310 
00311    //! Return top left point of rectangle.
00312    void GetTopLeft (                   
00313       LPOINT2D& ret
00314       ) const { ret.x = xinit; ret.y = ylast; }
00315 
00316    //! Return top right point of rectangle.
00317    void GetTopRight (                  
00318       LPOINT2D& ret
00319       ) const { ret.x = xlast; ret.y = ylast; }
00320 
00321    //! Return width (X size) of rectangle.
00322    UINT32 GetWidth (                   
00323       ) const { return (xlast - xinit + 1); }
00324 
00325    //! Read rectangle from INI file.
00326    bool IniRead (
00327       INIHANDLE IniHandle,
00328       const char *IniGroup,
00329       const char *IniName
00330       ) { return (_iniRead(IniHandle,IniGroup,IniName,INITYPE_INT32,this,4) == 4); }
00331 
00332    //! Read rectangle from INI file.
00333    void IniWrite (
00334       INIHANDLE IniHandle,
00335       const char *IniGroup,
00336       const char *IniName
00337       ) const { _iniWrite(IniHandle,IniGroup,IniName,INITYPE_INT32,this,4); }
00338 
00339    //! Intersect two DRECT2D's, may result in an invalid rectangle.
00340    void Intersect (                    
00341       const LRECT2D& rect
00342       ) {
00343       if (rect.IsValid()) {
00344          if (rect.xinit > xinit) xinit = rect.xinit;
00345          if (rect.yinit > yinit) yinit = rect.yinit;
00346          if (rect.xlast < xlast) xlast = rect.xlast;
00347          if (rect.ylast < ylast) ylast = rect.ylast;
00348          }
00349       else {
00350          *this = rect;
00351          }
00352       return;
00353       }
00354 
00355    //! Check if rectangle is valid.
00356    bool IsValid (                      
00357       ) const { return (xinit <= xlast && yinit <= ylast); }
00358 
00359    //! Limit point (LPOINT2D) to extents specified by rectangle.
00360    void Limit (
00361       LPOINT2D& point
00362       ) const {
00363       if (point.x < xinit) point.x = xinit; else if (point.x > xlast) point.x = xlast;
00364       if (point.y < yinit) point.y = yinit; else if (point.y > ylast) point.y = ylast;
00365       }
00366 
00367    //! Limit point (DPOINT2D) to extents specified by rectangle.
00368    void Limit (
00369       DPOINT2D& point
00370       ) const {
00371       if (point.x < xinit) point.x = xinit; else if (point.x > xlast) point.x = xlast;
00372       if (point.y < yinit) point.y = yinit; else if (point.y > ylast) point.y = ylast;
00373       }
00374 
00375    //! Check if rectangle overlaps.
00376    bool Overlaps (                     
00377       const LRECT2D& rhs
00378       ) const {
00379       return (!(rhs.xlast < xinit || rhs.xinit > xlast || rhs.ylast < yinit || rhs.yinit > ylast));
00380       }
00381    
00382    //! Set given (x1,y1), (x2,y2)
00383    void Set (
00384       INT32 x1,
00385       INT32 y1,
00386       INT32 x2,
00387       INT32 y2
00388       ) { xinit = x1; yinit = y1; xlast = x2; ylast = y2; }
00389 
00390    //! Sets the initial values to the maximum possible and the final values to the minimum possible, thus making the rectangle "invalid".
00391    //! Setting a rectangle to invalid means that no point will be in it.  It also makes it easy 
00392    //! to compute the min/max of a bunch of points.  You just iterate through all the points 
00393    //! and Extend() the rectangle.  Normally, you'd have to handle the first point specially.
00394    void SetInvalid (
00395       ) { xinit = yinit = INT32_MAX; xlast = ylast = INT32_MIN; }
00396 
00397    //! Perform byte-order swapping.
00398    void SwapBytes (
00399       ) { ::SwapBytes(xinit); ::SwapBytes(xlast); ::SwapBytes(yinit); ::SwapBytes(ylast); }
00400 
00401    //! Make compiler validate structure size.
00402    CHECKSIZE(16);                      
00403    };
00404 
00405 inline bool operator== (
00406    const LRECT2D& lhs,
00407    const LRECT2D& rhs
00408    ) {
00409    return (lhs.xinit == rhs.xinit && lhs.xlast == rhs.xlast && lhs.yinit == rhs.yinit && lhs.ylast == rhs.ylast);
00410    }
00411 
00412 inline bool operator!= (
00413    const LRECT2D& lhs,
00414    const LRECT2D& rhs
00415    ) {
00416    return (!operator==(lhs,rhs));
00417    }
00418 
00419 
00420 //-------------------------------------------------------------------------------------------------------------------
00421 
00422 //! 2D rectangle using 'double' precision coordinates.
00423 struct DRECT2D {
00424    
00425    double xinit;                    //!< Minimum X coordinate (inclusive)
00426    double yinit;                    //!< Minimum Y coordinate (inclusive)
00427    double xlast;                    //!< Maximum X coordinate (inclusive)
00428    double ylast;                    //!< Maximum Y coordinate (inclusive)
00429 
00430    //! Default constructor, initialize to "invalid" area.
00431    DRECT2D (                           
00432       ) : xinit(DBL_MAX), yinit(DBL_MAX), xlast(-DBL_MAX), ylast(-DBL_MAX) {
00433       }
00434 
00435    //! Construct from FPOINT2D (or FPOINT3D).
00436    DRECT2D (                           
00437       const FPOINT2D& pt
00438       ) : xinit(pt.x), yinit(pt.y), xlast(pt.x), ylast(pt.y) { }
00439 
00440    //! Construct from DPOINT2D (or DPOINT3D).
00441    DRECT2D (                           
00442       const DPOINT2D& pt
00443       ) : xinit(pt.x), yinit(pt.y), xlast(pt.x), ylast(pt.y) { }
00444 
00445    DRECT2D (
00446       double xi,
00447       double yi,
00448       double xl,
00449       double yl
00450       ) : xinit(xi), yinit(yi), xlast(xl), ylast(yl) { }
00451 
00452    //! Implicit conversion from LRECT2D.
00453    DRECT2D (                           
00454       const LRECT2D& rect
00455       ) : xinit(rect.xinit), yinit(rect.yinit), xlast(rect.xlast), ylast(rect.ylast) { }
00456 
00457    //! Assignment from DPOINT2D
00458    DRECT2D& operator= (                
00459       const DPOINT2D& pt
00460       ) { xinit = xlast = pt.x; yinit = ylast = pt.y; return (*this); }
00461 
00462    //! Assignment from LRECT2D.
00463    DRECT2D& operator= (                
00464       const LRECT2D& rhs
00465       ) { xinit = rhs.xinit; yinit = rhs.yinit; xlast = rhs.xlast; ylast = rhs.ylast; return (*this); }
00466 
00467    //! Clip this rectangle to specified rectangle.
00468    void ClipTo (                       
00469       const DRECT2D& rect
00470       ) {
00471       if (xinit < rect.xinit) xinit = rect.xinit;
00472       if (yinit < rect.yinit) yinit = rect.yinit;
00473       if (xlast > rect.xlast) xlast = rect.xlast;
00474       if (ylast > rect.ylast) ylast = rect.ylast;
00475       return;
00476       }
00477 
00478    //! Given the center point of the DRECT2D and the 'TestPt' which is outside the box,
00479    //! compute the point on the edge of the box which falls between the center point and
00480    //! the 'TestPt'.
00481    //! @return 'true' if the point is found, false if the 'TestPt' is inside the box or the box is invalid
00482    bool ComputeEdgePoint (
00483       const DPOINT2D& OutsidePt,       //!< Point outside of 'this' 
00484       DPOINT2D& EdgePt                 //!< Point on the rectangle edge RETURNED if 'true' returned, center of the box if 'false' is returned
00485       ) const;
00486 
00487    //! Check if contains specified point.
00488    bool Contains (                     
00489       double x,
00490       double y
00491       ) const { return (x >= xinit && x <= xlast && y >= yinit && y <= ylast); }
00492 
00493    //! Check if contains specified point.
00494    bool Contains (                     
00495       const DPOINT2D& pt
00496       ) const { return (pt.x >= xinit && pt.x <= xlast && pt.y >= yinit && pt.y <= ylast); }
00497 
00498    //! Check if contains specified point.
00499    bool Contains (                     
00500       const DRECT2D& rhs
00501       ) const { return (rhs.xinit >= xinit && rhs.xlast <= xlast && rhs.yinit >= yinit && rhs.ylast <= ylast); }
00502 
00503    //! Expand the rectangle by 'value' amount.
00504    void Expand (                       
00505       const double value
00506       ) { xinit -= value; yinit -= value; xlast += value; ylast += value; }
00507 
00508    //! Expand the rectangle by 'value' amount.
00509    void Expand (                       
00510       const double xval,
00511       const double yval
00512       ) { xinit -= xval; yinit -= yval; xlast += xval; ylast += yval; }
00513 
00514    //! Extend rectangle to include specified X,Y point.
00515    void Extend (                       
00516       const double xval,
00517       const double yval
00518       ) {
00519       if (xval < xinit) xinit = xval;
00520       if (yval < yinit) yinit = yval;
00521       if (xval > xlast) xlast = xval;
00522       if (yval > ylast) ylast = yval;
00523       return;
00524       }
00525 
00526    //! Extend rectangle to encompass both rectangles.
00527    void Extend (                       
00528       const DRECT2D& rect
00529       ) {
00530       if (rect.xinit < xinit) xinit = rect.xinit;
00531       if (rect.yinit < yinit) yinit = rect.yinit;
00532       if (rect.xlast > xlast) xlast = rect.xlast;
00533       if (rect.ylast > ylast) ylast = rect.ylast;
00534       return;
00535       }
00536 
00537    //! Extend rectangle to include specified DPOINT2D point.
00538    void Extend (                       
00539       const DPOINT2D& pt
00540       ) {
00541       if (pt.x < xinit) xinit = pt.x;
00542       if (pt.x > xlast) xlast = pt.x;
00543       if (pt.y < yinit) yinit = pt.y;
00544       if (pt.y > ylast) ylast = pt.y;
00545       return;
00546       }
00547 
00548    //! Compute area of rectangle.
00549    double GetArea (                    
00550       ) const { return ((xlast - xinit) * (ylast - yinit)); }
00551 
00552    //! Return bottom left point of rectangle.
00553    void GetBottomLeft (                
00554       DPOINT2D& ret
00555       ) const { ret.x = xinit; ret.y = yinit; }
00556 
00557    //! Return bottom right point of rectangle.
00558    void GetBottomRight (               
00559       DPOINT2D& ret
00560       ) const { ret.x = xlast; ret.y = yinit; }
00561 
00562    //! Return center point of rectangle.
00563    DPOINT2D GetCenter (                
00564       ) const { return (DPOINT2D((xlast + xinit)/2.0, (ylast + yinit)/2.0)); }
00565 
00566    //! Return center point of rectangle.
00567    void GetCenter (                    
00568       DPOINT2D& ret
00569       ) const { ret.x = (xinit + xlast) / 2.0; ret.y = (yinit + ylast) / 2.0; }
00570 
00571    //! Get corners as array.
00572    void GetCorners (                   
00573       DPOINT2D *corners,               //!< Array of points to fill in
00574       bool ClosePoly = false,          //!< Return "closed" polygon, corners[4] = corners[0]
00575       bool OrientCCW = false           //!< Orient points in counterclockwise order for right-hand cartesian
00576       ) const;
00577 
00578    //! Get corners as array.
00579    void GetCorners (                   
00580       DPOINT3D *corners,               //!< Array of points to fill in
00581       bool ClosePoly = false,          //!< Return "closed" polygon, corners[4] = corners[0]
00582       bool OrientCCW = false           //!< Orient points in counterclockwise order for right-hand cartesian
00583       ) const;
00584 
00585    //! Compute number of non zero dimensions (0, 1, or 2).
00586    int GetDimension (                  
00587       ) const {
00588       int count(0);
00589       if (xinit < xlast) count ++;
00590       if (yinit < ylast) count ++;
00591       return (count);
00592       }
00593 
00594    //! Compute the distance between two disjoint rectangles
00595    //! @return Distance between two disjoint rectangles, 0.0 if they overlap.
00596    double GetDistance (
00597       const DRECT2D& rect
00598       ) const;
00599 
00600    //! Return height of rectangle.
00601    double GetHeight (                  
00602       ) const { return (ylast - yinit); }
00603 
00604    //! Compute the maximum distance between two rectangles
00605    //! Uses Extend() and then computes the diagonal distance
00606    //! @return Max distance between two rectangles
00607    double GetMaxDistance (
00608       const DRECT2D& rect
00609       ) const;
00610 
00611    //! Compute the maximum distance between two rectangles
00612    //! Uses Extend() and then computes the diagonal distance
00613    //! @return Max distance between two rectangles
00614    double GetMaxDistanceSquared (
00615       const DRECT2D& rect
00616       ) const;
00617 
00618    //! Get the rectangle as an LRECT2D (with rounding)
00619    void GetRect (
00620       LRECT2D& rect
00621       ) const {
00622       rect.xinit = static_cast<INT32>(ROUND(xinit));
00623       rect.yinit = static_cast<INT32>(ROUND(yinit));
00624       rect.xlast = static_cast<INT32>(ROUND(xlast));
00625       rect.ylast = static_cast<INT32>(ROUND(ylast));
00626       return;
00627       }
00628 
00629    //! Get size of rectangle.
00630    void GetSize (                      
00631       DPOINT2D& ret
00632       ) const { ret.x = xlast - xinit; ret.y = ylast - yinit; }
00633 
00634    //! Return top left point of rectangle.
00635    void GetTopLeft (                   
00636       DPOINT2D& ret
00637       ) const { ret.x = xinit; ret.y = ylast; }
00638 
00639    //! Return top right point of rectangle.
00640    void GetTopRight (                  
00641       DPOINT2D& ret
00642       ) const { ret.x = xlast; ret.y = ylast; }
00643 
00644    //! Return width of rectangle.
00645    double GetWidth (                   
00646       ) const { return (xlast - xinit); }
00647 
00648    //! Read rectangle from INI file.
00649    bool IniRead (
00650       INIHANDLE IniHandle,
00651       const char *IniGroup,
00652       const char *IniName
00653       ) { return (_iniRead(IniHandle,IniGroup,IniName,INITYPE_DRECT2D,this,1) == 1); }
00654 
00655    //! Read rectangle from INI file with default.
00656    bool IniRead (
00657       INIHANDLE IniHandle,
00658       const char *IniGroup,
00659       const char *IniName,
00660       const DRECT2D& dft
00661       ) { if (IniRead(IniHandle,IniGroup,IniName)) return (true); else { *this = dft; return (false); } }
00662 
00663    //! Read rectangle from INI file.
00664    void IniWrite (
00665       INIHANDLE IniHandle,
00666       const char *IniGroup,
00667       const char *IniName
00668       ) const { _iniWrite(IniHandle,IniGroup,IniName,INITYPE_DRECT2D,this,1); }
00669 
00670    //! Intersect two DRECT2D's, may result in an invalid rectangle.
00671    void Intersect (                    
00672       const DRECT2D& rect
00673       ) {
00674       if (rect.IsValid()) {
00675          if (rect.xinit > xinit) xinit = rect.xinit;
00676          if (rect.yinit > yinit) yinit = rect.yinit;
00677          if (rect.xlast < xlast) xlast = rect.xlast;
00678          if (rect.ylast < ylast) ylast = rect.ylast;
00679          }
00680       else {
00681          *this = rect;
00682          }
00683       return;
00684       }
00685       
00686    //! Determine if the two rectangles are equivalent 
00687    //! This method uses "Fuzzy" edge comparisons
00688    //! Specify a different threshold to allow greater distances
00689    //! @return 'True' if they are, 'False' if not
00690    bool IsEquivalentTo (
00691       const DRECT2D& rhs,
00692       double threshold = 0.0        //!< Default threshold is max absolute value of rectangle coordinate * 1.0E-13
00693       ) const;
00694 
00695    //! Check if rectangle is valid.
00696    bool IsValid (                      
00697       ) const { return (xinit <= xlast && yinit <= ylast); }
00698 
00699    //! Limit point to extents specified by rectangle.
00700    void Limit (
00701       DPOINT2D& point
00702       ) const {
00703       if (point.x < xinit) point.x = xinit; else if (point.x > xlast) point.x = xlast;
00704       if (point.y < yinit) point.y = yinit; else if (point.y > ylast) point.y = ylast;
00705       return;
00706       }
00707 
00708    //! Check if rectangle overlaps.
00709    bool Overlaps (                     
00710       const DRECT2D& rhs
00711       ) const { return (!(rhs.xlast < xinit || rhs.xinit > xlast || rhs.ylast < yinit || rhs.yinit > ylast)); }
00712 
00713    //! Set given (x1,y1), (x2,y2)
00714    void Set (
00715       double x1,
00716       double y1,
00717       double x2,
00718       double y2
00719       ) { xinit = x1; yinit = y1; xlast = x2; ylast = y2; }
00720 
00721    //! Sets the initial values to the maximum possible and the final values to the minimum possible, thus making the rectangle "invalid".
00722    //! Setting a rectangle to invalid means that no point will be in it.  It also makes it easy 
00723    //! to compute the min/max of a bunch of points.  You just iterate through all the points 
00724    //! and Extend() the rectangle.  Normally, you'd have to handle the first point specially.
00725    void SetInvalid (
00726       ) { xinit = yinit = DBL_MAX; xlast = ylast = -DBL_MAX; }
00727 
00728    //! Perform byte-order swapping.
00729    void SwapBytes (
00730       ) { ::SwapBytes(xinit); ::SwapBytes(xlast); ::SwapBytes(yinit); ::SwapBytes(ylast); }
00731 
00732    //! Make compiler validate structure size.
00733    CHECKSIZE(32);                      
00734    };
00735 
00736 inline bool operator== (
00737    const DRECT2D& lhs,
00738    const DRECT2D& rhs
00739    ) {
00740    return (lhs.xinit == rhs.xinit && lhs.xlast == rhs.xlast && lhs.yinit == rhs.yinit && lhs.ylast == rhs.ylast);
00741    }
00742 
00743 inline bool operator!= (
00744    const DRECT2D& lhs,
00745    const DRECT2D& rhs
00746    ) {
00747    return (!operator==(lhs,rhs));
00748    }
00749 
00750 inline void SwapBytes (
00751    DRECT2D& rect
00752    ) {
00753    rect.SwapBytes();
00754    }
00755 
00756 //! Read 'DRECT2D' value from INI file.
00757 inline int IniRead (INIHANDLE hdl, const char *group, const char *field, DRECT2D& value) { return (_iniRead(hdl,group,field,INITYPE_DRECT2D,&value,1)); }
00758 
00759 //! Read 'DRECT2D' value from INI file with default.
00760 inline int IniRead (INIHANDLE hdl, const char *group, const char *field, DRECT2D& value, const DRECT2D& dft) { value = dft; return (IniRead(hdl,group,field,value)); }
00761 
00762 //! Write 'DRECT2D' value to INI file.
00763 inline int IniWrite (INIHANDLE hdl, const char *group, const char *field, const DRECT2D& value) { return (_iniWrite(hdl,group,field,INITYPE_DRECT2D,&value,1)); }
00764 
00765 
00766 //-------------------------------------------------------------------------------------------------------------------
00767 
00768 //! 3D rectangle using 'double' precision coordinates.
00769 struct DRECT3D : public DRECT2D {
00770    
00771    double zinit;
00772    double zlast;
00773 
00774    //! Initialize to nonexistent area.
00775    DRECT3D (                           
00776       ) : DRECT2D(), zinit(DBL_MAX), zlast(-DBL_MAX) { }
00777 
00778    //! Construct from FPOINT3D.
00779    DRECT3D (                           
00780       const FPOINT3D& pt
00781       ) : DRECT2D(pt), zinit(pt.z), zlast(pt.z) { }
00782 
00783    //! Construct from DPOINT3D.
00784    DRECT3D (                           
00785       const DPOINT3D& pt
00786       ) : DRECT2D(pt), zinit(pt.z), zlast(pt.z) { }
00787 
00788    //! Construct from DRECT2D.
00789    DRECT3D (                           
00790       const DRECT2D& rect
00791       ) : DRECT2D(rect), zinit(0.0), zlast(0.0) { }
00792 
00793    //! Construct from DRECT2D and Z min/max.
00794    DRECT3D (                           
00795       const DRECT2D& rect,
00796       double zmin,
00797       double zmax
00798       ) : DRECT2D(rect), zinit(zmin), zlast(zmax) { }
00799 
00800    //! Assignment from DPOINT3D
00801    DRECT3D& operator= (                
00802       const DPOINT3D& pt
00803       ) {
00804       xinit = xlast = pt.x;
00805       yinit = ylast = pt.y;
00806       zinit = zlast = pt.z;
00807       return (*this);
00808       }
00809 
00810    //! Check if point is inside.
00811    bool Contains (                     
00812       const DPOINT3D& pt
00813       ) const { return (DRECT2D::Contains(pt) && pt.z >= zinit && pt.z <= zlast); }
00814    
00815    //! Check if rectangle is inside.
00816    bool Contains (                     
00817       const DRECT3D& rhs
00818       ) const { return (DRECT2D::Contains(rhs) && rhs.zinit >= zinit && rhs.zlast <= zlast); }
00819 
00820    //! Expand the rectangle by 'value' amount.
00821    void Expand (                       
00822       const double value
00823       ) {
00824       DRECT2D::Expand(value);
00825       zinit -= value; zlast += value;
00826       return;
00827       }
00828 
00829    //! Expand the rectangle by 'value' amount.
00830    void Expand (                       
00831       const double xval,
00832       const double yval
00833       ) { DRECT2D::Expand(xval, yval); }
00834 
00835    //! Extend rectangle to encompass both rectangles.
00836    void Extend (                       
00837       const double xval,
00838       const double yval
00839       ) { DRECT2D::Extend(xval, yval); }
00840 
00841    //! Extend rectangle to encompass both rectangles.
00842    void Extend (                       
00843       const double xval,
00844       const double yval,
00845       const double zval
00846       ) {
00847       DRECT2D::Extend(xval, yval);
00848       if (zval < zinit) zinit = zval;
00849       if (zval > zlast) zlast = zval;
00850       return;
00851       }
00852 
00853    //! Union rectangles together, resulting rect is extents of both
00854    void Extend (                       
00855       const DRECT3D& rect
00856       ) {
00857       DRECT2D::Extend(rect);
00858       if (rect.zinit < zinit) zinit = rect.zinit;
00859       if (rect.zlast > zlast) zlast = rect.zlast;
00860       return;
00861       }
00862 
00863    //! Extend to contain specified point.
00864    void Extend (                       
00865       const DPOINT2D& pt
00866       ) { DRECT2D::Extend(pt); }
00867 
00868    //! Extend to contain specified point.
00869    void Extend (                       
00870       const DPOINT3D& pt
00871       ) {
00872       DRECT2D::Extend(pt);
00873       if (pt.z < zinit) zinit = pt.z;
00874       if (pt.z > zlast) zlast = pt.z;
00875       return;
00876       }
00877 
00878    //! Return center of the box.
00879    DPOINT3D GetCenter (
00880       ) const { return (DPOINT3D((xinit+xlast)/2.0,(yinit+ylast)/2.0,(zinit+zlast)/2.0)); }
00881 
00882    //! Return center of the box.
00883    void GetCenter (
00884       DPOINT3D& ret
00885       ) const {
00886       ret.x = (xinit + xlast) / 2.0;
00887       ret.y = (yinit + ylast) / 2.0;
00888       ret.z = (zinit + zlast) / 2.0;
00889       return;
00890       }
00891 
00892    //! Return depth of the box (z distance).
00893    double GetDepth (                   
00894       ) const { return (zlast - zinit); }
00895 
00896    //! Compute number of non zero dimensions (0, 1, 2, or 3).
00897    int GetDimension (                  
00898       ) const {
00899       int count(DRECT2D::GetDimension());
00900       if (zinit < zlast) count ++;
00901       return (count);
00902       }
00903 
00904    //! Get maximum coordinate.
00905    void GetMaximum (
00906       DPOINT3D& maximum
00907       ) const { maximum.x = xlast; maximum.y = ylast; maximum.z = zlast; }
00908 
00909    //! Get minimum coordinate.
00910    void GetMinimum (
00911       DPOINT3D& minimum
00912       ) const { minimum.x = xinit; minimum.y = yinit; minimum.z = zinit; }
00913 
00914    //! Get size of box.
00915    void GetSize (                      
00916       DPOINT3D& ret
00917       ) const {
00918       ret.x = xlast - xinit;
00919       ret.y = ylast - yinit;
00920       ret.z = zlast - zinit;
00921       return;
00922       }
00923 
00924    //! Compute volume of box.
00925    double GetVolume (                  
00926       ) const { return (DRECT2D::GetArea() * (zlast - zinit)); }
00927 
00928    //! Read rectangle from INI file.
00929    bool IniRead (
00930       INIHANDLE IniHandle,
00931       const char *IniGroup,
00932       const char *IniName
00933       ) { return (_iniRead(IniHandle,IniGroup,IniName,INITYPE_Double,this,6) == 6); }
00934 
00935    //! Read rectangle from INI file.
00936    void IniWrite (
00937       INIHANDLE IniHandle,
00938       const char *IniGroup,
00939       const char *IniName
00940       ) const { _iniWrite(IniHandle,IniGroup,IniName,INITYPE_Double,this,6); }
00941 
00942    //! Intersect two DRECT3D's, may result in an invalid rectangle.
00943    void Intersect (                    
00944       const DRECT3D& rect
00945       ) {
00946       if (rect.IsValid()) {
00947          DRECT2D::Intersect(rect);
00948          if (rect.zinit > zinit) zinit = rect.zinit;
00949          if (rect.zlast < zlast) zlast = rect.zlast;
00950          }
00951       else {
00952          *this = rect;
00953          }
00954       return;
00955       }
00956    
00957    //! Check if rectangle is valid.
00958    bool IsValid (                      
00959       ) const { return (DRECT2D::IsValid() && zinit <= zlast); }
00960 
00961    //! Check if rectangle overlaps.
00962    bool Overlaps (                     
00963       const DRECT3D& rhs
00964       ) const { return (DRECT2D::Overlaps(rhs) && !(rhs.zlast < zinit || rhs.zinit > zlast)); }
00965 
00966    //! Set given (x1,y1), (x2,y2)
00967    void Set (
00968       double x1,
00969       double y1,
00970       double x2,
00971       double y2
00972       ) { xinit = x1; yinit = y1; xlast = x2; ylast = y2; zinit = zlast = 0.0; }
00973 
00974    //! Sets the initial values to the maximum possible and the final values to the minimum possible, thus making the rectangle "invalid".
00975    //!
00976    //! Setting a rectangle to invalid means that no point will be in it.  It also makes it easy 
00977    //! to compute the min/max of a bunch of points.  You just iterate through all the points 
00978    //! and Extend() the rectangle.  Normally, you'd have to handle the first point specially.
00979    void SetInvalid (
00980       ) { DRECT2D::SetInvalid(); zinit = DBL_MAX; zlast = -DBL_MAX; }
00981 
00982    //! Perform byte-order swapping.
00983    void SwapBytes (
00984       ) { ::SwapBytes(xinit); ::SwapBytes(xlast); ::SwapBytes(yinit); ::SwapBytes(ylast); ::SwapBytes(zinit); ::SwapBytes(zlast); }
00985 
00986    //! Make compiler validate structure size.
00987    CHECKSIZE(48);                      
00988    };
00989 
00990 inline bool operator== (
00991    const DRECT3D& lhs,
00992    const DRECT3D& rhs
00993    ) {
00994    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);
00995    }
00996 
00997 inline bool operator!= (
00998    const DRECT3D& lhs,
00999    const DRECT3D& rhs
01000    ) {
01001    return (!operator==(lhs,rhs));
01002    }
01003 
01004 inline void SwapBytes (
01005    DRECT3D& rect
01006    ) {
01007    rect.SwapBytes();
01008    }
01009 
01010 
01011 //-------------------------------------------------------------------------------------------------------------------
01012 
01013 #endif   //!< INC_MI32_RECT_H

Generated on Thu Aug 12 06:19:03 2004 for TNTsdk by doxygen 1.3.4-20031026