/****************************************************************************
 *   gsegment_adt.h : 
 *   		header file for line segment ADT.
 *
 *   Change Log :
 *		  Dec-24-1996 Initial version,  Liujian Qian
 *
 *   $Id: gadt_segment.h,v 1.5 1999/02/16 22:14:36 qian Exp $
 ***************************************************************************/

#ifndef _GSEG_H_
#define _GSEG_H_

#include "gadt.h"


/**
 *
 *     The ADT of Segments. 
 *
 *     A Segment is a straight line with two ends and 
 *     no direction. 
 */
class GSegment : public GSpatial
{
    Coord   x1, y1,  //first end
	    x2, y2;  //second end: order is not important
public:

    // GROUP: ctors/dtor
    /**
      */
    GSegment () {init();}
    /**
      */
    GSegment (const GSegment& a);
    /**
      */
    GSegment (const GPoint& p1, const GPoint& p2);
    /**
     */
    GSegment (int x1, int y1, int x2, int y2);
     
    /**
      */
    virtual ~GSegment () {}
    
    virtual GType 	 type() const { return _Segment; }

    virtual uint32  	 getPSize() const;
    virtual Result	 init	   (void) {x1=y1=x2=y2=InvalidCoord; 
                                           return GOk;}
    virtual Result 	 input     (const char* in);
    virtual Result 	 output    (char*& out);
    virtual Result	 pack	   (DataPipe& p);
    virtual Result 	 unpack    (DataPipe& p);

    virtual Result       scale      (double xf, double yf, double zf=1);
    virtual Result       translate  (double xf, double yf, double zf=1);
    virtual Result	 rotate	    (double d, bool clock_wise) ;
    virtual Result	 transform  (const GMatrix& m) ;

    virtual Result       mbr(GRect& box) const ;
    virtual int		 cmp(const GADT& a) const;
    virtual GADT*        clone() const {return  new GSegment; }

    /**
     * set the two ends of the segment
     */
    void    set(Coord _x1, Coord _y1, Coord _x2, Coord _y2);
    /**
      */
    void    set(const GPoint&	pt1, const GPoint& pt2);

    /**
     * retrieve the coordinates of the two ends.
     */
    inline Coord   getX1() const {return x1;} ///
    inline Coord   getY1() const {return y1;} ///
    inline Coord   getX2() const {return x2;} ///
    inline Coord   getY2() const {return y2;} ///

    /**
     * calculate the vertical distance from the point to the segment.
     * uses the more advanced distance calculating method below.     
     */
    double  distance (const GPoint& pnt) const;

    /**
     * calculate the vertical distance from the point to the segment.   
     * also indicates whether the point' projection falls on the segments.
     * 
     * Returns the vertical distance.                                   
     * the 'flag' indicates whether the point's perpendicular projection
     * is on the segment (1) or not (0).                                
     */
    double  distance (const GPoint& pnt, int& flag) const;
    /**
     * generates a rectangular bufferzone along this segement. Two opposite
     * sides of the rectangle are in right angle with the segment, while
     * the other two are parallel along the segment. In other words, this 
     * segement is the central line that splits the rectangle into two equal
     * parts. The size of of cushion along each side of the segment is given by
     * the first parameter. The four coordinates are stored into xcoords and
     * ycoords. The first corner is repeated at the end (to make the zone 
     * closed), so you need to provide space for at least five doubles in
     * each array. 
     */
    Result   bufferzone(double size, Coord* xcoords, Coord* ycoords) const;
    /**
     * get the length of the segment
     */
    double  length () const;

    /**
     * this function is not defined.
     */
    virtual int covers (const GSpatial&) const {return 0;}
    /**
     * intesecting a segment with other ADTs.
     */
    virtual int	intersects (const GSpatial& a) const;
    
    /**
     * check if this segment is inside a rectangle.
     * simply use the bounding rectangle and call
     * covers() method of incoming rectangle.     
     */
    int    isInside     (const GRect& other) const;
    
    /**
     * check if the segment is inside a circle.
     */
    int    isInside     (const GCircle& other) const;

private:

    int    _intersects (const GSegment& seg, GPoint* secp = 0) const;
    int    _intersects (const GRect&  r) const;
    int    _intersects (const GCircle& c) const;
    int    _intersects (const GArc& pln) const;
    int    _intersects (const GPolygon& pgn) const;    

    friend ostream& operator << (ostream& s, const GSegment& g);
};


static class _GISegment
{
    static int cnt;
public:
    _GISegment() 
    {
	if(cnt++ ==0 ) 
	    GADTManager::registerADT(new GADTDef( _Segment, "Segment", 
						  1, 1, new GSegment) );
    }
    ~_GISegment() 
    {
	if(--cnt==0)
	    GADTManager::removeADT(_Segment);
    }
} gi_segment;


#endif

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