using System.Collections; using GisSharpBlog.NetTopologySuite.Index; using GisSharpBlog.NetTopologySuite.Index.Chain; using GisSharpBlog.NetTopologySuite.Index.Quadtree; using GisSharpBlog.NetTopologySuite.Index.Strtree; namespace GisSharpBlog.NetTopologySuite.Noding { /// /// Nodes a set of s using a index based /// on s and a . /// The used should be something that supports /// envelope (range) queries efficiently (such as a /// or . /// public class MCIndexNoder : SinglePassNoder { private readonly IList monoChains = new ArrayList(); private readonly ISpatialIndex index = new STRtree(); private int idCounter; private IList nodedSegStrings; private int nOverlaps; // statistics /// /// Initializes a new instance of the class. /// public MCIndexNoder() { } /// /// Initializes a new instance of the class. /// /// The to use. public MCIndexNoder(ISegmentIntersector segInt) : base(segInt) { } /// /// /// public IList MonotoneChains { get { return monoChains; } } /// /// /// public ISpatialIndex Index { get { return index; } } /// /// Returns a of fully noded s. /// The s have the same context as their parent. /// /// public override IList GetNodedSubstrings() { return SegmentString.GetNodedSubstrings(nodedSegStrings); } /// /// Computes the noding for a collection of s. /// Some Noders may add all these nodes to the input s; /// others may only add some or none at all. /// /// public override void ComputeNodes(IList inputSegStrings) { nodedSegStrings = inputSegStrings; foreach(var obj in inputSegStrings) Add((SegmentString)obj); IntersectChains(); } /// /// /// private void IntersectChains() { MonotoneChainOverlapAction overlapAction = new SegmentOverlapAction(SegmentIntersector); foreach(var obj in monoChains) { var queryChain = (MonotoneChain)obj; var overlapChains = index.Query(queryChain.Envelope); foreach(var j in overlapChains) { var testChain = (MonotoneChain)j; /* * following test makes sure we only compare each pair of chains once * and that we don't compare a chain to itself */ if (testChain.Id <= queryChain.Id) continue; queryChain.ComputeOverlaps(testChain, overlapAction); nOverlaps++; } } } /// /// /// /// private void Add(SegmentString segStr) { var segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr); foreach (var obj in segChains) { var mc = (MonotoneChain)obj; mc.Id = idCounter++; index.Insert(mc.Envelope, mc); monoChains.Add(mc); } } /// /// /// public class SegmentOverlapAction : MonotoneChainOverlapAction { private readonly ISegmentIntersector si; /// /// Initializes a new instance of the class. /// /// The public SegmentOverlapAction(ISegmentIntersector si) { this.si = si; } /// /// /// /// /// /// /// public override void Overlap(MonotoneChain mc1, int start1, MonotoneChain mc2, int start2) { var ss1 = (SegmentString) mc1.Context; var ss2 = (SegmentString) mc2.Context; si.ProcessIntersections(ss1, start1, ss2, start2); } } } }