} // public override void Insert( EdgeEnd e ) /// <summary> /// Update the IM with the contribution for the EdgeStubs around the node. /// </summary> /// <param name="im"></param> public void UpdateIM( IntersectionMatrix im ) { ArrayList edges = Edges(); foreach ( object obj in edges ) { EdgeEndBundle esb = (EdgeEndBundle) obj; esb.UpdateIM( im ); } } // void UpdateIM( IntersectionMatrix im )
/// <summary> /// Constructs an IntersectionMatrix with the same elements as other. /// </summary> /// <param name="other">The IntersectionMatrix to copy.</param> internal IntersectionMatrix(IntersectionMatrix other) : this() { _matrix[Location.Interior, Location.Interior] = other.Matrix[Location.Interior, Location.Interior]; _matrix[Location.Interior, Location.Boundary] = other.Matrix[Location.Interior, Location.Boundary]; _matrix[Location.Interior, Location.Exterior] = other.Matrix[Location.Interior, Location.Exterior]; _matrix[Location.Boundary, Location.Interior] = other.Matrix[Location.Boundary, Location.Interior]; _matrix[Location.Boundary, Location.Boundary] = other.Matrix[Location.Boundary, Location.Boundary]; _matrix[Location.Boundary, Location.Exterior] = other.Matrix[Location.Boundary, Location.Exterior]; _matrix[Location.Exterior, Location.Interior] = other.Matrix[Location.Exterior, Location.Interior]; _matrix[Location.Exterior, Location.Boundary] = other.Matrix[Location.Exterior, Location.Boundary]; _matrix[Location.Exterior, Location.Exterior] = other.Matrix[Location.Exterior, Location.Exterior]; }
/// <summary> /// Constructs an IntersectionMatrix with the same elements as other. /// </summary> /// <param name="other">The IntersectionMatrix to copy.</param> internal IntersectionMatrix( IntersectionMatrix other ) : this() { _matrix[Location.Interior, Location.Interior] = other.Matrix[Location.Interior, Location.Interior]; _matrix[Location.Interior, Location.Boundary] = other.Matrix[Location.Interior, Location.Boundary]; _matrix[Location.Interior, Location.Exterior] = other.Matrix[Location.Interior, Location.Exterior]; _matrix[Location.Boundary, Location.Interior] = other.Matrix[Location.Boundary, Location.Interior]; _matrix[Location.Boundary ,Location.Boundary] = other.Matrix[Location.Boundary, Location.Boundary]; _matrix[Location.Boundary, Location.Exterior] = other.Matrix[Location.Boundary, Location.Exterior]; _matrix[Location.Exterior, Location.Interior] = other.Matrix[Location.Exterior, Location.Interior]; _matrix[Location.Exterior, Location.Boundary] = other.Matrix[Location.Exterior, Location.Boundary]; _matrix[Location.Exterior, Location.Exterior] = other.Matrix[Location.Exterior, Location.Exterior]; }
/// <summary> /// Compute the contribution to an IM for this component. /// </summary> /// <param name="im"></param> protected abstract void ComputeIM(IntersectionMatrix im);
/// <summary> /// Update the IM with the contribution for this component. A component only contributes /// if it has a labeling for both parent geometries. /// </summary> /// <param name="im"></param> public void UpdateIM(IntersectionMatrix im) { if ( _label.GetGeometryCount() < 2 ) { throw new InvalidOperationException("Found partial label."); } ComputeIM(im); }
} // public static bool Matches( int actualDimensionValue, char requiredDimensionSymbol ) /// <summary> /// Returns true if each of the actual dimension symbols satisfies the /// corresponding required dimension symbol. /// </summary> /// <param name="actualDimensionSymbols">Nine dimension symbols to validate. Possible values are /// {T, F, * , 0, 1, 2}</param> /// <param name="requiredDimensionSymbols">Nine dimension symbols to validate against. Possible values are /// {T, F, * , 0, 1, 2}</param> /// <returns>Returns true if each of the required dimension /// symbols encompass the corresponding actual dimension symbol.</returns> public static bool Matches(string actualDimensionSymbols, string requiredDimensionSymbols) { IntersectionMatrix m = new IntersectionMatrix(actualDimensionSymbols); return(m.Matches(requiredDimensionSymbols)); }
} // private void LabelNodeEdges() /// <summary> /// Update the IM with the sum of the IMs for each component. /// </summary> /// <param name="im"></param> private void UpdateIM( IntersectionMatrix im ) { //Trace.WriteLine( im.ToString() ); foreach ( object obj in _isolatedEdges ) { Edge e = (Edge) obj; e.UpdateIM( im ); //Trace.WriteLine( im.ToString() ); } // foreach ( object obj in _isolatedEdges ) foreach ( DictionaryEntry entry in _nodes ) { RelateNode node = (RelateNode) entry.Value; node.UpdateIM( im ); //Trace.WriteLine( im.ToString() ); node.UpdateIMFromEdges( im ); //Trace.WriteLine( im.ToString() ); //Trace.WriteLine( node.ToString() ); } // foreach ( object obj in _nodes ) } // private void UpdateIM( IntersectionMatrix im )
} // private void LabelIntersectionNodes( int argIndex ) /// <summary> /// If the Geometries are disjoint, we need to enter their dimension and /// boundary dimension in the Ext rows in the IM. /// </summary> /// <param name="im"></param> private void ComputeDisjointIM( IntersectionMatrix im ) { Geometry ga = _arg[0].Geometry; if ( !ga.IsEmpty() ) { im.Set( Location.Interior, Location.Exterior, ga.GetDimension() ); im.Set( Location.Boundary, Location.Exterior, ga.GetBoundaryDimension() ); } Geometry gb = _arg[1].Geometry; if ( !gb.IsEmpty() ) { im.Set( Location.Exterior, Location.Interior, gb.GetDimension() ); im.Set( Location.Exterior, Location.Boundary, gb.GetBoundaryDimension() ); } } // private void ComputeDisjointIM( IntersectionMatrix im )
} // 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()
} // protected override void ComputeIM( IntersectionMatrix im ) /// <summary> /// Update the IM with the contribution for the EdgeEnds incident on this node. /// </summary> /// <param name="im"></param> public void UpdateIMFromEdges( IntersectionMatrix im ) { ((EdgeEndBundleStar) _edges).UpdateIM( im ); } // void UpdateIMFromEdges( IntersectionMatrix im )
/// <summary> /// Update the IM with the contribution for this component. /// A component only contributes if it has a labelling for both parent geometries /// </summary> /// <param name="im"></param> protected override void ComputeIM( IntersectionMatrix im ) { im.SetAtLeastIfValid( _label.GetLocation( 0 ), _label.GetLocation( 1 ), 0 ); } // protected override void ComputeIM( IntersectionMatrix im )
} // private void ComputeLabelSide( int geomIndex, int side ) /// <summary> /// Update the IM with the contribution for the computed label for the EdgeStubs. /// </summary> /// <param name="im"></param> public void UpdateIM(IntersectionMatrix im) { Edge.UpdateIM( _label, im ); } // void UpdateIM(IntersectionMatrix im)
/// <summary> /// Update the IM with the contribution for this component. A component only contributes if it has a labelling for both parent geometries. /// </summary> /// <param name="im"></param> protected override void ComputeIM(IntersectionMatrix im) { UpdateIM( _label, im ); }
/// <summary> /// Updates an IM from the label for an edge. Handles edges from both L and A geometrys. /// </summary> /// <param name="label"></param> /// <param name="im"></param> public static void UpdateIM(Label label, IntersectionMatrix im) { im.SetAtLeastIfValid( label.GetLocation( 0, Position.On ), label.GetLocation( 1, Position.On ), 1); if ( label.IsArea() ) { im.SetAtLeastIfValid( label.GetLocation( 0, Position.Left ), label.GetLocation( 1, Position.Left ), 2); im.SetAtLeastIfValid( label.GetLocation( 0, Position.Right ), label.GetLocation( 1, Position.Right ), 2); } }
} // public static bool Matches( int actualDimensionValue, char requiredDimensionSymbol ) /// <summary> /// Returns true if each of the actual dimension symbols satisfies the /// corresponding required dimension symbol. /// </summary> /// <param name="actualDimensionSymbols">Nine dimension symbols to validate. Possible values are /// {T, F, * , 0, 1, 2}</param> /// <param name="requiredDimensionSymbols">Nine dimension symbols to validate against. Possible values are /// {T, F, * , 0, 1, 2}</param> /// <returns>Returns true if each of the required dimension /// symbols encompass the corresponding actual dimension symbol.</returns> public static bool Matches(string actualDimensionSymbols, string requiredDimensionSymbols) { IntersectionMatrix m = new IntersectionMatrix( actualDimensionSymbols ); return m.Matches( requiredDimensionSymbols ); }
} // private void InsertEdgeEnds( ArrayList ee ) /// <summary> /// /// </summary> /// <param name="intersector"></param> /// <param name="im"></param> private void ComputeProperIntersectionIM( SegmentIntersector intersector, IntersectionMatrix im ) { // If a proper intersection is found, we can set a lower bound on the IM. int dimA = _arg[0].Geometry.GetDimension(); int dimB = _arg[1].Geometry.GetDimension(); bool hasProper = intersector.HasProperIntersection; bool hasProperInterior = intersector.HasProperInteriorIntersection; // For Geometrys of dim 0 there can never be proper intersections. // If edge segments of Areas properly intersect, the areas must properly overlap. if ( dimA == 2 && dimB == 2 ) { if ( hasProper ) { im.SetAtLeast( "212101212" ); } } // if ( dimA == 2 && dimB == 2 ) // If an Line segment properly intersects an edge segment of an Area, // it follows that the Interior of the Line intersects the Boundary of the Area. // If the intersection is a proper <i>interior</i> intersection, then // there is an Interior-Interior intersection too. // Note that it does not follow that the Interior of the Line intersects the Exterior // of the Area, since there may be another Area component which contains the rest of the Line. else if ( dimA == 2 && dimB == 1 ) { if ( hasProper ) { im.SetAtLeast( "FFF0FFFF2" ); } if ( hasProperInterior ) { im.SetAtLeast( "1FFFFF1FF" ); } } // else if ( dimA == 2 && dimB == 1 ) else if ( dimA == 1 && dimB == 2 ) { if ( hasProper ) { im.SetAtLeast("F0FFFFFF2"); } if ( hasProperInterior ) { im.SetAtLeast("1F1FFFFFF"); } } // else if ( dimA == 1 && dimB == 2 ) // If edges of LineStrings properly intersect *in an interior point*, all // we can deduce is that // the interiors intersect. (We can NOT deduce that the exteriors intersect, // since some other segments in the geometries might cover the points in the // neighbourhood of the intersection.) // It is important that the point be known to be an interior point of // both Geometries, since it is possible in a self-intersecting geometry to // have a proper intersection on one segment that is also a boundary point of another segment. else if ( dimA == 1 && dimB == 1 ) { if ( hasProperInterior ) { im.SetAtLeast( "0FFFFFFFF" ); } } // else if ( dimA == 1 && dimB == 1 ) } // private void ComputeProperIntersectionIM( SegmentIntersector intersector, IntersectionMatrix im )
/// <summary> /// Basic nodes do not compute IMs. /// </summary> /// <param name="im"></param> protected override void ComputeIM( IntersectionMatrix im ) { }