/****************************************************************************
 *   rect_adt.h : 
 *   		header file for rectanle ADT.
 *
 *   Change Log :
 *		 DEC-22-1996 Initial version,  Liujian Qian
 *
 *   $Id: gadt_rect.h,v 1.8 1999/02/03 06:44:59 qian Exp $
 ***************************************************************************/
#ifndef _GRECT_H_
#define _GRECT_H_

#include "gadt.h"
#include <math.h>

/**
 *     a rectangle ADT class.
 *
 *    Setup the lower corner (the corner with lower 
 *    coordinates) and the upper corner. Then you can check whether
 *    it  covers or intersects other types of spatial objects, among
 *    other functionalities.
 */
class GRect : public GSpatial
{
public:
    /**
     * the two corners' coordinates
     */
    Coord xlow, ylow, xhi, yhi;
    
public:

    /**
      */
    GRect() ;
    
    /**
      */
    GRect(Coord xLow, Coord yLow, Coord xUp, Coord yUp);

    /**
      */
    GRect(const GRect& other);

    /**
      */
    GRect& operator= (const GRect& other);

    /**
      */
    virtual ~GRect() { };
    
  
    virtual GType 	 type	   (void) const { return _Rect; }

    virtual uint32  	 getPSize() const;

    virtual Result 	 input     (const char* in);
    virtual Result 	 output    (char*& out);
    virtual Result	 pack	   (DataPipe& p);
    virtual Result 	 unpack    (DataPipe& p);
    
    virtual Result 	 mbr	   (GRect& b) const { b = *this; return GOk; }
    virtual int		 cmp	   (const GADT& other) const;
    virtual Result  	 init	   (void) { xlow=ylow=xhi=yhi=InvalidCoord;
                                            return GOk;}
    virtual GADT* 	 clone	   () const {return new GRect;}

    virtual Result      scale      (double xf, double yf, double zf=1);
    virtual Result      translate  (double xf, double yf, double zf=1);
    virtual Result	rotate	   (double, bool);
    virtual Result	transform  (const GMatrix&);
    
    /**
     * return the smaller X  coordinate 
     */
    inline Coord  getXL() const { return xlow; }
    /**
     * return the smaller Y coordinate
     */
    inline Coord  getYL() const { return ylow; }
    /**
     * return the higher X coordinate
     */
    inline Coord  getXH() const { return xhi;  }
    /**      
     * return the hither Y coordinate
     */
    inline Coord  getYH() const { return yhi;  }
    /**
     * set the value of lower X coordinate
     */
    inline void   setXL(Coord x) {  xlow = x; }
    /**
     * set the value of lower Y coordinate
     */
    inline void   setYL(Coord y) {  ylow = y; }
    /**
     * set the value of higher X coordinate
     */
    inline void   setXH(Coord x) {  xhi = x;  }
    /**
     * set the value of higher Y coordinate
     */
    inline void   setYH(Coord y) {  yhi = y;  }
    /**
     * set the coordinates for the two corners.
     * xLow/yLow is the lower corner; xHi/yHi the higher corner.
     */
    inline void   set(Coord xLow, Coord yLow, Coord xHi, Coord yHi);
      
    /**
      */
    inline Coord  getWidth(void)  const    {return GABS(xhi - xlow) ;}
    /**
      */
    inline Coord  getHeight(void) const    {return GABS(yhi - ylow) ;}
    /**
      */
    inline double area() const { return (getWidth() * getHeight()); }
    /**
     * return the distance between the centroids of the two rectangles.
     */
    double distance (const GRect& other) const;
    /**
     */
    inline double perimeter() const {return (2*getWidth() + 2*getHeight()); }
    /**
     * check if the rectangle contains valid coordinates.
     * a rectangle is invalid if A: any of the coordinates are of 
     * InvalidCoord value, or B: the lower coordinate values are 
     * greater than the higher coordinates.
     */
    inline bool   isValid() const ;
    /**
     * check whehter two rectangles are the same
     */
    bool   	  equals (const GRect& other) const;
    /**
     * if the "other" rectangle covers or intersects with this one, 
     * then enlarge this rectangle to just contain the other one;
     * otherwise (the other rect is inside this one) do nothing.
     */
    void	  enlarge (const GRect& other);
    /**
     * get the centroid of the rectangle
     */
    void   	  centroid(Coord& x, Coord& y);

    /**
     * check if the rectangle covers another geometry  object;
     * possible types of objects are: Rect, Point, Segment, Polyline, Ring, Polygon.
     */
    virtual int  covers    (const GSpatial& a) const;

    /**
     * check if the rectangle intersects another object
     * possible types of objects are: Rect, Circle, Polyline, Ring, Segment, Polygon
     */
    virtual int  intersects(const GSpatial& a) const;

private:    
    int   _covers(const GRect& a) const;
    int   _covers(const GPoint& p) const;
    int   _covers(const GSegment& seg) const;
    int   _covers(const GArc& pln) const;
    int   _covers(const GPolygon& pgn) const;
    
    int   _intersects(const GRect& a) const;
    int   _intersects(const GCircle& a) const;
    int   _intersects(const GArc& ln) const;
    int	 _intersects(const GSegment& seg) const;
    int   _intersects(const GPolygon& pgn) const;

    friend ostream&  operator<<(ostream& s, const GRect& r);
    
};  //class GRect

static class _GIRect
{
    static int cnt;
public:
    _GIRect() 
    {
	if(cnt++ ==0 ) 
	    GADTManager::registerADT(new GADTDef( _Rect, "Rect", 1, 1, new GRect) );
    }
    ~_GIRect() 
    {
	if(--cnt==0)
	    GADTManager::removeADT(_Rect);
    }
} gi_rect;


inline void 
GRect::set(Coord xLow, Coord yLow, Coord xUp, Coord yUp)
{
    if(xLow<=xUp && yLow<=yUp) {
	xlow = xLow, ylow=yLow, xhi = xUp, yhi = yUp;
    } else {
	msgWarn("rect's lower/upper boundary not properly given");
	xlow = GMIN(xLow, xUp), ylow=GMIN(yLow,yUp);
	xhi  = GMAX(xLow, xUp), yhi =GMAX(yLow,yUp);
    }
}; 

#endif





Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999