Geometry.cs :  » GIS » DeepEarth » GisSharpBlog » NetTopologySuite » Geometries » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » GIS » DeepEarth 
DeepEarth » GisSharpBlog » NetTopologySuite » Geometries » Geometry.cs
using System;
using System.Collections;
using System.Xml;
using GeoAPI.Geometries;
using GeoAPI.Operations.Buffer;
using GisSharpBlog.NetTopologySuite.Algorithm;
using GisSharpBlog.NetTopologySuite.IO;
using GisSharpBlog.NetTopologySuite.IO.GML2;
using GisSharpBlog.NetTopologySuite.Operation.Buffer;
using GisSharpBlog.NetTopologySuite.Operation.Distance;
using GisSharpBlog.NetTopologySuite.Operation.Overlay;
using GisSharpBlog.NetTopologySuite.Operation.Overlay.Snap;
using GisSharpBlog.NetTopologySuite.Operation.Predicate;
using GisSharpBlog.NetTopologySuite.Operation.Relate;
using GisSharpBlog.NetTopologySuite.Operation.Valid;
using GisSharpBlog.NetTopologySuite.Utilities;
using System.Collections.Generic;

namespace GisSharpBlog.NetTopologySuite.Geometries{   
    /// <summary>  
    /// Basic implementation of <c>Geometry</c>.
    /// <c>Clone</c> returns a deep copy of the object.
    /// <para>
    /// Binary Predicates: 
    /// Because it is not clear at this time what semantics for spatial
    /// analysis methods involving <c>GeometryCollection</c>s would be useful,
    /// <c>GeometryCollection</c>s are not supported as arguments to binary
    /// predicates (other than <c>ConvexHull</c>) or the <c>Relate</c> method.
    /// </para>
    /// <para>
    /// Set-Theoretic Methods: 
    /// The spatial analysis methods will
    /// return the most specific class possible to represent the result. If the
    /// result is homogeneous, a <c>Point</c>, <c>LineString</c>, or
    /// <c>Polygon</c> will be returned if the result contains a single
    /// element; otherwise, a <c>MultiPoint</c>, <c>MultiLineString</c>,
    /// or <c>MultiPolygon</c> will be returned. If the result is
    /// heterogeneous a <c>GeometryCollection</c> will be returned.
    /// </para>
    /// <para>
    /// Representation of Computed Geometries:  
    /// The SFS states that the result
    /// of a set-theoretic method is the "point-set" result of the usual
    /// set-theoretic definition of the operation (SFS 3.2.21.1). However, there are
    /// sometimes many ways of representing a point set as a <c>Geometry</c>.
    /// The SFS does not specify an unambiguous representation of a given point set
    /// returned from a spatial analysis method. One goal of NTS is to make this
    /// specification precise and unambiguous. NTS will use a canonical form for
    /// <c>Geometry</c>s returned from spatial analysis methods. The canonical
    /// form is a <c>Geometry</c> which is simple and noded:
    /// Simple means that the Geometry returned will be simple according to
    /// the NTS definition of <c>IsSimple</c>.
    /// Noded applies only to overlays involving <c>LineString</c>s. It
    /// means that all intersection points on <c>LineString</c>s will be
    /// present as endpoints of <c>LineString</c>s in the result.
    /// This definition implies that non-simple geometries which are arguments to
    /// spatial analysis methods must be subjected to a line-dissolve process to
    /// ensure that the results are simple.
    /// </para>
    /// <para>
    /// Constructed Points And The Precision Model: 
    /// The results computed by the set-theoretic methods may
    /// contain constructed points which are not present in the input <c>Geometry</c>s. 
    /// These new points arise from intersections between line segments in the
    /// edges of the input <c>Geometry</c>s. In the general case it is not
    /// possible to represent constructed points exactly. This is due to the fact
    /// that the coordinates of an intersection point may contain twice as many bits
    /// of precision as the coordinates of the input line segments. In order to
    /// represent these constructed points explicitly, NTS must truncate them to fit
    /// the <c>PrecisionModel</c>. 
    /// Unfortunately, truncating coordinates moves them slightly. Line segments
    /// which would not be coincident in the exact result may become coincident in
    /// the truncated representation. This in turn leads to "topology collapses" --
    /// situations where a computed element has a lower dimension than it would in
    /// the exact result. 
    /// When NTS detects topology collapses during the computation of spatial
    /// analysis methods, it will throw an exception. If possible the exception will
    /// report the location of the collapse. 
    /// </para>
    /// </summary>
    /// <remarks>
    /// <see cref="object.Equals(object)" /> and <see cref="object.GetHashCode" /> are not overridden, so that when two
    /// topologically equal Geometries are added to Collections and Dictionaries, they
    /// remain distinct. This behaviour is desired in many cases.
  /// </remarks>
#if !SILVERLIGHT
  [Serializable]
#endif
  public abstract class Geometry: IGeometry
    {        
        /// <summary>
        /// 
        /// </summary>
        private static readonly Type[] SortedClasses = new Type[] 
        {
            typeof(Point),
            typeof(MultiPoint),
            typeof(LineString),
            typeof(LinearRing),
            typeof(MultiLineString),
            typeof(Polygon),
            typeof(MultiPolygon),
            typeof(GeometryCollection),    
        };                    

        private IGeometryFactory factory = null;

        /// <summary> 
        /// Gets the factory which contains the context in which this point was created.
        /// </summary>
        /// <returns>The factory for this point.</returns>
        public IGeometryFactory Factory
        {
            get 
            { 
                return factory; 
            }
        }

        private object userData = null;
        
        /// <summary> 
        /// Gets/Sets the user data object for this point, if any.
        /// A simple scheme for applications to add their own custom data to a Geometry.
        /// An example use might be to add an object representing a Coordinate Reference System.
        /// Note that user data objects are not present in geometries created by
        /// construction methods.
        /// </summary>
        public object UserData
        {
            get
            {                
                return userData;
            }
            set
            {
                userData = value;
            }
        }
           
        /// <summary>
        /// The bounding box of this <c>Geometry</c>.
        /// </summary>
        protected IEnvelope envelope;
       
        // The ID of the Spatial Reference System used by this <c>Geometry</c>
        private int srid;

