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);
}
}
}
}