}         // public Coordinate GetInvalidPoint()

        #endregion

        #region Public Methods
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public bool IsNodeConsistentArea()
        {
            SegmentIntersector intersector = _arg[0].ComputeSelfNodes(_li);

            if (intersector.HasProperIntersection)
            {
                _invalidPoint = intersector.ProperIntersectionPoint;
                return(false);
            }

            // compute intersections between edges
            ComputeIntersectionNodes(0);

            //Copy the labelling for the nodes in the parent Geometry.  These override
            //any labels determined by intersections.
            CopyNodesAndLabels(0);

            // Build EdgeEnds for all intersections.
            EdgeEndBuilder eeBuilder = new EdgeEndBuilder();
            ArrayList      ee0       = eeBuilder.ComputeEdgeEnds(_arg[0].Edges);

            InsertEdgeEnds(ee0);

            //Trace.WriteLine("==== NodeList ===");
            //Trace.WriteLine( _nodes.ToString() );

            return(IsNodeEdgeAreaLabelsConsistent());
        }         // public bool IsNodeConsistentArea()
		/// <summary>
		/// 
		/// </summary>
		/// <param name="geomGraph"></param>
		public void Build(GeometryGraph geomGraph)
		{
			// compute nodes for intersections between previously noded edges
			ComputeIntersectionNodes( geomGraph, 0 );
			// Copy the labelling for the nodes in the parent Geometry.  These override
			// any labels determined by intersections.
			CopyNodesAndLabels( geomGraph, 0 );

			// Build EdgeEnds for all intersections.
			EdgeEndBuilder eeBuilder = new EdgeEndBuilder();
			ArrayList eeList = eeBuilder.ComputeEdgeEnds( geomGraph.Edges );
			InsertEdgeEnds( eeList );

			//Trace.WriteLine("==== NodeList ===");
			//Trace.WriteLine( _nodes.ToString() );
		} // public void Build(GeometryGraph geomGraph)
        /// <summary>
        ///
        /// </summary>
        /// <param name="geomGraph"></param>
        public void Build(GeometryGraph geomGraph)
        {
            // compute nodes for intersections between previously noded edges
            ComputeIntersectionNodes(geomGraph, 0);
            // Copy the labelling for the nodes in the parent Geometry.  These override
            // any labels determined by intersections.
            CopyNodesAndLabels(geomGraph, 0);

            // Build EdgeEnds for all intersections.
            EdgeEndBuilder eeBuilder = new EdgeEndBuilder();
            ArrayList      eeList    = eeBuilder.ComputeEdgeEnds(geomGraph.Edges);

            InsertEdgeEnds(eeList);

            //Trace.WriteLine("==== NodeList ===");
            //Trace.WriteLine( _nodes.ToString() );
        }         // public void Build(GeometryGraph geomGraph)
		} // public Coordinate GetInvalidPoint()

		#endregion

		#region Public Methods
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public bool IsNodeConsistentArea()
		{
			SegmentIntersector intersector = _arg[0].ComputeSelfNodes( _li );
			if ( intersector.HasProperIntersection ) 
			{
				_invalidPoint = intersector.ProperIntersectionPoint;
				return false;
			}

			// compute intersections between edges
			ComputeIntersectionNodes( 0 );
			
			 //Copy the labelling for the nodes in the parent Geometry.  These override
			 //any labels determined by intersections.
			CopyNodesAndLabels( 0 );

			// Build EdgeEnds for all intersections.
			EdgeEndBuilder eeBuilder = new EdgeEndBuilder();
			ArrayList ee0 = eeBuilder.ComputeEdgeEnds( _arg[0].Edges );
			InsertEdgeEnds( ee0 );

			//Trace.WriteLine("==== NodeList ===");
			//Trace.WriteLine( _nodes.ToString() );

			return IsNodeEdgeAreaLabelsConsistent();
		} // public bool IsNodeConsistentArea()
		} // public bool HasDuplicateRings()

		/// <summary>
		/// Computes the Intersection matrix for the geometries.
		/// </summary>
		/// <returns></returns>
		public IntersectionMatrix ComputeIM()
		{
			IntersectionMatrix im = new IntersectionMatrix();

			// since Geometries are finite and embedded in a 2-D space, the EE element must always be 2
			im.Set( Location.Exterior, Location.Exterior, 2);

			// if the Geometries don't overlap there is nothing to do
			if ( !_arg[0].Geometry.GetEnvelopeInternal().Intersects( 
				  _arg[1].Geometry.GetEnvelopeInternal() ) ) 
			{
				ComputeDisjointIM( im );
				return im;
			}

			_arg[0].ComputeSelfNodes( _li );
			_arg[1].ComputeSelfNodes( _li );

			// compute intersections between edges of the two input geometries
			SegmentIntersector intersector = _arg[0].ComputeEdgeIntersections( _arg[1], _li, false );
			ComputeIntersectionNodes(0);
			ComputeIntersectionNodes(1);

			 // Copy the labelling for the nodes in the parent Geometries.  These override
			 // any labels determined by intersections between the geometries.
			CopyNodesAndLabels(0);
			CopyNodesAndLabels(1);

			// complete the labelling for any nodes which only have a label for a single geometry
			LabelIsolatedNodes();

			// If a proper intersection was found, we can set a lower bound on the IM.
			ComputeProperIntersectionIM( intersector, im );

			 // Now process improper intersections
			 // (eg where one or other of the geometrys has a vertex at the intersection point)
			 // We need to compute the edge graph at all nodes to determine the IM.

			// build EdgeEnds for all intersections
			EdgeEndBuilder eeBuilder = new EdgeEndBuilder();
			ArrayList ee0 = eeBuilder.ComputeEdgeEnds( _arg[0].Edges );
			InsertEdgeEnds( ee0 );
			ArrayList ee1 = eeBuilder.ComputeEdgeEnds( _arg[1].Edges );
			InsertEdgeEnds( ee1 );

			//Trace.WriteLine("==== NodeList ===");
			//Trace.WriteLine( _nodes.ToString() );

			LabelNodeEdges();

			 // Compute the labeling for isolated components
			 // <br>
			 // Isolated components are components that do not touch any other components in the graph.
			 // They can be identified by the fact that they will
			 // contain labels containing ONLY a single element, the one for their parent geometry.
			 // We only need to check components contained in the input graphs, since
			 // isolated components will not have been replaced by new components formed by intersections.
			//Trace.WriteLine("Graph A isolated edges - ");
			LabelIsolatedEdges(0, 1);
			//Trace.WriteLine("Graph B isolated edges - ");
			LabelIsolatedEdges(1, 0);

			// update the IM from all components
			UpdateIM( im );
			return im;
		} // public IntersectionMatrix ComputeIM()
        }         // public bool HasDuplicateRings()

        /// <summary>
        /// Computes the Intersection matrix for the geometries.
        /// </summary>
        /// <returns></returns>
        public IntersectionMatrix ComputeIM()
        {
            IntersectionMatrix im = new IntersectionMatrix();

            // since Geometries are finite and embedded in a 2-D space, the EE element must always be 2
            im.Set(Location.Exterior, Location.Exterior, 2);

            // if the Geometries don't overlap there is nothing to do
            if (!_arg[0].Geometry.GetEnvelopeInternal().Intersects(
                    _arg[1].Geometry.GetEnvelopeInternal()))
            {
                ComputeDisjointIM(im);
                return(im);
            }

            _arg[0].ComputeSelfNodes(_li);
            _arg[1].ComputeSelfNodes(_li);

            // compute intersections between edges of the two input geometries
            SegmentIntersector intersector = _arg[0].ComputeEdgeIntersections(_arg[1], _li, false);

            ComputeIntersectionNodes(0);
            ComputeIntersectionNodes(1);

            // Copy the labelling for the nodes in the parent Geometries.  These override
            // any labels determined by intersections between the geometries.
            CopyNodesAndLabels(0);
            CopyNodesAndLabels(1);

            // complete the labelling for any nodes which only have a label for a single geometry
            LabelIsolatedNodes();

            // If a proper intersection was found, we can set a lower bound on the IM.
            ComputeProperIntersectionIM(intersector, im);

            // Now process improper intersections
            // (eg where one or other of the geometrys has a vertex at the intersection point)
            // We need to compute the edge graph at all nodes to determine the IM.

            // build EdgeEnds for all intersections
            EdgeEndBuilder eeBuilder = new EdgeEndBuilder();
            ArrayList      ee0       = eeBuilder.ComputeEdgeEnds(_arg[0].Edges);

            InsertEdgeEnds(ee0);
            ArrayList ee1 = eeBuilder.ComputeEdgeEnds(_arg[1].Edges);

            InsertEdgeEnds(ee1);

            //Trace.WriteLine("==== NodeList ===");
            //Trace.WriteLine( _nodes.ToString() );

            LabelNodeEdges();

            // Compute the labeling for isolated components
            // <br>
            // Isolated components are components that do not touch any other components in the graph.
            // They can be identified by the fact that they will
            // contain labels containing ONLY a single element, the one for their parent geometry.
            // We only need to check components contained in the input graphs, since
            // isolated components will not have been replaced by new components formed by intersections.
            //Trace.WriteLine("Graph A isolated edges - ");
            LabelIsolatedEdges(0, 1);
            //Trace.WriteLine("Graph B isolated edges - ");
            LabelIsolatedEdges(1, 0);

            // update the IM from all components
            UpdateIM(im);
            return(im);
        }         // public IntersectionMatrix ComputeIM()