        /// <summary>  
        /// Gets/Sets the ID of the Spatial Reference System used by the <c>Geometry</c>. 
        /// NTS supports Spatial Reference System information in the simple way
        /// defined in the SFS. A Spatial Reference System ID (SRID) is present in
        /// each <c>Geometry</c> object. <c>Geometry</c> provides basic
        /// accessor operations for this field, but no others. The SRID is represented
        /// as an integer.
        /// </summary>        
        public int SRID
        {
            get 
            { 
                return srid; 
            }
            set 
            {
                srid = value;
        IGeometryCollection collection = this as IGeometryCollection;
        if (collection != null)
        {
          foreach (IGeometry geometry in collection.Geometries)
          {
            geometry.SRID = value;
          }
        }
        factory = new GeometryFactory(factory.PrecisionModel, value, factory.CoordinateSequenceFactory);
      }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="factory"></param>
        public Geometry(IGeometryFactory factory)
        {
            this.factory = factory;
            srid = factory.SRID;
        }

        /// <summary>  
        /// Returns the name of this object's interface.
    /// </summary>
    /// <returns>The name of this <c>Geometry</c>s most specific interface.</returns>
        public abstract string GeometryType { get; }

        /// <summary>  
        /// Returns true if the array contains any non-empty <c>Geometry</c>s.
    /// </summary>
    /// <param name="geometries"> an array of <c>Geometry</c>s; no elements may be <c>null</c></param>
    /// <returns>            
        /// <c>true</c> if any of the <c>Geometry</c>s
    /// <c>IsEmpty</c> methods return <c>false</c>.
    /// </returns>
        protected static bool HasNonEmptyElements(IGeometry[] geometries)
        {
            foreach (IGeometry g in geometries)
                if(!g.IsEmpty)
                    return true;                                        
            return false;
        }

        /// <summary>  
        /// Returns true if the array contains any <c>null</c> elements.
        /// </summary>
        /// <param name="array"> an array to validate.</param>
        /// <returns><c>true</c> if any of <c>array</c>s elements are <c>null</c>.</returns>
        public static bool HasNullElements(object[] array)
        {
            foreach (object o in array)
                if (o == null)
                    return true;
            return false;            
        }

        /// <summary>  
        /// Returns the <c>PrecisionModel</c> used by the <c>Geometry</c>.
        /// </summary>
        /// <returns>    
        /// the specification of the grid of allowable points, for this
        /// <c>Geometry</c> and all other <c>Geometry</c>s.
        /// </returns>
        public IPrecisionModel PrecisionModel
        {
            get
            {
                return Factory.PrecisionModel;
            }
        }

        /// <summary>  
        /// Returns a vertex of this <c>Geometry</c>.
        /// </summary>
        /// <returns>    
        /// a Coordinate which is a vertex of this <c>Geometry</c>.
        /// Returns <c>null</c> if this Geometry is empty.
        /// </returns>
        public abstract ICoordinate Coordinate { get; }

        /// <summary>  
        /// Returns this <c>Geometry</c> s vertices. If you modify the coordinates
        /// in this array, be sure to call GeometryChanged afterwards.
        /// The <c>Geometry</c>s contained by composite <c>Geometry</c>s
        /// must be Geometry's; that is, they must implement <c>Coordinates</c>.
        /// </summary>
        /// <returns>The vertices of this <c>Geometry</c>.</returns>
        public abstract ICoordinate[] Coordinates { get; }

        /// <summary>  
        /// Returns the count of this <c>Geometry</c>s vertices. The <c>Geometry</c>
        /// s contained by composite <c>Geometry</c>s must be
        /// Geometry's; that is, they must implement <c>NumPoints</c>.
        /// </summary>
        /// <returns>The number of vertices in this <c>Geometry</c>.</returns>
        public abstract int NumPoints { get; }

        /// <summary>
        /// Returns the number of Geometryes in a GeometryCollection,
        /// or 1, if the geometry is not a collection.
        /// </summary>
        public virtual int NumGeometries
        {
            get
            {
                return 1;
            }
        }
        
        /// <summary>
        /// Returns an element Geometry from a GeometryCollection,
        /// or <code>this</code>, if the geometry is not a collection.
        /// </summary>
        /// <param name="n">The index of the geometry element.</param>
        /// <returns>The n'th geometry contained in this geometry.</returns>
        public virtual IGeometry GetGeometryN(int n)
        {
            return this;
        }

        /// <summary> 
        /// Returns false if the <c>Geometry</c> not simple.
        /// Subclasses provide their own definition of "simple". If
        /// this <c>Geometry</c> is empty, returns <c>true</c>. 
        /// In general, the SFS specifications of simplicity seem to follow the
        /// following rule:
        ///  A Geometry is simple if the only self-intersections are at boundary points.
        /// For all empty <c>Geometry</c>s, <c>IsSimple==true</c>.
        /// </summary>
        /// <returns>    
        /// <c>true</c> if this <c>Geometry</c> has any points of
        /// self-tangency, self-intersection or other anomalous points.
        /// </returns>
        public abstract bool IsSimple { get; }

        /// <summary>  
        /// Tests the validity of this <c>Geometry</c>.
        /// Subclasses provide their own definition of "valid".
        /// </summary>
        /// <returns><c>true</c> if this <c>Geometry</c> is valid.</returns>
        public virtual bool IsValid
        {
            get
            {
                IsValidOp isValidOp = new IsValidOp(this);
                return isValidOp.IsValid;
            }
        }

        /// <summary> 
        /// Returns whether or not the set of points in this <c>Geometry</c> is empty.
        /// </summary>
        /// <returns><c>true</c> if this <c>Geometry</c> equals the empty point.</returns>
        public abstract bool IsEmpty { get; }

        /// <summary>  
        /// Returns the minimum distance between this <c>Geometry</c>
        /// and the <c>Geometry</c> g.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> from which to compute the distance.</param>
        public double Distance(IGeometry g)
        {
            return DistanceOp.Distance(this, g);
        }

        /// <summary> 
        /// Tests whether the distance from this <c>Geometry</c>
        /// to another is less than or equal to a specified value.
        /// </summary>
        /// <param name="geom">the Geometry to check the distance to.</param>
        /// <param name="distance">the distance value to compare.</param>
        /// <returns><c>true</c> if the geometries are less than <c>distance</c> apart.</returns>
        public bool IsWithinDistance(IGeometry geom, double distance)
        {
            double envDist = EnvelopeInternal.Distance(geom.EnvelopeInternal);            
            if (envDist > distance)
                return false;
            return DistanceOp.IsWithinDistance(this, geom, distance);
        }

        /// <summary>  
        /// Returns the area of this <c>Geometry</c>.
        /// Areal Geometries have a non-zero area.
        /// They override this function to compute the area.
        /// Others return 0.0
        /// </summary>
        /// <returns>The area of the Geometry.</returns>
        public virtual double Area
        {
            get
            {
                return 0.0;
            }
        }

        /// <summary> 
        /// Returns the length of this <c>Geometry</c>.
        /// Linear geometries return their length.
        /// Areal geometries return their perimeter.
        /// They override this function to compute the length.
        /// Others return 0.0
        /// </summary>
        /// <returns>The length of the Geometry.</returns>
        public virtual double Length
        {
            get
            {
                return 0.0;
            }
        }

        /// <summary> 
        /// Computes the centroid of this <c>Geometry</c>.
        /// The centroid is equal to the centroid of the set of component Geometries of highest
        /// dimension (since the lower-dimension geometries contribute zero "weight" to the centroid).
        /// </summary>
        /// <returns>A Point which is the centroid of this Geometry.</returns>
        public IPoint Centroid
        {
            get
            {
                if (IsEmpty) 
                    return null;

                ICoordinate centPt = null;
                Dimensions dim = Dimension;
                if (dim == Dimensions.Point)
                {
                    CentroidPoint cent = new CentroidPoint();
                    cent.Add(this);
                    centPt = cent.Centroid;
                }
                else if (dim == Dimensions.Curve)
                {
                    CentroidLine cent = new CentroidLine();
                    cent.Add(this);
                    centPt = cent.Centroid;
                }
                else
                {
                    CentroidArea cent = new CentroidArea();
                    cent.Add(this);
                    centPt = cent.Centroid;
                }
                return CreatePointFromInternalCoord(centPt, this);
            }
        }

        /// <summary>
        /// Computes an interior point of this <c>Geometry</c>.
        /// An interior point is guaranteed to lie in the interior of the Geometry,
        /// if it possible to calculate such a point exactly. Otherwise,
        /// the point may lie on the boundary of the point.
        /// </summary>
        /// <returns>A <c>Point</c> which is in the interior of this Geometry.</returns>
        public IPoint InteriorPoint
        {
            get
            {
                ICoordinate interiorPt = null;
                Dimensions dim = Dimension;
                if (dim == Dimensions.Point)
                {
                    InteriorPointPoint intPt = new InteriorPointPoint(this);
                    interiorPt = intPt.InteriorPoint;
                }
                else if (dim == Dimensions.Curve)
                {
                    InteriorPointLine intPt = new InteriorPointLine(this);
                    interiorPt = intPt.InteriorPoint;
                }
                else
                {
                    InteriorPointArea intPt = new InteriorPointArea(this);
                    interiorPt = intPt.InteriorPoint;
                }
                return CreatePointFromInternalCoord(interiorPt, this);
            }
        }

        /// <summary>
        /// <see cref="InteriorPoint" />
        /// </summary>
        public IPoint PointOnSurface
        {
            get
            {
                return InteriorPoint;
            }
        }

        private Dimensions dimension;

        /// <summary> 
        /// Returns the dimension of this <c>Geometry</c>.
        /// </summary>
        /// <returns>  
        /// The dimension of the class implementing this interface, whether
        /// or not this object is the empty point.
        /// </returns>
        public virtual Dimensions Dimension
        {
            get { return dimension; }
            set { dimension = value; }
        }


        private IGeometry boundary;

        /// <summary>  
        /// Returns the boundary, or the empty point if this <c>Geometry</c>
        /// is empty. For a discussion of this function, see the OpenGIS Simple
        /// Features Specification. As stated in SFS Section 2.1.13.1, "the boundary
        /// of a Geometry is a set of Geometries of the next lower dimension."
        /// </summary>
        /// <returns>The closure of the combinatorial boundary of this <c>Geometry</c>.</returns>
        public virtual IGeometry Boundary
        {
            get { return boundary; }
            set { boundary = value; }
        }

        private Dimensions boundaryDimension;

        /// <summary> 
        /// Returns the dimension of this <c>Geometry</c>s inherent boundary.
        /// </summary>
        /// <returns>    
        /// The dimension of the boundary of the class implementing this
        /// interface, whether or not this object is the empty point. Returns
        /// <c>Dimension.False</c> if the boundary is the empty point.
        /// </returns>
        public virtual Dimensions BoundaryDimension
        {
            get { return boundaryDimension; }
            set { boundaryDimension = value; }
        }

        /// <summary>  
        /// Returns this <c>Geometry</c>s bounding box. If this <c>Geometry</c>
        /// is the empty point, returns an empty <c>Point</c>. If the <c>Geometry</c>
        /// is a point, returns a non-empty <c>Point</c>. Otherwise, returns a
        /// <c>Polygon</c> whose points are (minx, miny), (maxx, miny), (maxx,
        /// maxy), (minx, maxy), (minx, miny).
        /// </summary>
        /// <returns>    
        /// An empty <c>Point</c> (for empty <c>Geometry</c>s), a
        /// <c>Point</c> (for <c>Point</c>s) or a <c>Polygon</c>
        /// (in all other cases).
        /// </returns>
        public IGeometry Envelope
        {
            get
            {
                return Factory.ToGeometry(EnvelopeInternal);
            }
        }

        /// <summary> 
        /// Returns the minimum and maximum x and y values in this <c>Geometry</c>
        /// , or a null <c>Envelope</c> if this <c>Geometry</c> is empty.
        /// </summary>
        /// <returns>    
        /// This <c>Geometry</c>s bounding box; if the <c>Geometry</c>
        /// is empty, <c>Envelope.IsNull</c> will return <c>true</c>.
        /// </returns>
        public IEnvelope EnvelopeInternal
        {
            get
            {
                if (envelope == null)
                    envelope = ComputeEnvelopeInternal();                
                return envelope;
            }
        }

        private class GeometryChangedFilter : IGeometryComponentFilter
        {
            public void Filter(IGeometry geom)
            {
                geom.GeometryChangedAction();
            }
        };

        /// <summary>
        /// Notifies this Geometry that its Coordinates have been changed by an external
        /// party (using a CoordinateFilter, for example). The Geometry will flush
        /// and/or update any information it has cached (such as its Envelope).
        /// </summary>
        public void GeometryChanged()
        {
            Apply(new GeometryChangedFilter());
        }

        /// <summary> 
        /// Notifies this Geometry that its Coordinates have been changed by an external
        /// party. When GeometryChanged is called, this method will be called for
        /// this Geometry and its component Geometries.
        /// </summary>
        public void GeometryChangedAction()
        {
            envelope = null;
        }

        /// <summary>  
        /// Returns <c>true</c> if the DE-9IM intersection matrix for the two
        /// <c>Geometry</c>s is FF*FF****.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns><c>true</c> if the two <c>Geometry</c>s are disjoint.</returns>
        public bool Disjoint(IGeometry g)
        {
            // short-circuit test
            if (! EnvelopeInternal.Intersects(g.EnvelopeInternal))
                return true;
            return Relate(g).IsDisjoint();
        }

        /// <summary>  
        /// Returns <c>true</c> if the DE-9IM intersection matrix for the two
        /// <c>Geometry</c>s is FT*******, F**T***** or F***T****.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns>
        /// <c>true</c> if the two <c>Geometry</c>s touch;
        /// Returns false if both <c>Geometry</c>s are points.
        /// </returns>
        public bool Touches(IGeometry g) 
        {
            // short-circuit test
            if (! EnvelopeInternal.Intersects(g.EnvelopeInternal))
                return false;
            return Relate(g).IsTouches(Dimension, g.Dimension);
        }

        /// <summary>  
        /// Returns <c>true</c> if <c>disjoint</c> returns false.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns><c>true</c> if the two <c>Geometry</c>s intersect.</returns>
        public bool Intersects(IGeometry g) 
        {
            // short-circuit test
            if (!EnvelopeInternal.Intersects(g.EnvelopeInternal))
                return false;
            // optimizations for rectangle arguments
            if (IsRectangle)
                return RectangleIntersects.Intersects((IPolygon) this, g);
            if (g.IsRectangle)
                return RectangleIntersects.Intersects((IPolygon) g, this);
            return Relate(g).IsIntersects();
        }

        /// <summary>  
        /// Returns <c>true</c> if the DE-9IM intersection matrix for the two
        /// <c>Geometry</c>s is
        ///  T*T****** (for a point and a curve, a point and an area or a line
        /// and an area) 0******** (for two curves).
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns>
        /// <c>true</c> if the two <c>Geometry</c>s cross.
        /// For this function to return <c>true</c>, the <c>Geometry</c>
        /// s must be a point and a curve; a point and a surface; two curves; or a
        /// curve and a surface.
        /// </returns>
        public bool Crosses(IGeometry g) 
        {
            // short-circuit test
            if (! EnvelopeInternal.Intersects(g.EnvelopeInternal))
                return false;
            return Relate(g).IsCrosses(Dimension, g.Dimension);
        }

        /// <summary>
        /// Returns <c>true</c> if the DE-9IM intersection matrix for the two
        /// <c>Geometry</c>s is T*F**F***.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns><c>true</c> if this <c>Geometry</c> is within <c>other</c>.</returns>
        public bool Within(IGeometry g)
        {
            return g.Contains(this); ;
        }

        /// <summary>
        /// Returns <c>true</c> if <c>other.within(this)</c> returns <c>true</c>.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns><c>true</c> if this <c>Geometry</c> contains <c>other</c>.</returns>
        public bool Contains(IGeometry g) 
        {
            // short-circuit test
            if (!EnvelopeInternal.Contains(g.EnvelopeInternal))
                return false;
            // optimizations for rectangle arguments
            if (IsRectangle)
                return RectangleContains.Contains((IPolygon) this, g);
            // general case
            return Relate(g).IsContains();
        }

        /// <summary>
        /// Returns <c>true</c> if the DE-9IM intersection matrix for the two
        /// <c>Geometry</c>s is
        ///  T*T***T** (for two points or two surfaces)
        ///  1*T***T** (for two curves).
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns>
        /// <c>true</c> if the two <c>Geometry</c>s overlap.
        /// For this function to return <c>true</c>, the <c>Geometry</c>
        /// s must be two points, two curves or two surfaces.
        /// </returns>
        public bool Overlaps(IGeometry g) 
        {
            // short-circuit test
            if (! EnvelopeInternal.Intersects(g.EnvelopeInternal))
                return false;
            return Relate(g).IsOverlaps(Dimension, g.Dimension);
        }

        /// <summary>
        /// Returns <c>true</c> if this geometry covers the specified geometry.
        /// <para>
        /// The <c>Covers</c> predicate has the following equivalent definitions:
        ///     - Every point of the other geometry is a point of this geometry.
        ///     - The DE-9IM Intersection Matrix for the two geometries is <c>T*****FF*</c> or <c>*T****FF*</c> or <c>***T**FF*</c> or <c>****T*FF*</c>.
        ///     - <c>g.CoveredBy(this)</c> (<c>Covers</c> is the inverse of <c>CoveredBy</c>).
        /// </para>
        /// Note the difference between <c>Covers</c> and <c>Contains</c>: <c>Covers</c> is a more inclusive relation.
        /// In particular, unlike <c>Contains</c> it does not distinguish between
        /// points in the boundary and in the interior of geometries.        
        /// </summary>
        /// <remarks>
        /// For most situations, <c>Covers</c> should be used in preference to <c>Contains</c>.
        /// As an added benefit, <c>Covers</c> is more amenable to optimization, and hence should be more performant.
        /// </remarks>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c></param>
        /// <returns><c>true</c> if this <c>Geometry</c> covers <paramref name="g" /></returns>
        /// <seealso cref="Geometry.Contains" />
        /// <seealso cref="Geometry.CoveredBy" />
        public bool Covers(IGeometry g)
        {
            // short-circuit test
            if (!EnvelopeInternal.Contains(g.EnvelopeInternal))
                return false;
            
            // optimization for rectangle arguments
            if (IsRectangle)
                return EnvelopeInternal.Contains(g.EnvelopeInternal);
            
            return Relate(g).IsCovers();
        }

        /// <summary>
        /// Returns <c>true</c> if this geometry is covered by the specified geometry.
        /// <para>
        /// The <c>CoveredBy</c> predicate has the following equivalent definitions:
        ///     - Every point of this geometry is a point of the other geometry.
        ///     - The DE-9IM Intersection Matrix for the two geometries is <c>T*F**F***</c> or <c>*TF**F***</c> or <c>**FT*F***</c> or <c>**F*TF***</c>.
        ///     - <c>g.Covers(this)</c> (<c>CoveredBy</c> is the inverse of <c>Covers</c>).
        /// </para>
        /// Note the difference between <c>CoveredBy</c> and <c>Within</c>: <c>CoveredBy</c> is a more inclusive relation.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c></param>.
        /// <returns><c>true</c> if this <c>Geometry</c> is covered by <paramref name="g" />.</returns>
        /// <seealso cref="Geometry.Within" />
        /// <seealso cref="Geometry.Covers" />
        public bool CoveredBy(IGeometry g)
        {
            return g.Covers(this);
        }

        /// <summary>  
        /// Returns <c>true</c> if the elements in the DE-9IM intersection
        /// matrix for the two <c>Geometry</c>s match the elements in <c>intersectionPattern</c>
        /// , which may be:
        ///  0
        ///  1
        ///  2
        ///  T ( = 0, 1 or 2)
        ///  F ( = -1)
        ///  * ( = -1, 0, 1 or 2)
        /// For more information on the DE-9IM, see the OpenGIS Simple Features
        /// Specification.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <param name="intersectionPattern">The pattern against which to check the intersection matrix for the two <c>Geometry</c>s.</param>
        /// <returns><c>true</c> if the DE-9IM intersection matrix for the two <c>Geometry</c>s match <c>intersectionPattern</c>.</returns>
        public bool Relate(IGeometry g, string intersectionPattern)
        {
            return Relate(g).Matches(intersectionPattern);
        }

        /// <summary>
        /// Returns the DE-9IM intersection matrix for the two <c>Geometry</c>s.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c></param>
        /// <returns>
        /// A matrix describing the intersections of the interiors,
        /// boundaries and exteriors of the two <c>Geometry</c>s.
        /// </returns>
        public IntersectionMatrix Relate(IGeometry g) 
        {
            CheckNotGeometryCollection(this);
            CheckNotGeometryCollection(g);

            return RelateOp.Relate(this, g);
        }                    
                
        /// <summary>
        /// Returns <c>true</c> if the DE-9IM intersection matrix for the two
        /// <c>Geometry</c>s is T*F**FFF*.
        /// </summary>
        /// <param name="g">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns><c>true</c> if the two <c>Geometry</c>s are equal.</returns>
        public bool Equals(IGeometry g)
        {
            // NOTE: Not in JTS!!!
      if (IsEmpty && g.IsEmpty)
        return true;

            // Short-circuit test
            if (!EnvelopeInternal.Intersects(g.EnvelopeInternal))
                return false;

            // NOTE: Not in JTS!!!
            // We use an alternative method for compare GeometryCollections (but not subclasses!), 
            if (isGeometryCollection(this) || isGeometryCollection(g))
                return CompareGeometryCollections(this, g);
            
            // Use RelateOp comparation method
            return Relate(g).IsEquals(Dimension, g.Dimension);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj1"></param>
        /// <param name="obj2"></param>
        /// <returns></returns>
        private static bool CompareGeometryCollections(IGeometry obj1, IGeometry obj2)
        {
            IGeometryCollection coll1 = obj1 as IGeometryCollection;
            IGeometryCollection coll2 = obj2 as IGeometryCollection;
            if (coll1 == null || coll2 == null)
                return false;

            // Short-circuit test
            if (coll1.NumGeometries != coll2.NumGeometries)
                return false;

            // Deep test
            for (int i = 0; i < coll1.NumGeometries; i++)
            {
                IGeometry geom1 = coll1[i];
                IGeometry geom2 = coll2[i];
                if (!geom1.Equals(geom2))
                    return false;
            }

            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            if (GetType().Namespace != obj.GetType().Namespace)
                return false;            
            return Equals((IGeometry) obj);         
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj1"></param>
        /// <param name="obj2"></param>
        /// <returns></returns>
        public static bool operator ==(Geometry obj1, IGeometry obj2)
        {            
            return Equals(obj1, obj2); 
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj1"></param>
        /// <param name="obj2"></param>
        /// <returns></returns>
        public static bool operator !=(Geometry obj1, IGeometry obj2)
        {
            return !(obj1 == obj2);
        }    

        /// <summary>
        /// 
        /// </summary>
        public override int GetHashCode()
        {
            int result = 17;            
            foreach (Coordinate coord in Coordinates)
                result = 37 * result + coord.X.GetHashCode();                        
            return result;
        } 

        /// <summary>
        /// Returns the Well-known Text representation of this <c>Geometry</c>.
        /// For a definition of the Well-known Text format, see the OpenGIS Simple
        /// Features Specification.
        /// </summary>
        /// <returns>
        /// The Well-known Text representation of this <c>Geometry</c>.
        /// </returns>
        public override string ToString() 
        {
            return ToText();
        }

        /// <summary>
        /// Returns the Well-known Text representation of this <c>Geometry</c>.
        /// For a definition of the Well-known Text format, see the OpenGIS Simple
        /// Features Specification.
        /// </summary>
        /// <returns>
        /// The Well-known Text representation of this <c>Geometry</c>.
        /// </returns>
        public string ToText() 
        {
            WKTWriter writer = new WKTWriter();
            return writer.Write(this);
        }

        /// <summary>
        /// <see cref="ToText" />
        /// </summary>
        /// <returns></returns>
        public string AsText()
        {
            return ToText();
        }

        /// <summary>
        /// Returns the Well-known Binary representation of this <c>Geometry</c>.
        /// For a definition of the Well-known Binary format, see the OpenGIS Simple
        /// Features Specification.
        /// </summary>
        /// <returns>The Well-known Binary representation of this <c>Geometry</c>.</returns>
        public byte[] ToBinary()
        {
            WKBWriter writer = new WKBWriter();
            return writer.Write(this);
        }

        /// <summary>
        /// <see cref="ToBinary" />
        /// </summary>
        /// <returns></returns>
        public byte[] AsBinary()
        {
            return ToBinary();
        }

        /// <summary>
        /// Returns the feature representation as GML 2.1.1 XML document.
        /// This XML document is based on <c>Geometry.xsd</c> schema.
        /// NO features or XLink are implemented here!
        /// </summary>        
        public XmlReader ToGMLFeature()
        {
            GMLWriter writer = new GMLWriter();
            return writer.Write(this);
        }        

        /// <summary>
        /// Returns a buffer region around this <c>Geometry</c> having the given width.
        /// The buffer of a Geometry is the Minkowski sum or difference of the Geometry with a disc of radius <c>distance</c>.
        /// </summary>
        /// <param name="distance">
        /// The width of the buffer, interpreted according to the
        /// <c>PrecisionModel</c> of the <c>Geometry</c>.
        /// </param>
        /// <returns>
        /// All points whose distance from this <c>Geometry</c>
        /// are less than or equal to <c>distance</c>.
        /// </returns>
        public IGeometry Buffer(double distance)
        {
            return BufferOp.Buffer(this, distance);
        }

        /// <summary>
        /// Returns a buffer region around this <c>Geometry</c> having the given width.
        /// The buffer of a Geometry is the Minkowski sum or difference of the Geometry with a disc of radius <c>distance</c>.
        /// </summary>
        /// <param name="distance">
        /// The width of the buffer, interpreted according to the
        /// <c>PrecisionModel</c> of the <c>Geometry</c>.
        /// </param>
        /// <param name="endCapStyle">Cap Style to use for compute buffer.</param>
        /// <returns>
        /// All points whose distance from this <c>Geometry</c>
        /// are less than or equal to <c>distance</c>.
        /// </returns>
        public IGeometry Buffer(double distance, BufferStyle endCapStyle)
        {
            return BufferOp.Buffer(this, distance, endCapStyle);
        }

        /// <summary>
        /// Returns a buffer region around this <c>Geometry</c> having the given
        /// width and with a specified number of segments used to approximate curves.
        /// The buffer of a Geometry is the Minkowski sum of the Geometry with
        /// a disc of radius <c>distance</c>.  Curves in the buffer polygon are
        /// approximated with line segments.  This method allows specifying the
        /// accuracy of that approximation.
        /// </summary>
        /// <param name="distance">
        /// The width of the buffer, interpreted according to the
        /// <c>PrecisionModel</c> of the <c>Geometry</c>.
        /// </param>
        /// <param name="quadrantSegments">The number of segments to use to approximate a quadrant of a circle.</param>
        /// <returns>
        /// All points whose distance from this <c>Geometry</c>
        /// are less than or equal to <c>distance</c>.
        /// </returns>
        public IGeometry Buffer(double distance, int quadrantSegments) 
        {
            return BufferOp.Buffer(this, distance, quadrantSegments);
        }

        /// <summary>
        /// Returns a buffer region around this <c>Geometry</c> having the given
        /// width and with a specified number of segments used to approximate curves.
        /// The buffer of a Geometry is the Minkowski sum of the Geometry with
        /// a disc of radius <c>distance</c>.  Curves in the buffer polygon are
        /// approximated with line segments.  This method allows specifying the
        /// accuracy of that approximation.
        /// </summary>
        /// <param name="distance">
        /// The width of the buffer, interpreted according to the
        /// <c>PrecisionModel</c> of the <c>Geometry</c>.
        /// </param>
        /// <param name="quadrantSegments">The number of segments to use to approximate a quadrant of a circle.</param>
        /// <param name="endCapStyle">Cap Style to use for compute buffer.</param>
        /// <returns>
        /// All points whose distance from this <c>Geometry</c>
        /// are less than or equal to <c>distance</c>.
        /// </returns>
        public IGeometry Buffer(double distance, int quadrantSegments, BufferStyle endCapStyle)
        {
            return BufferOp.Buffer(this, distance, quadrantSegments, endCapStyle);
        } 

        /// <summary>
        /// Returns the smallest convex <c>Polygon</c> that contains all the
        /// points in the <c>Geometry</c>. This obviously applies only to <c>Geometry</c>
        /// s which contain 3 or more points.
        /// </summary>
        /// <returns>the minimum-area convex polygon containing this <c>Geometry</c>'s points.</returns>
        public virtual IGeometry ConvexHull()
        {
            return (new ConvexHull(this)).GetConvexHull();         
        }

        /// <summary>
        /// Returns a <c>Geometry</c> representing the points shared by this
        /// <c>Geometry</c> and <c>other</c>.
        /// </summary>
        /// <param name="other">The <c>Geometry</c> with which to compute the intersection.</param>
        /// <returns>The points common to the two <c>Geometry</c>s.</returns>
        public IGeometry Intersection(IGeometry other) 
        {
            // Special case: if one input is empty ==> empty
            if (IsEmpty) 
                return Factory.CreateGeometryCollection(null);
            if (other.IsEmpty) 
                return Factory.CreateGeometryCollection(null);


            CheckNotGeometryCollection(this);
            CheckNotGeometryCollection(other);        
            return SnapIfNeededOverlayOp.Overlay(this, other, SpatialFunction.Intersection);
        }

        /// <summary>
        /// Returns a <c>Geometry</c> representing all the points in this <c>Geometry</c>
        /// and <c>other</c>.
        /// </summary>
        /// <param name="other">The <c>Geometry</c> with which to compute the union.</param>
        /// <returns>A set combining the points of this <c>Geometry</c> and the points of <c>other</c>.</returns>
        public IGeometry Union(IGeometry other) 
        {
            // Special case: if either input is empty ==> other input
            if (IsEmpty) 
                return (IGeometry) other.Clone();
            if (other.IsEmpty) 
                return (IGeometry) Clone();

            CheckNotGeometryCollection(this);
            CheckNotGeometryCollection(other);
            return SnapIfNeededOverlayOp.Overlay(this, other, SpatialFunction.Union);
        }

        /// <summary>
        /// Returns a <c>Geometry</c> representing the points making up this
        /// <c>Geometry</c> that do not make up <c>other</c>. This method
        /// returns the closure of the resultant <c>Geometry</c>.
        /// </summary>
        /// <param name="other">The <c>Geometry</c> with which to compute the difference.</param>
        /// <returns>The point set difference of this <c>Geometry</c> with <c>other</c>.</returns>
        public IGeometry Difference(IGeometry other)
        {
            // Special case: if A.isEmpty ==> empty; if B.isEmpty ==> A
            if (IsEmpty) 
                return Factory.CreateGeometryCollection(null);
            if (other.IsEmpty) 
                return (IGeometry) Clone();

            CheckNotGeometryCollection(this);
            CheckNotGeometryCollection(other);
            return SnapIfNeededOverlayOp.Overlay(this, other, SpatialFunction.Difference);
         }

        /// <summary>
        /// Returns a set combining the points in this <c>Geometry</c> not in
        /// <c>other</c>, and the points in <c>other</c> not in this
        /// <c>Geometry</c>. This method returns the closure of the resultant
        /// <c>Geometry</c>.
        /// </summary>
        /// <param name="other">The <c>Geometry</c> with which to compute the symmetric difference.</param>
        /// <returns>The point set symmetric difference of this <c>Geometry</c> with <c>other</c>.</returns>
        public IGeometry SymmetricDifference(IGeometry other) 
        {
            // Special case: if either input is empty ==> other input
            if (IsEmpty) 
                return (IGeometry) other.Clone();
            if (other.IsEmpty) 
                return (IGeometry) Clone();

            CheckNotGeometryCollection(this);
            CheckNotGeometryCollection(other);
            return SnapIfNeededOverlayOp.Overlay(this, other, SpatialFunction.SymDifference);
        }

        /// <summary>
        /// Returns true if the two <c>Geometry</c>s are exactly equal,
        /// up to a specified tolerance.
        /// Two Geometries are exactly within a tolerance equal iff:
        /// they have the same class,
        /// they have the same values of Coordinates,
        /// within the given tolerance distance, in their internal
        /// Coordinate lists, in exactly the same order.
        /// If this and the other <c>Geometry</c>s are
        /// composites and any children are not <c>Geometry</c>s, returns
        /// false.
        /// </summary>
        /// <param name="other">The <c>Geometry</c> with which to compare this <c>Geometry</c></param>
        /// <param name="tolerance">Distance at or below which two Coordinates will be considered equal.</param>
        /// <returns>
        /// <c>true</c> if this and the other <c>Geometry</c>
        /// are of the same class and have equal internal data.
        /// </returns>
        public abstract bool EqualsExact(IGeometry other, double tolerance);

        /// <summary>
        /// Returns true if the two <c>Geometry</c>s are exactly equal.
        /// Two Geometries are exactly equal iff:
        /// they have the same class,
        /// they have the same values of Coordinates in their internal
        /// Coordinate lists, in exactly the same order.
        /// If this and the other <c>Geometry</c>s are
        /// composites and any children are not <c>Geometry</c>s, returns
        /// false.
        /// This provides a stricter test of equality than <c>equals</c>.
        /// </summary>
        /// <param name="other">The <c>Geometry</c> with which to compare this <c>Geometry</c>.</param>
        /// <returns>
        /// <c>true</c> if this and the other <c>Geometry</c>
        /// are of the same class and have equal internal data.
        /// </returns>
        public bool EqualsExact(IGeometry other) 
        { 
            return EqualsExact(other, 0); 
        }

        /// <summary>
        /// Performs an operation with or on this <c>Geometry</c>'s
        /// coordinates. If you are using this method to modify the point, be sure
        /// to call GeometryChanged() afterwards. Note that you cannot use this
        /// method to
        /// modify this Geometry if its underlying CoordinateSequence's Get method
        /// returns a copy of the Coordinate, rather than the actual Coordinate stored
        /// (if it even stores Coordinates at all).
        /// </summary>
        /// <param name="filter">The filter to apply to this <c>Geometry</c>'s coordinates</param>
        public abstract void Apply(ICoordinateFilter filter);

        /// <summary>
        /// Performs an operation with or on this <c>Geometry</c> and its
        /// subelement <c>Geometry</c>s (if any).
        /// Only GeometryCollections and subclasses
        /// have subelement Geometry's.
        /// </summary>
        /// <param name="filter">
        /// The filter to apply to this <c>Geometry</c> (and
        /// its children, if it is a <c>GeometryCollection</c>).
        /// </param>
        public abstract void Apply(IGeometryFilter filter);

        /// <summary>
        /// Performs an operation with or on this Geometry and its
        /// component Geometry's. Only GeometryCollections and
        /// Polygons have component Geometry's; for Polygons they are the LinearRings
        /// of the shell and holes.
        /// </summary>
        /// <param name="filter">The filter to apply to this <c>Geometry</c>.</param>
        public abstract void Apply(IGeometryComponentFilter filter);

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual object Clone() 
        {            
            Geometry clone = (Geometry) MemberwiseClone();
            if (clone.envelope != null) 
                clone.envelope = new Envelope(clone.envelope);                 
            return clone;         
        }

        /// <summary>
        /// Converts this <c>Geometry</c> to normal form (or 
        /// canonical form ). Normal form is a unique representation for <c>Geometry</c>
        /// s. It can be used to test whether two <c>Geometry</c>s are equal
        /// in a way that is independent of the ordering of the coordinates within
        /// them. Normal form equality is a stronger condition than topological
        /// equality, but weaker than pointwise equality. The definitions for normal
        /// form use the standard lexicographical ordering for coordinates. "Sorted in
        /// order of coordinates" means the obvious extension of this ordering to
        /// sequences of coordinates.
        /// </summary>
        public abstract void Normalize();

        /// <summary>
        /// Returns whether this <c>Geometry</c> is greater than, equal to,
        /// or less than another <c>Geometry</c>. 
        /// If their classes are different, they are compared using the following
        /// ordering:
        ///     Point (lowest),
        ///     MultiPoint,
        ///     LineString,
        ///     LinearRing,
        ///     MultiLineString,
        ///     Polygon,
        ///     MultiPolygon,
        ///     GeometryCollection (highest).
        /// If the two <c>Geometry</c>s have the same class, their first
        /// elements are compared. If those are the same, the second elements are
        /// compared, etc.
        /// </summary>
        /// <param name="o">A <c>Geometry</c> with which to compare this <c>Geometry</c></param>
        /// <returns>
        /// A positive number, 0, or a negative number, depending on whether
        /// this object is greater than, equal to, or less than <c>o</c>, as
        /// defined in "Normal Form For Geometry" in the NTS Technical
        /// Specifications.
        /// </returns>
        public int CompareTo(object o) 
        {
            return CompareTo((IGeometry) o);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="geom"></param>
        /// <returns></returns>
        public int CompareTo(IGeometry geom)
        {
            Geometry other = (Geometry) geom;
            if (ClassSortIndex != other.ClassSortIndex)
                return ClassSortIndex - other.ClassSortIndex;
            if (IsEmpty && other.IsEmpty)
                return 0;
            if (IsEmpty)
                return -1;
            if (other.IsEmpty)
                return 1;
            return CompareToSameClass(geom);
        }

        /// <summary>
        /// Returns whether the two <c>Geometry</c>s are equal, from the point
        /// of view of the <c>EqualsExact</c> method. Called by <c>EqualsExact</c>
        /// . In general, two <c>Geometry</c> classes are considered to be
        /// "equivalent" only if they are the same class. An exception is <c>LineString</c>
        /// , which is considered to be equivalent to its subclasses.
        /// </summary>
        /// <param name="other">The <c>Geometry</c> with which to compare this <c>Geometry</c> for equality.</param>
        /// <returns>
        /// <c>true</c> if the classes of the two <c>Geometry</c>
        /// s are considered to be equal by the <c>equalsExact</c> method.
        /// </returns>
        protected bool IsEquivalentClass(IGeometry other) 
        {
            return GetType().FullName == other.GetType().FullName;
        }

        /// <summary>
        /// Throws an exception if <c>g</c>'s class is <c>GeometryCollection</c>. 
        /// (its subclasses do not trigger an exception).
        /// </summary>
        /// <param name="g">The <c>Geometry</c> to check.</param>
        /// <exception cref="ArgumentException">
        /// if <c>g</c> is a <c>GeometryCollection</c>, but not one of its subclasses.
        /// </exception>
        protected void CheckNotGeometryCollection(IGeometry g) 
        {
            if (isGeometryCollection(g)) 
                throw new ArgumentException("This method does not support GeometryCollection arguments");                            
        }

        /// <summary>
        /// Returns <c>true</c> if <c>g</c>'s class is <c>GeometryCollection</c>. 
        /// (its subclasses do not trigger an exception).
        /// </summary>
        /// <param name="g">The <c>Geometry</c> to check.</param>
        /// <exception cref="ArgumentException">
        /// If <c>g</c> is a <c>GeometryCollection</c>, but not one of its subclasses.
        /// </exception>        
        private bool isGeometryCollection(IGeometry g)
        {
            return g.GetType().Name == "GeometryCollection" && g.GetType().Namespace == GetType().Namespace;
        }

        /// <summary>
        /// Returns the minimum and maximum x and y values in this <c>Geometry</c>
        /// , or a null <c>Envelope</c> if this <c>Geometry</c> is empty.
        /// Unlike <c>EnvelopeInternal</c>, this method calculates the <c>Envelope</c>
        /// each time it is called; <c>EnvelopeInternal</c> caches the result
        /// of this method.        
        /// </summary>
        /// <returns>
        /// This <c>Geometry</c>s bounding box; if the <c>Geometry</c>
        /// is empty, <c>Envelope.IsNull</c> will return <c>true</c>.
        /// </returns>
        protected abstract IEnvelope ComputeEnvelopeInternal();

        /// <summary>
        /// Returns whether this <c>Geometry</c> is greater than, equal to,
        /// or less than another <c>Geometry</c> having the same class.
        /// </summary>
        /// <param name="o">A <c>Geometry</c> having the same class as this <c>Geometry</c>.</param>
        /// <returns>
        /// A positive number, 0, or a negative number, depending on whether
        /// this object is greater than, equal to, or less than <c>o</c>, as
        /// defined in "Normal Form For Geometry" in the NTS Technical
        /// Specifications.
        /// </returns>
        protected internal abstract int CompareToSameClass(object o);

        /// <summary>
        /// Returns the first non-zero result of <c>CompareTo</c> encountered as
        /// the two <c>Collection</c>s are iterated over. If, by the time one of
        /// the iterations is complete, no non-zero result has been encountered,
        /// returns 0 if the other iteration is also complete. If <c>b</c>
        /// completes before <c>a</c>, a positive number is returned; if a
        /// before b, a negative number.
        /// </summary>
        /// <param name="a">A <c>Collection</c> of <c>IComparable</c>s.</param>
        /// <param name="b">A <c>Collection</c> of <c>IComparable</c>s.</param>
        /// <returns>The first non-zero <c>compareTo</c> result, if any; otherwise, zero.</returns>
        protected int Compare(IEnumerable<IComparable> a, IEnumerable<IComparable> b) 
        {
            IEnumerator i = a.GetEnumerator();
            IEnumerator j = b.GetEnumerator();

            while (i.MoveNext() && j.MoveNext()) 
            {
                IComparable aElement = (IComparable) i.Current;
                IComparable bElement = (IComparable) j.Current;
                int comparison = aElement.CompareTo(bElement);            
                if (comparison != 0)                 
                    return comparison;                
            }

            if (i.MoveNext())             
                return 1;            

            if (j.MoveNext())             
                return -1;            

            return 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        protected bool Equal(ICoordinate a, ICoordinate b, double tolerance) 
        {
            if (tolerance == 0)             
                return a.Equals(b);             

            return a.Distance(b) <= tolerance;
        }

        /// <summary>
        /// 
        /// </summary>
        private int ClassSortIndex 
        {
            get
            {
                for (int i = 0; i < SortedClasses.Length; i++)                
                    if (GetType().Equals(SortedClasses[i]))                                        
                        return i;                                    
                Assert.ShouldNeverReachHere(String.Format("Class not supported: {0}", GetType().FullName));
                return -1;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="coord"></param>
        /// <param name="exemplar"></param>
        /// <returns></returns>
        private IPoint CreatePointFromInternalCoord(ICoordinate coord, IGeometry exemplar)
        {
            exemplar.PrecisionModel.MakePrecise(coord);
            return exemplar.Factory.CreatePoint(coord);
        }        

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual bool IsRectangle
        {
            get
            {
                // Polygon overrides to check for actual rectangle
                return false;
            }
        }

        /* BEGIN ADDED BY MPAUL42: monoGIS team */

        /// <summary>
        /// A predefined <see cref="GeometryFactory" /> with <see cref="PrecisionModel" /> <c> == </c> <see cref="PrecisionModels.Fixed" />.
        /// </summary>
        /// <seealso cref="GeometryFactory.Default" />
        /// <seealso cref="GeometryFactory.Fixed"/>
        public static readonly IGeometryFactory DefaultFactory = GeometryFactory.Default;
        
        /* END ADDED BY MPAUL42: monoGIS team */

    }
}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.