/****************************************************************************
 *   gadt_arc.h : 
 *   		 header file for Arc ADT.
 *
 *   Change Log :
 *		 June 17, 1998 Initial version,  Liujian Qian
 *
 *   $Id: gadt_arc.h,v 1.8 1998/12/10 00:11:24 qian Exp $
 ***************************************************************************/
#ifndef _GARC_H_
#define _GARC_H_

#include "glist.h"
#include "gadt.h"
#include "gops.h"

/**
 *  The Arc ADT represents a linear feature with branches.
 * 
 *  An arc consists of multiple branch polylines which are 
 *  not necessarily connected to each other. Each polyline
 *  is a sereis of connected points or segments. 
 */
class GArc : public GSpatial
{
    GOps	ops;
    
    friend	class GRect;
    friend	class GCircle;

public:
    /**
     */
    GArc();
    /**
     */
    GArc(const GArc& a);
    /**
     */
    GArc& operator= (const GArc& other);
    /**
     */
    virtual ~GArc();
    
    virtual GType	type() const {return _Arc; }
    virtual uint32	getPSize() const;
    virtual Result	init(void);

    /**
     * user format: "n_polylines, num_points_1, num_points_2,...num_pooints_N,
     *		     x1 y1 x2 y2 ... xm ym"
     */
    virtual Result	input	(const char* in);
    /**
     * generates a stpolyline with same format for input
     */
    virtual Result	output  (char*& out);
    /**
     * pack the arc into a binary structure. The structure is the 
     * same as the geometry part of the Arc record in ArcView 
     * Shapefile (ie, no record header, no type info.)
     */
    virtual Result	pack    (DataPipe& p);
    /**
     * unpack a binary stream into an Arc. The binary stream should
     * have same structure as the geometry part of the Arc record in
     * an ArcView shapefile. 
     */
    virtual Result	unpack  (DataPipe& p);
    
    /**
     * return the mbr of the Arc.
     */
    virtual Result	mbr(GRect& box) const;
    virtual GADT*	clone() const {return new GArc; }
    /**
     * compares the length with the arc 'a's area.
     * Returns -1 if 'a' has larger length; zero if equal, otherwise 1.
     */
    virtual int		cmp	(const GADT&) const {return UNDEFINED; }
    
    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&);
    /**
     * this method accepts severl "parts" each of which are a series of 
     * ordered points. All existing data will be replaced by the new data.
     */
    virtual void	set(int n_parts, int n_pnts, 
			    const int* parts, const Coord* coord);
    /**
     * return total number of verticies in all polylines.
     */
    int		numVerticies(void) const {return ops.n_points; }
    /**
     * return number of branches.
     */
    int		numBranches(void) const {return ops.n_parts;}
    /**
     * return length of the arc
     */
    double	length() const;
    /**
     * return the length of the nth branch.
     */
    double	branchLength(int nth) const;
    /**
     * add a polyline (branch) to this  arc
     */
    Result  	addBranch(int, Coord*);
    /**
     * get information about a particular branch/polyline.
     * @param nth	which branch to retrieve
     * @param coords    where its coordinates are stored
     * @return the number of vertices in the branch
     */
    int	    	getBranch(int nth, Coord*& coords);
    /**
     * check if there is a loop in this Arc. Having a loop means  
     * it either has duplicate points or the some polylines intersect 
     * themselves.  
     * We need an algorithm better than O(N*N). Currently two iterators
     * are used to loop over all the possible combination of vertices.
     * currently always returns false!!!
     */
    int		hasLoop() const;
    
   /**
    * This function is not defined for Arcs.
    * it always returns 0.
    */
    virtual int covers     (const GSpatial&) const {return 0;}
    /**
     * check if this arc intersects a segment.          
     * This method calls the segment's intersects(GSegment)
     * function for each edge of the arc.               
     */
    virtual int intersects (const GSpatial&) const;
    /**
     * check if this polygon intersects with a linear series of 
     * connected coordinates.
     */
    virtual int intersects(int n_point, Coord* coo) const;
    /**
     * check if the arc intersects a set of 
     * ordered point series.
     */
    virtual int intersects(const GOps& ops) const;
    /**
     * Check if this arc completely falls within a rectangle.
     */
    int    	isInside     (const GRect& other) const;    
    /**
     * check if this polyline complete falls inside a circle.   
     * simply loop through all nodes.                          
     */
    int    	isInside     (const GCircle& other) const;
    /**
     * scan the verticies and generate an MBR
     */
    Result 	genMbr(GRect& );
    /**
     * set the MBR
     */
    void 	setMbr(const GRect& b) {ops.setMbr(b);}

private:
    Result extend();

    int    _intersects (const GSegment& seg) const; 	
    int    _intersects (const GArc& other) const;
    int    _intersects (const GPolygon& pgn)const ;
    int    _intersects (const GRect&  r) const;
    int    _intersects (const GCircle& c)const;

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

static class _GIArc
{
    static int cnt;
public:
    _GIArc() 
    {
	if(cnt++ ==0 ) 
	    GADTManager::
	    registerADT(new GADTDef( _Arc, "Arc", 0, 1, new GArc) );
    }
    ~_GIArc() 
    {
	if(--cnt==0)
	    GADTManager::removeADT(_Arc);
    }
} gi_arc;


#endif

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