/**
 * This file describes some 2-D line-oriented geometry.
 * Classes described here are:
 *		IGLine2D and IGPolyline2D
 *
 *   IBM Open Class Library
 *   (C) Copyright International Business Machines Corporation,  1997
 *   Licensed Material - Program-Property of IBM - All Rights Reserved.
 *
 */

// Revision: 79 1.20.1.6 source/albert/graph2d/igline2d.hpp, 2d, ioc.v400, 980918 

#ifndef _IGLINE2D_
#define _IGLINE2D_

#include <igbase2d.hpp>
#include <ipt2darr.hpp>
#include <iprimtyp.hpp>

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

class IGrafMatrix;

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


/**
 * IGLine2D is line segment defined by two end points.
 * IGLine2D is line segment defined by two end points.
 * Line segments have an implied direction that move from the starting point to the end point.
 */

class IGLine2D {
	public :
        IDataStream&    operator>>= (IDataStream&) const;
        IDataStream&    operator<<= (IDataStream&);
		void writeToStream( IDataStream& toWhere ) const;
		void readFromStream( IDataStream& toWhere );
    public:

		/**
		 * Default constructor. The start and end points are initialized to IGPoint2D::kOrigin.
		 */
        IGLine2D();

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

		/**
		 * Constructor that takes two IGPoint2D objects as arguments.
		 */
        IGLine2D( IGPoint2D startPt, IGPoint2D endPt );

        virtual ~IGLine2D();

		/**
		 * Returns the starting point of the IGLine2D.
		 */
        IGPoint2D     startPoint() const;

		/**
		 * Returns the end point of the IGLine2D.
		 */
        IGPoint2D     endPoint() const;

		/**
		 * Returns, in its arguments, both end points of the IGLine2D.
		 */
        void        points( IGPoint2D& startPt, IGPoint2D& endPt) const;

		/**
		 * Returns a point corresponding to the parameter.  Values outside the range return an extrapolated point.
		 */
        IGPoint2D     evaluate( GParametric u ) const;

		/**
		 * Sets the starting point of the IGLine2D.
		 */
        void        setStartPoint( const IGPoint2D& point);

		/**
		 * Sets the end point of the IGLine2D.
		 */
        void        setEndPoint( const IGPoint2D& point);

		/**
		 * Transforms the IGLine2D by the specified transformation.
		 */
        void        transformBy( const IGrafMatrix& transform );

		/**
		 * Moves the IGLine2D so that the specified parametric position on the IGLine2D matches the specified point.
		 */
        void        dragPosition(
                                GParametric u,
                                const IGPoint2D& toPoint );

		/**
		 * Finds the parametric value corresponding to the point on the IGLine2D that is nearest to the specified point.
		 * Finds the parametric value corresponding to the point on the IGLine2D that is nearest to the specified point.
		 * Values returned are clamped between 0 and 1.
		 */
        GParametric nearestParametric( const IGPoint2D& test ) const;

		/**
		 * Returns true if the IGLine2D intersects the specified rectangle.
		 */
        bool        intersects( const IGRect2D& g) const;

		/**
		 * Returns the IGLine2D's bounding box (the smallest IGRect2D that encloses the line).
		 */
       IGRect2D      bounds() const;

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

		/**
		 * Tests two IGLine2D objects for equality.
		 */
        bool                operator==( const IGLine2D& Src ) const;

		/**
		 * Tests two IGLine2D objects for inequality.
		 */
        bool                operator!=( const IGLine2D& Src ) const;


    private:
        IGPoint2D fStartPt, fEndPt;
};

class IGPolygon2D;

/**
 * A IGPolyline2D is a collection of points that are connected with straight line segments.
 * A IGPolyline2D is a collection of points that are connected with straight line segments.
 * The line segments form a single path through all the points, so each point, except
 * the first and last, is connected to two other points.
 * It is not explicitly closed (use IGPolygon2D for that; explictly closing a IGPolyline2D
 * may give an unexpected "seam").
 *
 * 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 IGPolyline2D {
	public :
        IDataStream&    operator>>= (IDataStream&) const;
        IDataStream&    operator<<= (IDataStream&);
		void writeToStream( IDataStream& toWhere ) const;
		void readFromStream( IDataStream& toWhere );
    public:

		/**
		 * Default constructor with 0 point.
		 */
        IGPolyline2D();

		/**
		 * Creates an IGPolylin2D with the specified number of control points (IGPoint2D::kOrigin).
		 */
        IGPolyline2D( unsigned long numPoints );

		/**
		 * Creates an IGPolyline2D with the points copied from the IGPoint2DArray.
		 */
        IGPolyline2D( const IGPoint2DArray& points );

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

        virtual ~IGPolyline2D();

		/**
		 * Returns the number of control points in the IGPolyline2D.
		 */
        unsigned long   numberOfPoints() const;

		/**
		 * Returns the control point at the specified index.
		 */
        IGPoint2D     point( unsigned long index ) const;

		/**
		 * Copies the IGPolyline2D's control points into the argument.
		 */
        void        points( IGPoint2DArray& pts) const;

		/**
		 * Return a point at the given parametric distance along the polyline.
		 * Return a point at the given parametric distance along the polyline.
		 * Polylines are parameterized as one integer unit for every point, for example, the
		 * parameter from 0..1 goes between the first and second points, 1..2 between the second
		 * and third, and so on. That is to say, the integer part of u determines which segment
		 * of the polyline is referenced, and the fraction determines where on that segment the
		 * point is.
		 */
        IGPoint2D     evaluate( GParametric u ) const;

		/**
		 * Determines whether all the line segments of the IGPolyline2D are horizontal or vertical.
		 */
        bool        isRectilinear() const;

		/**
		 * Resets the IGPolyline2D's control points. The number of points can be changed.
		 */
        void        setPoints( const IGPoint2DArray& newPoints );

		/**
		 * Resets the control point at the specified index to the IGPoint2D.
		 */
        void        setPoint( unsigned long index, const IGPoint2D& p );

		/**
		 * Inserts the specified IGPoint2D before the control point at the specified index.
		 */
        void        addBefore( unsigned long index, const IGPoint2D& tobeadded );

		/**
		 * Appends the specified point to the end of the IGPolyline2D.
		 */
        void        append( const IGPoint2D& p );

		/**
		 * Removes the control point at the specified index.
		 */
        void        removePoint( unsigned long index );

		/**
		 * Reverses the direction of the IGPolyline2D (that is, the order of the control points).
		 */
        void        reverseDirection();

		/**
		 * Transforms the IGPolyline2D's control points by the specified transformation matrix.
		 */
        void        transformBy( const IGrafMatrix& transform );

		/**
		 * Changes the IGPolyline2D so that it passes through the specified IGPoint2D at the specified parametric.
		 */
        void        dragPosition( GCoordinate parametric, const IGPoint2D& toPoint );

		/**
		 * Returns the parametric value at the point on the polyline nearest to the specified IGPoint2D.
		 */
        GParametric nearestParametric( const IGPoint2D& p ) const;

		/**
		 * Determines whether the IGPolyline2D intersects the specified rectangle.
		 */
        bool        intersects( const IGRect2D& g) const;

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

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

		/**
		 * Tests two IGPolyline2D objects for equality.
		 */
        bool        operator==( const IGPolyline2D& Src ) const;

		/**
		 * Tests two IGPolyline2D objects for inequality.
		 */
        bool        operator!=( const IGPolyline2D& Src ) const;


    private:
        IGPoint2DArray fPoints;
        friend class IGPolygon2D; // For access by IGPolygon2D::contains, etc.
};

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

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

#endif // _IGLINE2D_
