private void DoTest(ISpatialIndex <object> index, double queryEnvelopeExtent, IList <Envelope> sourceData) { Console.WriteLine("---------------"); Console.WriteLine("Envelope Extent: " + queryEnvelopeExtent); int extraMatchCount = 0; int expectedMatchCount = 0; int actualMatchCount = 0; int queryCount = 0; for (double x = 0; x < CELL_EXTENT * CELLS_PER_GRID_SIDE; x += queryEnvelopeExtent) { for (double y = 0; y < CELL_EXTENT * CELLS_PER_GRID_SIDE; y += queryEnvelopeExtent) { var queryEnvelope = new Envelope(x, x + queryEnvelopeExtent, y, y + queryEnvelopeExtent); var expectedMatches = IntersectingEnvelopes(queryEnvelope, sourceData); var actualMatches = index.Query(queryEnvelope); Assert.IsTrue(expectedMatches.Count <= actualMatches.Count); extraMatchCount += (actualMatches.Count - expectedMatches.Count); expectedMatchCount += expectedMatches.Count; actualMatchCount += actualMatches.Count; Compare(expectedMatches, actualMatches); queryCount++; } } Console.WriteLine("Expected Matches: " + expectedMatchCount); Console.WriteLine("Actual Matches: " + actualMatchCount); Console.WriteLine("Extra Matches: " + extraMatchCount); Console.WriteLine("Query Count: " + queryCount); Console.WriteLine("Average Expected Matches: " + (expectedMatchCount / (double)queryCount)); Console.WriteLine("Average Actual Matches: " + (actualMatchCount / (double)queryCount)); Console.WriteLine("Average Extra Matches: " + (extraMatchCount / (double)queryCount)); }
public static double CalculateLengthOfLineWithinPolygon(Geometry lineGeometry, ISpatialIndex <Geometry> geometriesToCheck) { // restrict the search space to nodes in the bounding box of the buffered line--subquadratic speedup over a naive search var candidateGeometriesToCheck = geometriesToCheck.Query(lineGeometry.EnvelopeInternal); return(CalculateLengthOfLineWithinPolygon(lineGeometry, candidateGeometriesToCheck)); }
/// <summary> /// Query shapefile by MBR. /// MBR coordinates MUST be in the Shapefile's coordinate system. /// /// NOTE: If you are using the default ISpatialIndex (which is an instance of the STRtree NTS class), it has some limitations. /// Since it works with MBRs rather than the shapes themselves, you can get some shapes that are not actually in the MBR /// you provided just because their MBRs are bounded by the given envelope. /// If you wish to avoid this behaviour, send true in the second paramter, but be weary of the consequences listed below. /// </summary> /// <param name="envelope"> The envlope to query. </param> /// <param name="testGeometriesActuallyInMBR"> /// False by default, true to double-check the returned geometries against given Envelope, to avoid index error margin. /// /// It is advisable that you implement your own ISpatialIndex with your required precision rather than set this to True. /// /// ********** /// CAUTION: If you choose to set this parameter as True, it will greatly affect performance as it /// will cancel any lazy mechanism implemented with reading the geometries from the file. /// Do not set this to True unless you either: /// A. Do not have any performance restrictions. /// Or: /// B. Absolutely need that precision in the geographic query. /// ********** /// </param> /// <returns></returns> public IEnumerable <IShapefileFeature> ReadByMBRFilter(Envelope envelope, bool testGeometriesActuallyInMBR = false) { if (envelope == null) { throw new ArgumentNullException("envelope"); } // If index creation task wasnt completed, wait for it to complete. if (!m_IsIndexingComplete) { m_IndexCreationTask.Wait(); } var shapesInRegion = m_SpatialIndex.Query(envelope); if (shapesInRegion.Count == 0) { return(Enumerable.Empty <IShapefileFeature>()); } var results = shapesInRegion.Select(ReadFeature); if (!testGeometriesActuallyInMBR) { return(results); } else { var envelopeGeo = new GeometryFactory().ToGeometry(envelope); return(results.Where(feature => envelopeGeo.Intersects(feature.Geometry))); } }
private void DoTest(ISpatialIndex<object> index, double queryEnvelopeExtent, IList<Envelope> sourceData) { Console.WriteLine("---------------"); Console.WriteLine("Envelope Extent: " + queryEnvelopeExtent); int extraMatchCount = 0; int expectedMatchCount = 0; int actualMatchCount = 0; int queryCount = 0; for (double x = 0; x < CELL_EXTENT * CELLS_PER_GRID_SIDE; x += queryEnvelopeExtent) { for (double y = 0; y < CELL_EXTENT * CELLS_PER_GRID_SIDE; y += queryEnvelopeExtent) { Envelope queryEnvelope = new Envelope(x, x + queryEnvelopeExtent, y, y + queryEnvelopeExtent); var expectedMatches = IntersectingEnvelopes(queryEnvelope, sourceData); var actualMatches = index.Query(queryEnvelope); Assert.IsTrue(expectedMatches.Count <= actualMatches.Count); extraMatchCount += (actualMatches.Count - expectedMatches.Count); expectedMatchCount += expectedMatches.Count; actualMatchCount += actualMatches.Count; Compare(expectedMatches, actualMatches); queryCount++; } } Console.WriteLine("Expected Matches: " + expectedMatchCount); Console.WriteLine("Actual Matches: " + actualMatchCount); Console.WriteLine("Extra Matches: " + extraMatchCount); Console.WriteLine("Query Count: " + queryCount); Console.WriteLine("Average Expected Matches: " + (expectedMatchCount/(double)queryCount)); Console.WriteLine("Average Actual Matches: " + (actualMatchCount/(double)queryCount)); Console.WriteLine("Average Extra Matches: " + (extraMatchCount/(double)queryCount)); }
public bool IsNonNested() { BuildIndex(); for (int i = 0; i < _rings.Count; i++) { var innerRing = (ILinearRing)_rings[i]; Coordinate[] innerRingPts = innerRing.Coordinates; var results = _index.Query(innerRing.EnvelopeInternal); for (int j = 0; j < results.Count; j++) { var searchRing = (ILinearRing)results[j]; var searchRingPts = searchRing.Coordinates; if (innerRing == searchRing) { continue; } if (!innerRing.EnvelopeInternal.Intersects(searchRing.EnvelopeInternal)) { continue; } Coordinate innerRingPt = IsValidOp.FindPointNotNode(innerRingPts, searchRing, _graph); // Diego Guidi: removed => see Issue 121 //Assert.IsTrue(innerRingPt != null, "Unable to find a ring point not a node of the search ring"); /** * If no non-node pts can be found, this means * that the searchRing touches ALL of the innerRing vertices. * This indicates an invalid polygon, since either * the two holes create a disconnected interior, * or they touch in an infinite number of points * (i.e. along a line segment). * Both of these cases are caught by other tests, * so it is safe to simply skip this situation here. */ if (innerRingPt == null) { continue; } Boolean isInside = PointLocation.IsInRing(innerRingPt, searchRingPts); if (isInside) { _nestedPt = innerRingPt; return(false); } } } return(true); }
/// <summary> /// /// </summary> /// <param name="querySeg"></param> /// <returns></returns> public IList <LineSegment> Query(LineSegment querySeg) { var env = new Envelope(querySeg.P0, querySeg.P1); var visitor = new LineSegmentVisitor(querySeg); _index.Query(env, visitor); var itemsFound = visitor.Items; return(itemsFound); }
// <FIX> fast lookup for edges /// <summary> /// If there is an edge equal to e already in the list, return it. /// Otherwise return null. /// </summary> /// <param name="e"></param> /// <returns> /// equal edge, if there is one already in the list, /// null otherwise. /// </returns> public Edge FindEqualEdge(Edge e) { ICollection testEdges = index.Query(e.Envelope); for (IEnumerator i = testEdges.GetEnumerator(); i.MoveNext();) { Edge testEdge = (Edge)i.Current; if (testEdge.Equals(e)) { return(testEdge); } } return(null); }
public IEnumerable <TItem> ElementsIn(Rectangle bounds) { if (_index == null) { _index = new SpatialQuadTreeIndex <TItem> { BoundsOf = item => new Rectangle(this.GetLocation(item), this.GetSize(item)), HasBounds = item => this.HasLocation(item) && this.HasSize(item) }; _index.AddRange(this.changedLocations.Keys); } var result = _index.Query(bounds); return(result); }
// <FIX> fast lookup for edges /// <summary> If there is an edge equal to e already in the list, return it. /// Otherwise return null. /// </summary> /// <returns> equal edge, if there is one already in the list /// null otherwise /// </returns> public Edge FindEqualEdge(Edge e) { IList testEdges = index.Query(e.Envelope); int nCount = testEdges.Count; for (int i = 0; i < nCount; i++) { Edge testEdge = (Edge)testEdges[i]; if (testEdge.Equals(e)) { return(testEdge); } } return(null); }
private void DoTest(ISpatialIndex <object> index, double queryEnvelopeExtent, List <Envelope> sourceData) { if (Verbose) { //System.Console.WriteLine("---------------"); //System.Console.WriteLine("Envelope Extent: " + queryEnvelopeExtent); } int extraMatchCount = 0; int expectedMatchCount = 0; int actualMatchCount = 0; int queryCount = 0; for (double x = 0d; x < CellExtent * CellsPerGridSide; x += queryEnvelopeExtent) { for (double y = 0d; y < CellExtent * CellsPerGridSide; y += queryEnvelopeExtent) { var queryEnvelope = new Envelope(x, x + queryEnvelopeExtent, y, y + queryEnvelopeExtent); var expectedMatches = IntersectingEnvelopes(queryEnvelope, sourceData); var actualMatches = index.Query(queryEnvelope); // since index returns candidates only, it may return more than the expected value if (expectedMatches.Count > actualMatches.Count) { IsSuccess = false; } extraMatchCount += (actualMatches.Count - expectedMatches.Count); expectedMatchCount += expectedMatches.Count; actualMatchCount += actualMatches.Count; Compare(expectedMatches, actualMatches); queryCount++; } } if (Verbose) { //System.Console.WriteLine("Expected Matches: " + expectedMatchCount); //System.Console.WriteLine("Actual Matches: " + actualMatchCount); //System.Console.WriteLine("Extra Matches: " + extraMatchCount); //System.Console.WriteLine("Query Count: " + queryCount); //System.Console.WriteLine("Average Expected Matches: " + (expectedMatchCount/(double) queryCount)); //System.Console.WriteLine("Average Actual Matches: " + (actualMatchCount/(double) queryCount)); //System.Console.WriteLine("Average Extra Matches: " + (extraMatchCount/(double) queryCount)); } }
/// <summary> /// /// </summary> /// <returns></returns> public bool IsNonNested() { BuildQuadtree(); for (int i = 0; i < _rings.Count; i++) { var innerRing = _rings[i]; var innerRingPts = innerRing.Coordinates; var results = _quadtree.Query(innerRing.EnvelopeInternal); for (int j = 0; j < results.Count; j++) { var searchRing = results[j]; var searchRingPts = searchRing.Coordinates; if (innerRing == searchRing) { continue; } if (!innerRing.EnvelopeInternal.Intersects(searchRing.EnvelopeInternal)) { continue; } var innerRingPt = IsValidOp.FindPointNotNode(innerRingPts, searchRing, _graph); Assert.IsTrue(innerRingPt != null, "Unable to find a ring point not a node of the search ring"); bool isInside = PointLocation.IsInRing(innerRingPt, searchRingPts); if (isInside) { _nestedPt = innerRingPt; return(false); } } } return(true); }
/// <inheritdocs/> public Dictionary <int, Shape> GetShapes(ref int startIndex, int count, IEnvelope envelope) { Dictionary <int, Shape> result = new Dictionary <int, Shape>(); ShapefileIndexFile shx = CacheShapeIndexFile(); // Check to ensure the fileName is not null if (Filename == null) { throw new NullReferenceException(Filename); } if (File.Exists(Filename) == false) { throw new FileNotFoundException(Filename); } // Get the basic header information. ShapefileHeader header = new ShapefileHeader(Filename); Extent ext = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax }); if (envelope != null) { if (!ext.Intersects(envelope)) { return(result); } } // Check to ensure that the fileName is the correct shape type if (header.ShapeType != ShapeType && header.ShapeType != ShapeTypeM && header.ShapeType != ShapeTypeZ) { throw new ArgumentException("Wrong feature type."); } FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read); if (fs.Length == 100) { // The shapefile is empty so we can simply return here fs.Close(); return(result); } int shapesTested = 0; int shapesReturned = 0; // Use spatial index if we have one if (null != _spatialIndex && null != envelope) { IList spatialQueryResults = _spatialIndex.Query(envelope); // Sort the results from low to high index var sqra = new int[spatialQueryResults.Count]; spatialQueryResults.CopyTo(sqra, 0); Array.Sort(sqra); foreach (int shp in sqra) { if (shp >= startIndex) { Shape myShape = GetShapeAtIndex(fs, shx, header, shp, envelope); shapesTested++; if (null != myShape) { shapesReturned++; result.Add(shp, myShape); if (shapesReturned >= count) { break; } } } } } else { int numShapes = shx.Shapes.Count; for (int shp = startIndex; shp < numShapes; shp++) { Shape myShape = GetShapeAtIndex(fs, shx, header, shp, envelope); shapesTested++; if (null != myShape) { shapesReturned++; result.Add(shp, myShape); if (shapesReturned >= count) { break; } } } } startIndex += shapesTested; fs.Close(); return(result); }
private IList <EdgeRing> QueryOverlappingShells(Envelope ringEnv) { return(_shellIndex.Query(ringEnv)); }
private void DoTest(ISpatialIndex<object> index, double queryEnvelopeExtent, List<Envelope> sourceData) { if (Verbose) { Console.WriteLine("---------------"); Console.WriteLine("Envelope Extent: " + queryEnvelopeExtent); } int extraMatchCount = 0; int expectedMatchCount = 0; int actualMatchCount = 0; int queryCount = 0; for (var x = 0d; x < CellExtent*CellsPerGridSide; x += queryEnvelopeExtent) { for (var y = 0d; y < CellExtent*CellsPerGridSide; y += queryEnvelopeExtent) { var queryEnvelope = new Envelope(x, x + queryEnvelopeExtent, y, y + queryEnvelopeExtent); var expectedMatches = IntersectingEnvelopes(queryEnvelope, sourceData); var actualMatches = index.Query(queryEnvelope); // since index returns candidates only, it may return more than the expected value if (expectedMatches.Count > actualMatches.Count) { IsSuccess = false; } extraMatchCount += (actualMatches.Count - expectedMatches.Count); expectedMatchCount += expectedMatches.Count; actualMatchCount += actualMatches.Count; Compare(expectedMatches, actualMatches); queryCount++; } } if (Verbose) { Console.WriteLine("Expected Matches: " + expectedMatchCount); Console.WriteLine("Actual Matches: " + actualMatchCount); Console.WriteLine("Extra Matches: " + extraMatchCount); Console.WriteLine("Query Count: " + queryCount); Console.WriteLine("Average Expected Matches: " + (expectedMatchCount/(double) queryCount)); Console.WriteLine("Average Actual Matches: " + (actualMatchCount/(double) queryCount)); Console.WriteLine("Average Extra Matches: " + (extraMatchCount/(double) queryCount)); } }
public static int CountIntersectingGeometries(Geometry lineGeometry, ISpatialIndex <Geometry> geometriesToCheck) { var candidateGeometriesToCheck = geometriesToCheck.Query(lineGeometry.EnvelopeInternal); return(candidateGeometriesToCheck.Count(x => x.Intersects(lineGeometry))); }