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 ILinearRing ring; private SIRtree sirTree; private int crossings = 0; // number of segment/ray crossings /// /// /// /// public SIRtreePointInRing(ILinearRing ring) { this.ring = ring; BuildIndex(); } /// /// /// 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); } } /// /// /// /// /// 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 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++; } } } }