/**
 * This file describes the area-enclosing geometry in 2-D graphics.
 * Classes described here are:
 * 		IGEllipse2D, IGPolygon2D, and IGArea.
 *
 *   IBM Open Class Library
 *   (C) Copyright International Business Machines Corporation,  1997
 *   Licensed Material - Program-Property of IBM - All Rights Reserved.
 *
 */

// Revision: 28 1.24.1.6 source/albert/graph2d/igarea2d.hpp, 2d, ioc.v400, 980918 

#ifndef _IGAREA2D_
#define _IGAREA2D_

#include <igrtypes.hpp>
#include <igbase2d.hpp>
#include <igline2d.hpp>  // For IGPolyline2D
#include <imatrix.hpp>
#include <imstrmbl.hpp>
#include <iprimtyp.hpp>

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

class IGLoop2D;
class IGEllipse2D;
class IGLine2D;
class IGPoint2D;
class IGPolygon2D;
class IGRect2D;
class IGrafMatrix;

#pragma pack(push,4)
#pragma enum(4)


/**
 * IGEllipse2D is a vertically or horizontally oriented ellipse defined by an axis-aligned rectangle (an IGRect2D).
 * IGEllipse2D is a vertically or horizontally oriented ellipse defined by an axis-aligned rectangle (an IGRect2D).
 * The ellipse is inscribed in the rectangle so it just touches at the midpoint of each edge of the
 * rectangle.  An IGEllipse2D is area enclosing geometry that may be filled and/or framed.
 */

class IGEllipse2D {
	public :
        IDataStream&    operator>>= (IDataStream&) const;
        IDataStream&    operator<<= (IDataStream&);
		void writeToStream( IDataStream& toWhere ) const;
		void readFromStream( IDataStream& toWhere );
    public :
        /**
		 * Creates an ellipse centered at the origin with zero radius.
		 */
        IGEllipse2D();

		/**
		 * Copy constructor.
		 */
        IGEllipse2D( const IGEllipse2D& );

		/**
		 * Creates an ellipse geometry to fit within the provided rectangle. If the rectangle is a square, the ellipse is a circle.
		 */
        IGEllipse2D( const IGRect2D& r );

		/**
		 * Creates an ellipse geometry with a uniform radius (a circle) whose center is at the specified location.
		 */
        IGEllipse2D( const IGPoint2D& center, GCoordinate radius );

		/**
		 * Creates an ellipse geometry with the specified horizontal and vertical radii, and whose center is at the specified location.
		 */
        IGEllipse2D( const IGPoint2D& center, GCoordinate Xradius, GCoordinate Yradius );

        ~IGEllipse2D();

		/**
		 * Returns the ellipse's height and width.
		 */
        IGPoint2D     size() const;

		/**
		 * Returns the center point of the ellipse.
		 */
        IGPoint2D     center() const;

		/**
		 * Tests whether the ellipse intersects the given rectangle.
		 */
        bool        intersects( const IGRect2D& rect ) const;

		/**
		 * Tests whether the ellipse contains the given point.
		 */
        bool        contains( const IGPoint2D& point ) const;

		/**
		 * Returns the bounding rectangle of the ellipse.
		 */
        IGRect2D      bounds() const;

		/**
		 * Moves the ellipse to be centered on the given point, without changing its radii.
		 */
        void        setCenter( const IGPoint2D& center );

		/**
		 * Sets the ellipse's height and width without changing its center point.
		 */
        void        setSize( const IGPoint2D& size );

		/**
		 * Sets the bounding rectangle (which generally changes the ellipse's shape and location).
		 */
        void        setBounds( const IGRect2D& bounds );

		/**
		 * Assignment operator.
		 */
        IGEllipse2D&          operator=( const IGEllipse2D& Src );

		/**
		 * Tests whether the two ellipses are equal.
		 */
        bool                operator==( const IGEllipse2D& Src ) const;

		/**
		 * Tests whether the two ellipses are not equal.
		 */
        bool                operator!=( const IGEllipse2D& Src ) const;


    private:
        IGRect2D fRectangle;
};

/**
 * An IGPolygon is a collection of points connected with straight line segments.
 * An IGPolygon is a collection of points connected with straight line segments.
 * It is automatically closed.  An IGPolygon2D is area-enclosing geometry that may be filled and/or framed.
 * Boolean flag EOFill. true means an even-odd rule is used for determining what area is filled, and false means a nonzero winding rule is used.
 *
 * Note: IRawArray does not check whether allocation is successful. Before construction,
 * one should check if there is enough memory and use a reasonable size.
 */

class IGPolygon2D : public IGPolyline2D {
	public :
        IDataStream&    operator>>= (IDataStream&) const;
        IDataStream&    operator<<= (IDataStream&);
		void writeToStream( IDataStream& toWhere ) const;
		void readFromStream( IDataStream& toWhere );
    public:
        /**
		 * Creates a polygon with number of points equal to zero.
		 */
        IGPolygon2D();

