using System.Collections;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Geometries;
using GisSharpBlog.NetTopologySuite.Index.Strtree;
namespace GisSharpBlog.NetTopologySuite.Algorithm
{
///
/// Implements PointInRing using a SIRtree index to increase performance.
///
public class SIRtreePointInRing : IPointInRing
{
private readonly ILinearRing ring;
private SIRtree sirTree;
private int crossings = 0; // number of segment/ray crossings
///
///
///
///
public SIRtreePointInRing(ILinearRing ring)
{
this.ring = ring;
BuildIndex();
}
///
///
///
///
///
public bool IsInside(ICoordinate pt)
{
crossings = 0;
// test all segments intersected by vertical ray at pt
IList segs = sirTree.Query(pt.Y);
for (IEnumerator i = segs.GetEnumerator(); i.MoveNext();)
{
LineSegment seg = (LineSegment) i.Current;
TestLineSegment(pt, seg);
}
/*
* p is inside if number of crossings is odd.
*/
if ((crossings%2) == 1)
{
return true;
}
return false;
}
///
///
///
private void BuildIndex()
{
sirTree = new SIRtree();
ICoordinate[] pts = ring.Coordinates;
for (int i = 1; i < pts.Length; i++)
{
if (pts[i - 1].Equals(pts[i]))
{
continue;
}
LineSegment seg = new LineSegment(pts[i - 1], pts[i]);
sirTree.Insert(seg.P0.Y, seg.P1.Y, seg);
}
}
///
///
///
///
///
private void TestLineSegment(ICoordinate p, LineSegment seg)
{
double xInt; // x intersection of segment with ray
double x1; // translated coordinates
double y1;
double x2;
double y2;
/*
* Test if segment crosses ray from test point in positive x direction.
*/
ICoordinate p1 = seg.P0;
ICoordinate p2 = seg.P1;
x1 = p1.X - p.X;
y1 = p1.Y - p.Y;
x2 = p2.X - p.X;
y2 = p2.Y - p.Y;
if (((y1 > 0) && (y2 <= 0)) || ((y2 > 0) && (y1 <= 0)))
{
/*
* segment straddles x axis, so compute intersection.
*/
xInt = RobustDeterminant.SignOfDet2x2(x1, y1, x2, y2)/(y2 - y1);
/*
* crosses ray if strictly positive intersection.
*/
if (0.0 < xInt)
{
crossings++;
}
}
}
}
}