/****************************************************************************
* gadt_polygon.h : header file for polygon ADT.
*
* Change Log :
* 06-12-1996 Initial version, Liujian Qian
*
* $Id: gadt_polygon.h,v 1.12 1998/12/10 00:11:29 qian Exp $
***************************************************************************/
#ifndef _GPOLYGON_H_
#define _GPOLYGON_H_
#include "gadt.h"
#include "gops.h"
/**
* The 2D polygon (with holes) ADT.
*
* A polygon is a bounded area defined by one or
* more rings. If there are more than one rings, then there is one
* outer boundary ring and the rest are interier rings (holes). The
* internal data layout is very similar to that of an ArcView shapefile
* Polygon record (without all the record headers etc).
*
* The first ring is the outer boundary of the polygon by default.
*/
class GPolygon : public GSpatial
{
GOps ops;
friend class GRect;
friend class GCircle;
public:
/**
*/
GPolygon ();
/**
*/
GPolygon (const GPolygon& a);
/**
*/
GPolygon& operator= (const GPolygon& other);
/**
*/
virtual ~GPolygon ();
virtual GType type() const { return _Polygon; }
virtual uint32 getPSize() const;
virtual Result init(void);
/**
* User format: "n_rings, #_points_1, #_points_2, ... #_points_N,
* x1 y1 x2 y2 ... xm ym"
*/
virtual Result input (const char* in);
/**
* generates a string with same format in input
*/
virtual Result output (char*& out);
virtual Result pack (DataPipe& p);
virtual Result unpack (DataPipe& p);
/**
* @short return the mbr of the out boundary ring.
* @param box will be filled with the minimum bounding rectangle.
* if returns GFail, then box is not set.
*/
virtual Result mbr(GRect& box) const;
virtual GADT* clone() const {return new GPolygon; }
/**
* compares the area with the polygon 'a's area.
* Returns -1 if 'a' has larger area; or zero if they equal; otherwise 1
*/
virtual int cmp (const GADT&) const {return UNDEFINED;}
/**
* 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);
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&);
/**
*/
int numVertices(void) const { return ops.n_points; }
/**
* return number of rings
*/
int numRings (void) const { return ops.n_parts; }
/**
* return 1 if the polygon has holes
*/
bool hasHole (void) const { return ops.n_parts>1; };
/**
* add a ring to the owning polygon
* @param n_vertices number of vertices in the new ring
* @param coords the coordinates of the new ring
*/
Result addRing(int n_vertices, Coord* coords);
/**
* return the information about a particular ring
* @param nth which ring to get
* @param coords where the coordinates of the ring begin
* @return the number of vertices in this ring.
*/
int getRing(int nth, Coord*& coords);
/**
* set the MBR
*/
void setMbr(const GRect& b) {ops.setMbr(b);}
/**
* recalculate the MBR for this polygon
* @param r is the newly calculated MBR
*/
Result genMbr(GRect& r);
//Result addPoint(Coord x, Coord y, bool do_mbr=1);
//Result addPoint(const GPoint& pnt);
/**
*/
int bearing (const GADT& other) const;
/**
* return distance between this polygon and another object.
*
* if the argument is another polygon, we calculte the distance
* between the centroids of the two polygons' outer boundary ring
* only... this may not really what we want since we don't take
* into account any of the holes of either polygon.
*
* @Return the distance.
*/
double distance (const GADT& other) const;
/**
* return the area (not including any holes)
*/
double area () const;
/**
* calculate the signed area of a ring (simple polygon without holes).
* @param n_points number of vertices in the ring
* @param coord coordinates of the vertices.
* Can be used to determine the ordering of vertices.
*/
double sarea (int n_points, Coord* coord) const;
/**
* calculate the signed area of a polygon (assuming a simple one).
* the area of holes are subtracted from that of the outer boundary
* ring.
*/
double sarea () const;
/**
* return the perimeter (including those of the holes)
*/
double perimeter () const;
/**
* calculate the perimeter of a particular ring
* @param nth specifies the ring
*/
double perimeter(int nth) const;
/**
* Determine the class of the polygon according to its convexity.
* It calls some inlines that are useful routines in
* their own right.
*
* Originally by Peter Schorn & Frederick Fisher, In "Graphics
* Gems IV", Academic Press 1994.
*
* @return the class of the polygon; for meaning of return values
* see geomacro.h, they are GCONVEX_CW, GCONVEX_CCW, GNOT_CONVEX,
* GNOT_CONVEX_DEGENERATE, GCONEXT_DEGENERATE.
*/
int classify (int, Coord*) ;
/**
* handy version of the classify method.
*/
int classify ();
/**
*/
static int
whichSide(GPoint& p, GPoint& q, GPoint& r);
/**
*/
int isConvex ();
/**
* return the centroid (of the outer boundary ring!)
*/
double centroid (GPoint& ctr) const;
/**
* calculate the centrod of a ring (simple polygon w/o holes).
*/
double centroid (int, Coord*, GPoint&) const;
/**
* ADT-in-Polygon checking. It is a driver that calls
* sub-routines according to the given type. for now it's only
* accepting point ADT.
*/
virtual int covers (const GSpatial& ) const;
/**
* check if this polygon intersects with other adt objects.
* calls subroutines accordingly with given type of adt.
*/
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 polygon intersects a set of
* ordered point series.
*/
virtual int intersects(const GOps& ops) const;
/**
* check if this polygon is inside the given rectangle.
* @return 1 if true, otherwise 0.
*/
int isInside (const GRect& other) const;
/**
* check if this polygon is inside the given circle.
* @return 1 if true, otherwise 0.
*/
int isInside (const GCircle& other) const;
private:
int _covers (const GPoint& p) const;
int _covers (const GSegment& s) const;
int _covers (const GArc& s) const;
int _covers (const GPolygon& a) const;
int pCompare(GPoint& p, GPoint& q) const;
int getPoint(int total, int& cur, Coord* coo, GPoint& p) const;
int getDifferentPoint(int total, int& cur, Coord* coo,
GPoint& previous, GPoint& next) const;
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;
// does triangulation
int _triangulate(GTrig*& result){result=0; return 0;};
friend ostream& operator << (ostream& s, const GPolygon& p);
};
static class _GIPolygon
{
static int cnt;
public:
_GIPolygon()
{
if(cnt++ ==0 )
GADTManager::registerADT(new GADTDef( _Polygon, "Polygon",
0, 1, new GPolygon) );
}
~_GIPolygon()
{
if(--cnt==0)
GADTManager::removeADT(_Polygon);
}
} gi_polygon;
//
// CheckTriple tests three consecutive points for change of direction
// and for orientation.
//
#define CheckTriple \
if ( (this_dir = pCompare(second, third)) == -cur_dir ) \
++dir_changes; \
cur_dir = this_dir; \
if ( (this_sign = whichSide(first, second, third)) ) { \
if ( angle_sign == -this_sign ) \
return GNOT_CONVEX; \
angle_sign = this_sign; \
} \
first = second; second = third;
#endif
Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999