		/**
		 * Copy constructor.
		 */
        IGPolygon2D( const IGPolygon2D& );

		/**
		 * Creates a polygon with the specified IGRect2D and the specified fill rule.
		 */
        IGPolygon2D( const IGRect2D& g, bool EOFill = true );

		/**
		 * Creates a polygon with the specified number of points and the specified fill rule.
		 */
        IGPolygon2D( unsigned long numPoints, bool EOFill = true );

		/**
		 * Creates a polygon with the specified points and the specified fill rule.
		 */
        IGPolygon2D( const IGPoint2DArray& pts, bool EOFill = true );

        virtual ~IGPolygon2D();

		/**
		 * Returns a boolean specifying the filling algorithm.
		 */
        bool    	eOFill() const;

		/**
		 * Tests whether the polygon is convex.
		 */
        bool        isConvex() const;

		/**
		 * Tests whether the polygon is comprised completely of straight lines.
		 */
        bool        isRectilinear() const;

		/**
		 * Sets the flag that specifies the filling algorithm.
		 */
        void        setEOFill(bool EOFill);

		/**
		 * Tests whether the polygon intersects the given rectangle.
		 */
        bool        intersects( const IGRect2D& g) const;

		/**
		 * Tests whether the polygon contains the given rectangle.
		 */
        bool        contains( const IGPoint2D& p ) const;

		/**
		 * Assignment operator.
		 */
        IGPolygon2D&          operator=( const IGPolygon2D& Src );

		/**
		 * Tests whether the two polygons are equal.
		 */
        bool                operator==( const IGPolygon2D& Src ) const;

		/**
		 * Tests whether the two polygons are not equal.
		 */
        bool                operator!=( const IGPolygon2D& Src ) const;

    private:
        bool fEOFill;

};


class IGrafExtractor;
class ICAGNode;
class IMAreaGeometry;

/*================
||
||  IAreaGeometryHandle - this is a internal (NON-API) class used by IGArea class only
||
||  This class wraps up an IMAreaGeometry object.  It handles the reference counting
||  and copy-on-write.  It can be passed by value, since it is very cheap to copy.
||
*/

class IAreaGeometryHandle : public IMSTREAMABLE {

		StreamableDeclarationsMacro(IAreaGeometryHandle);

	protected:
		virtual void writeToStream(IDataStream& toWhere) const;
		virtual void readFromStream(IDataStream& toWhere);

    public:
        IAreaGeometryHandle();     // empty area
        IAreaGeometryHandle(const IAreaGeometryHandle&);
        ~IAreaGeometryHandle();

        IAreaGeometryHandle& operator=(const IAreaGeometryHandle& g);

        bool operator==(const IAreaGeometryHandle&) const;
        bool operator!=(const IAreaGeometryHandle&) const;

        bool operator<(const IAreaGeometryHandle&) const;

    private:
friend class IGArea;
friend class IMAreaGeometry;
friend class ITransformedGeometry;
friend class IRectGeometry;
friend class IRectilinearGeometry;
friend class IEllipseGeometry;
friend class IPolygonGeometry;
friend class ILoopGeometry;
friend class IAddGeometry;
friend class ISubtractGeometry;
friend class IIntersectGeometry;
friend class IExclusiveOrGeometry;
        void add(const IAreaGeometryHandle&);
        void subtract(const IAreaGeometryHandle&);
        void intersect(const IAreaGeometryHandle&);
        void exclusiveOr(const IAreaGeometryHandle&);

        void transformBy(const IGrafMatrix&);


        bool isEmpty() const;
        void setToEmpty();

        bool isRectilinear() const;
        bool isRectangular() const;

        // === Singular:  consists of at most one basic geometry ===
        bool isSingular() const;

        // === Hit methods ===
        IGRect2D  bounds() const;
        bool intersects(const IGRect2D&) const;
        bool contains(const IGPoint2D&) const;
        bool contains(const IGRect2D&) const;

        unsigned long timeStamp() const;

friend class IGraph2DTestHelper;
        void extract(
                    IGrafExtractor& extractor,
                    ICAGNode* parentNode,
                    const IGrafMatrix& matrix = IGrafMatrix::identity()) const;
        IAreaGeometryHandle(IMAreaGeometry* adoptedGeometry);
        IMAreaGeometry* geometry();
        const IMAreaGeometry* geometry() const;

    private:
        IMAreaGeometry* fGeometry;
};

/**
 * IGArea is a device-independent specification of an arbitrarily-shaped area.
 * IGArea is a device-independent specification of an arbitrarily-shaped area.
 * IGArea object is defined as an object that performs certain binary CAG (Constructive Area
 * Geometry) operations on other area-defining geometries, such as IGRect2D, IGEllipse2D, and
 * IGPolygon2D. The CAG operations are Add (union), Subtract, Intersection, and Exclusive OR.
 *  For instance, an IGArea can be made up of the area of a rectangle minus the area of an ellipse.
 */

class IGArea {

	public :
        IDataStream&    operator>>= (IDataStream&) const;
        IDataStream&    operator<<= (IDataStream&);
		void writeToStream( IDataStream& toWhere ) const;
		void readFromStream( IDataStream& toWhere );
    public:
		/**
		 * Default constructor which does nothing.
		 */
        IGArea();

		/**
		 * Creates an area geometry from the specified rectangle.
		 */
        IGArea (const IGRect2D& g);

		/**
		 * Creates an area geometry from the specified ellipse.
		 */
        IGArea (const IGEllipse2D& g);

		/**
		 * Creates an area geometry from the specified polygon.
		 */
        IGArea (const IGPolygon2D& g);

		/**
		 * Creates an area geometry from the specified loop.
		 */
        IGArea (const IGLoop2D& g);

		/**
		 * Creates an area geometry from the specified area.
		 */
        IGArea (const IGArea& g);

        virtual ~IGArea();

		/**
		 * Creates a new area geometry that has no area.
		 */
        static const IGArea& emptyArea ();

		/**
		 * Creates a new area geometry that is infinitely large.
		 */
        static const IGArea& infiniteArea ();

		/**
		 * Transforms the entire area using the specified matrix.
		 */
        void    transformBy (const IGrafMatrix&);

		/**
		 * Tests whether this area contains any geometries.
		 */
        bool    isEmpty () const;

		/**
		 * Removes all basic geometries from this area.
		 */
        void    setToEmpty ();

		/**
		 * Tests whether the area is comprised completely of horizontal and vertical edges.
		 */
        bool isRectilinear () const;

		/**
		 * Tests whether the area is rectangular in shape.
		 */
        bool isRectangular () const;

		/**
		 * Tests whether the area is comprised of a single basic geometry.
		 */
        bool isSingular () const;

		/**
		 * Returns the rectangle that completely encloses the area.
		 */
        IGRect2D  bounds () const;

		/**
		 * Tests whether the area geometry intersects the given rectangle.
		 */
        bool    intersects (const IGRect2D&) const;

		/**
		 * Tests whether the area geometry contains the given point.
		 */
        bool    contains (const IGPoint2D&) const;

		/**
		 * Tests whether the area geometry contains the given rectangle.
		 */
        bool    contains (const IGRect2D&) const;

		/**
		 * Adds the shape of the specified IGArea to the current shape. Addition is achieved through union.
		 */
        void add (const IGArea&);

		/**
		 * Adds the shape of the IGArea on the right side of the operator += to this one. Addition is achieved through union.
		 */
        IGArea& operator+= (const IGArea&);

		/**
		 * Addition operator for IGArea. Addition is achieved through union.
		 */
        friend IGArea operator+ (const IGArea&, const IGArea&);

		/**
		 * Subtracts the shape of the specified IGArea from the current shape.
		 */
        void subtract (const IGArea&);

		/**
		 * Subtracts the shape of the specified IGArea from the current shape.
		 */
        IGArea& operator-= (const IGArea&);

		/**
		 * Subtraction operator for IGArea.
		 */
        friend IGArea operator- (const IGArea&, const IGArea&);

		/**
		 * Sets the shape to the intersection of the current shape with the specified IGArea's shape.
		 */
        void intersect (const IGArea&);

		/**
		 * Intersects the current shape with the specified IGArea's shape.
		 */
        IGArea& operator*= (const IGArea&);

		/**
		 * Intersects two IGAreas.
		 */
        friend IGArea operator* (const IGArea&, const IGArea&);

		/**
		 * Sets the shape to the combined area of the current shape and the specified IGArea's shape, minus their intersection.
		 */
        void exclusiveOr (const IGArea&);

		/**
		 * Sets the shape to the combined area of the current shape and the specified IGArea's shape, minus their intersection.
		 */
        IGArea& operator^= (const IGArea&);

		/**
		 * Sets the shape to the combined area of two IGArea's shape, minus their intersection.
		 */
        friend IGArea operator^ (const IGArea&, const IGArea&);

		/**
		 * Assignment operator.
		 */
        IGArea& operator= (const IGArea&);

		/**
		 * Tests whether the two objects are equal.
		 */
        bool operator== (const IGArea&) const;

		/**
		 * Tests whether the two objects differ.
		 */
        bool operator!= (const IGArea&) const;

		/**
		 * Returns the object's time stamp.
		 */
        unsigned long    timeStamp () const;

    private:
        IGArea (const IAreaGeometryHandle& g);

friend class IGrafDevice;
friend class IGraph2DTestHelper;
        // === Extraction of the contained basic geometries ===
        void    extract (
                    IGrafExtractor& extractor,
                    ICAGNode* parentNode,
                    const IGrafMatrix& coordSys = IGrafMatrix::identity()) const;

    private:
        IAreaGeometryHandle fGeometry;
};

#pragma enum(pop)
#pragma pack(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

#include <igarea2d.inl>

#endif // _IGAREA2D_

