/// <summary> /// Find element containing (x,y) coordinate. Returns null if no element found. /// <para> /// If (x,y) is exacly on the boundary between two elements, one of them will be returned. /// If (x,y) is matching exacly a node coordinate, one of the elements including the node will be returned. /// </para> /// </summary> public MeshElement FindElement(double x, double y) { // Find potential elements for (x,y) point Envelope targetEnvelope = new Envelope(x, x, y, y); #if NTS173 IList potentialSourceElmts = _elementSearchTree.Query(targetEnvelope); #else IList <MeshElement> potentialSourceElmts = _elementSearchTree.Query(targetEnvelope); #endif // Loop over all potential elements for (int i = 0; i < potentialSourceElmts.Count; i++) { #if NTS173 MeshElement element = (MeshElement)potentialSourceElmts[i]; #else MeshElement element = potentialSourceElmts[i]; #endif // Check if element includes the (x,y) point if (element.Includes(x, y)) { return(element); } } return(null); }
protected override Cell GetCell_internal(Vector2 cellPosition) { var cellPos = Utils.ConvertVector2(cellPosition); var result = NTSSTRTreeCellTree.Query(new Envelope(cellPos[0].MinVal, cellPos[0].MaxVal, cellPos[1].MinVal, cellPos[1].MaxVal)); return(result.First()); }
internal PointCollection KeepWithin(List <VertexPositionColor> coastTriangles) { var rtree = new STRtree <Polygon>(); for (int i = 0; i < coastTriangles.Count / 3; i++) { Coordinate[] coords = new Coordinate[] { new Coordinate(coastTriangles[i * 3].Position.X, coastTriangles[i * 3].Position.Y), new Coordinate(coastTriangles[i * 3 + 1].Position.X, coastTriangles[i * 3 + 1].Position.Y), new Coordinate(coastTriangles[i * 3 + 2].Position.X, coastTriangles[i * 3 + 2].Position.Y), new Coordinate(coastTriangles[i * 3].Position.X, coastTriangles[i * 3].Position.Y) }; var polygon = new Polygon(new LinearRing(coords)); rtree.Insert(polygon.EnvelopeInternal, polygon); } rtree.Build(); List <Vector2d> newpoints = new List <Vector2d>(); foreach (var x in points) { bool contains = false; foreach (var p in rtree.Query(new Envelope(x.X, x.X, x.Y, x.Y))) { if (p.Covers(new NetTopologySuite.Geometries.Point(x.X, x.Y))) { contains = true; break; } } if (contains) { newpoints.Add(x); } } points = newpoints; return(this); }
public List <SlimAccommodationData> GetNearest(Contracts.MultilingualAccommodation accommodation, STRtree <SlimAccommodationData> tree) { var accommodationEnvelope = new Envelope(accommodation.Location.Coordinates.Longitude - 0.01, accommodation.Location.Coordinates.Longitude + 0.01, accommodation.Location.Coordinates.Latitude - 0.01, accommodation.Location.Coordinates.Latitude + 0.01); return(tree.Query(accommodationEnvelope).ToList()); }
public int FindSurroundingSector(Vector2 position) { var envelope = new Envelope(new Coordinate(position.X, position.Y)); foreach (var sectorId in _sectorIdLookup.Query(envelope)) { if (IsInsideSector(sectorId, ref position)) { return(sectorId); } } return(-1); }
private void DisplayShapeByRTree(Coordinate p1, Coordinate p2) { if (areaSTRtree.IsEmpty) { return; } var areaQuery = new Envelope(p1, p2); var areaItems = areaSTRtree.Query(areaQuery); foreach (IGeometry item in areaItems) { DrawShape(item); areaSTRtree.Remove(item.EnvelopeInternal, item); } }
public void RunQueries() { var visitor = new CountItemVisitor <object>(); int size = _index.Count; int side = (int)Math.Sqrt(size); for (int i = 0; i < side; i++) { for (int j = 0; j < side; j++) { var env = new Envelope(i, i + QUERY_ENV_SIZE, j, j + QUERY_ENV_SIZE); _index.Query(env, visitor); } } Console.WriteLine($"Total query result items = {visitor.Count}"); }
public void TestStrIndex() { STRtree ndx = new STRtree(); foreach (var v in CreateTestGeometries(1000, 0.0, 0.0, 3000.0, 3000.0)) { ndx.Insert(v.EnvelopeInternal, v); } ndx.Build(); IEnvelope queryExtents = new Envelope(100.0, 120.0, 100.0, 120.0); IList matches = ndx.Query(queryExtents); foreach (IGeometry list in matches) { Assert.IsTrue(list.EnvelopeInternal.Intersects(queryExtents), "a result from the index does not intersect the query bounds"); } }
private HashSet <string> GetCodesFromGeo(string bbox) { var envelope = GeoUtils.ToEnvelope(bbox); var codesFromPoints = _kdTree.Query(envelope); var codesFromEnvelopes = _stRtree.Query(envelope); HashSet <string> codesFromGeo = new HashSet <string>(); foreach (var code in codesFromPoints) { codesFromGeo.Add(code.Data); } foreach (var code in codesFromEnvelopes) { codesFromGeo.Add(code); } return(codesFromGeo); }
internal PointCollection RemoveNear(LineGraph roads, double minDis) { if (roads.nodes.Count == 0) { return(this); } var rtree = new STRtree <LineString>(); foreach (var node in roads.nodes) { foreach (var next in node.nextConnections) { Coordinate[] coords = new Coordinate[] { new Coordinate(node.pos.X, node.pos.Y), new Coordinate(next.pos.X, next.pos.Y) }; LineString ls = new LineString(coords); rtree.Insert(ls.EnvelopeInternal, ls); } } rtree.Build(); List <Vector2d> newpoints = new List <Vector2d>(); foreach (var x in points) { bool isNear = false; foreach (var ls in rtree.Query(new Envelope(x.X - minDis, x.X + minDis, x.Y - minDis, x.Y + minDis))) { if (ls.IsWithinDistance(new NetTopologySuite.Geometries.Point(x.X, x.Y), minDis)) { isNear = true; break; } } if (!isNear) { newpoints.Add(x); } } points = newpoints; return(this); }
private void CheckPiles(List <Pile> piles) { STRtree <Pile> rtree = new STRtree <Pile> (); foreach (var p in piles) { var r = getPileEnvelope(p); rtree.Insert(r, p); } var minLenAbs = Options.PileSide * PileOptions.PileRatioLmin; var minLen = minLenAbs - 0.1; List <Pile> pilesErrMinLen = new List <Pile>(); foreach (var p in piles) { var envelope = new Envelope(p.Position.X - minLen, p.Position.X + minLen, p.Position.Y - minLen, p.Position.Y + minLen); var pilesMinLen = rtree.Query(envelope); foreach (var item in pilesMinLen) { if (p == item) { continue; } if (p.Position.DistanceTo(item.Position) < minLen) { pilesErrMinLen.Add(p); } } } foreach (var item in pilesErrMinLen) { Inspector.AddError($"Нарушено минимальное расстояние между сваями - Сторона сваи * {PileOptions.PileRatioLmin} = {minLenAbs}. Точка вставки сваи {item.Position}", item.IdBlRef, System.Drawing.SystemIcons.Warning); } }
//Dictionary<Coordinate, bool> isExsitedOnView = new Dictionary<Coordinate, bool>(); private void DisplayGPSByRTree(Coordinate p1, Coordinate p2) { if (gpsSTRtree.IsEmpty) { return; } var gpsQuery = new Envelope(p1, p2); var gpsItems = gpsSTRtree.Query(gpsQuery); //MainMap.Markers.Clear(); //button10_Click(null, null); foreach (Coordinate gps in gpsItems) { //if (!isExsitedOnView.ContainsKey(gps)) //{ AddMakerToGmap(gps); //isExsitedOnMap.Add(gps, true); //} //else //{ // isExsitedOnView[gps] = true; //} gpsSTRtree.Remove(new Envelope(gps), gps); } //foreach (var item in isExsitedOnView) //{ // if (item.Value == false) // { // GMapMarker gps = new GMapMarker(new PointLatLng(item.Key.Y, item.Key.X)); // MainMap.Markers.Remove(gps); // } //} //isExsitedOnView.Clear(); //isExsitedOnView = gpsItems.GroupBy(x => x).Select(x => x.First()).ToDictionary(key => key, value => true); }
/// <summary> /// Query the geospatial model for all entities that fall within a given viewport /// </summary> /// <param name="viewPort"></param> /// <returns></returns> public IList <ISpatiallyIndexable> Query(Envelope viewPort) { return(_geospatialElements.Query(viewPort)); }
internal static void DoIntersections(BlobCollection blobs) { Dictionary<string, long> uids = new Dictionary<string, long>(); // finally decided I needed something to guarantee uniqueness like this TODO: can probably eliminate this long uidCounter = -1000; List<Way> ways = TempGetWays(blobs); ways.Add(blobs.borderWay); List<WayRef> wayRefs = new List<WayRef>(); STRtree<WayRef> rtree = new STRtree<WayRef>(); foreach (var way in ways) { for (int i = 1; i < way.refs.Count; i++) { WayRef wayRef = new WayRef() { wayRef = way, nodePos = i - 1 }; wayRefs.Add(wayRef); Vector2d pos1 = blobs.nodes[way.refs[i - 1]]; Vector2d pos2 = blobs.nodes[way.refs[i]]; var env = new Envelope(Math.Min(pos1.X, pos2.X), Math.Max(pos1.X, pos2.X), Math.Min(pos1.Y, pos2.Y), Math.Max(pos1.Y, pos2.Y)); rtree.Insert(env, wayRef); } } rtree.Build(); Dictionary<Way, List<NewIntersection>> intersections = new Dictionary<Way, List<NewIntersection>>(); foreach (var n1 in wayRefs) { Vector2d pos1 = blobs.nodes[n1.wayRef.refs[n1.nodePos]]; Vector2d pos2 = blobs.nodes[n1.wayRef.refs[n1.nodePos + 1]]; var env = new Envelope(Math.Min(pos1.X, pos2.X), Math.Max(pos1.X, pos2.X), Math.Min(pos1.Y, pos2.Y), Math.Max(pos1.Y, pos2.Y)); foreach (var n2 in rtree.Query(env)) { if (n1.GetHashCode() <= n2.GetHashCode()) continue; // as a way of preventing the same query twice long Aid = n1.wayRef.refs[n1.nodePos]; long Bid = n1.wayRef.refs[n1.nodePos + 1]; long Cid = n2.wayRef.refs[n2.nodePos]; long Did = n2.wayRef.refs[n2.nodePos + 1]; Vector2d A = blobs.nodes[Aid]; Vector2d B = blobs.nodes[Bid]; Vector2d C = blobs.nodes[Cid]; Vector2d D = blobs.nodes[Did]; if (Math.Min(A.X, B.X) > Math.Max(C.X, D.X)) continue; if (Math.Max(A.X, B.X) < Math.Min(C.X, D.X)) continue; if (Math.Min(A.Y, B.Y) > Math.Max(C.Y, D.Y)) continue; if (Math.Max(A.Y, B.Y) < Math.Min(C.Y, D.Y)) continue; string intersectionKey = Aid + "," + Cid; // TODO: we're going to treat -1 as always matching for now bool ACSame = Aid == Cid; bool ADSame = Aid == Did; bool BCSame = Bid == Cid; bool BDSame = Bid == Did; // a subset of possible tiny angles that can cause rounding errors // only thing that changes between these is the condition, line direction, and the newpoint id // TODO: is this really what fixed the nonsense at 240202043? the angleDiff was only 0.009, which seems too big to cause an issue bool someCollinear = false; bool isBorderIntersection = Aid < 0 || Bid < 0 || Cid < 0 || Did < 0; someCollinear |= CheckCollinear(Aid, n2.nodePos, n2.nodePos + 1, n2, intersections, blobs, true, isBorderIntersection); someCollinear |= CheckCollinear(Bid, n2.nodePos, n2.nodePos + 1, n2, intersections, blobs, true, isBorderIntersection); someCollinear |= CheckCollinear(Cid, n1.nodePos, n1.nodePos + 1, n1, intersections, blobs, true, isBorderIntersection); someCollinear |= CheckCollinear(Did, n1.nodePos, n1.nodePos + 1, n1, intersections, blobs, true, isBorderIntersection); if (!ACSame && !ADSame && !BCSame && !BDSame) // proper intersection { if (someCollinear) { if (n1.wayRef.id == n2.wayRef.id) { n1.wayRef.selfIntersects = true; // mark for destruction, probably } } else { // let's sort these lines to guarantee duplicates by value long[] ns = new long[] { Aid, Bid, Cid, Did }; if (ns[0] >= ns[2]) ns = ns.Reverse().ToArray(); if (ns[0] >= ns[1]) { var t = ns[1]; ns[1] = ns[0]; ns[0] = t; } if (ns[2] >= ns[3]) { var t = ns[3]; ns[3] = ns[2]; ns[2] = t; } Vector2d intersection = Intersect(blobs.nodes[ns[0]], blobs.nodes[ns[1]], blobs.nodes[ns[2]], blobs.nodes[ns[3]]); if (intersection != null) { long intersectionID; if (uids.ContainsKey(intersectionKey)) { intersectionID = uids[intersectionKey]; } else { intersectionID = uidCounter--; uids[intersectionKey] = intersectionID; } NewIntersection newNode1 = new NewIntersection() { nodeID = intersectionID, wayRef = n1.wayRef, nodePos = n1.nodePos + 1 }; NewIntersection newNode2 = new NewIntersection() { nodeID = intersectionID, wayRef = n2.wayRef, nodePos = n2.nodePos + 1 }; blobs.nodes[intersectionID] = intersection; if (!intersections.ContainsKey(n1.wayRef)) intersections.Add(n1.wayRef, new List<NewIntersection>()); intersections[n1.wayRef].Add(newNode1); if (!intersections.ContainsKey(n2.wayRef)) intersections.Add(n2.wayRef, new List<NewIntersection>()); intersections[n2.wayRef].Add(newNode2); if (n1.wayRef.id == n2.wayRef.id) { n1.wayRef.selfIntersects = true; // mark for destruction, probably } } } } } } List<long> wayids = new List<long>(); foreach (var pair in intersections) { if (wayids.Contains(pair.Key.id)) throw new NotImplementedException(); wayids.Add(pair.Key.id); } foreach (var pair in intersections) { foreach (var intersection in pair.Value) { intersection.sortRank = Sorter(intersection, blobs); } } foreach (var pair in intersections) { var sorted = pair.Value.OrderBy(x => x.sortRank).ToList(); // get rid of duplicates for (int i = sorted.Count - 1; i > 0; i--) { if (sorted[i].nodeID == sorted[i - 1].nodeID) sorted.RemoveAt(i); } // now insert them for (int i = sorted.Count - 1; i >= 0; i--) { pair.Key.refs.Insert(sorted[i].nodePos, sorted[i].nodeID); } } RemoveDuplicates(blobs); // remove duplicates at the end to also remove duplicate intersections }
public void TestKNearestNeighbors() { int topK = 1000; int totalRecords = 10000; var geometryFactory = new GeometryFactory(); var coordinate = new Coordinate(10.1, -10.1); var queryCenter = geometryFactory.CreatePoint(coordinate); int valueRange = 1000; var testDataset = new List <Geometry>(); var correctData = new List <Geometry>(); var random = new Random(); var distanceComparator = new GeometryDistanceComparer(queryCenter, true); /* * Generate the random test data set */ for (int i = 0; i < totalRecords; i++) { coordinate = new Coordinate(-100 + random.Next(valueRange) * 1.1, random.Next(valueRange) * (-5.1)); var spatialObject = geometryFactory.CreatePoint(coordinate); testDataset.Add(spatialObject); } /* * Sort the original data set and make sure the elements are sorted in an ascending order */ testDataset.Sort(distanceComparator); /* * Get the correct top K */ for (int i = 0; i < topK; i++) { correctData.Add(testDataset[i]); } var strtree = new STRtree <Geometry>(); for (int i = 0; i < totalRecords; i++) { strtree.Insert(testDataset[i].EnvelopeInternal, testDataset[i]); } /* * Shoot a random query to make sure the STR-Tree is built. */ strtree.Query(new Envelope(1 + 0.1, 1 + 0.1, 2 + 0.1, 2 + 0.1)); /* * Issue the KNN query. */ var testTopK = strtree.NearestNeighbour(queryCenter.EnvelopeInternal, queryCenter, new GeometryItemDistance(), topK); var topKList = new List <Geometry>(testTopK); topKList.Sort(distanceComparator); /* * Check the difference between correct result and test result. The difference should be 0. */ int difference = 0; for (int i = 0; i < topK; i++) { if (distanceComparator.Compare(correctData[i], topKList[i]) != 0) { difference++; } } Assert.That(difference, Is.Zero); }
public IList <T> Query(Envelope searchEnv) { return(_index.Query(searchEnv)); }
// special case for streets public static bool CheckForIntersection(Geometry geometry, STRtree <Geometry> possibleIntersections) { return(possibleIntersections.Query(geometry.EnvelopeInternal).Any(x => x.Intersects(geometry))); }
// TODO: somehow merge this with DoIntersections all in one pass elegantly // this method is called before all of these maps get added together // it will detect and remove shapes found inside each other public static void FixLoops(List<SectorConstrainedOSMAreaGraph> addingMaps, BlobCollection blobs) { // TODO: I think we still need to exclude intersecting loops from our thing STRtree<LoopRef> rtree = new STRtree<LoopRef>(); List<MainLoopRef> mainLoopRefs = new List<MainLoopRef>(); HashSet<AreaNode> explored = new HashSet<AreaNode>(); foreach (var addingMap in addingMaps) { foreach (var nodeList in addingMap.nodes.Values) { foreach (var node in nodeList) { if (explored.Contains(node)) continue; List<AreaNode> newLoop = new List<AreaNode>(); AreaNode curr = node; while (true) { newLoop.Add(curr); explored.Add(curr); if (curr.next == node) { mainLoopRefs.Add(new MainLoopRef() { nodes = newLoop, graph = addingMap }); break; } curr = curr.next; } } } } foreach (var loopRef in mainLoopRefs) { loopRef.isCW = GetArea(loopRef.nodes, blobs) < 0; } foreach (var loopRef in mainLoopRefs) { for (int i = 0; i < loopRef.nodes.Count; i++) { Vector2d pos1 = blobs.nodes[loopRef.nodes[i].id]; Vector2d pos2 = blobs.nodes[loopRef.nodes[(i + 1) % loopRef.nodes.Count].id]; var env = new Envelope(Math.Min(pos1.X, pos2.X), Math.Max(pos1.X, pos2.X), Math.Min(pos1.Y, pos2.Y), Math.Max(pos1.Y, pos2.Y)); rtree.Insert(env, new LoopRef() { nodes = loopRef.nodes, graph = loopRef.graph, v1 = pos1, v2 = pos2, n1 = loopRef.nodes[i].id, n2 = loopRef.nodes[(i + 1) % loopRef.nodes.Count].id, isCW = loopRef.isCW }); } } rtree.Build(); List<MainLoopRef> remove = new List<MainLoopRef>(); foreach (var loopRef in mainLoopRefs) { HashSet<long> nodesLookup = new HashSet<long>(); foreach (var n in loopRef.nodes) nodesLookup.Add(n.id); var node = blobs.nodes[loopRef.nodes.First().id]; Vector2d v1 = new Vector2d(node.X, 10); Vector2d v2 = new Vector2d(node.X, -10); var env = new Envelope(node.X, node.X, -10, 10); var intersections = rtree.Query(env); bool doRemove = false; foreach (var group in intersections.GroupBy(x => x.graph)) { bool isOwnGraph = group.First().graph == loopRef.graph; if (!isOwnGraph && group.Any(x => x.nodes.Any(y => nodesLookup.Contains(y.id)))) continue; // let's ignore WHOLE GRAPHS that intersect with us (might need to revise this thinking) var lessfiltered = group.Where(x => x.v1.X != x.v2.X).ToList(); // skip vertical intersections var sorted = lessfiltered.Where(x => Math.Min(x.v1.X, x.v2.X) != node.X).ToList(); // on perfect-overlap of adjoining lines, this will count things appropriately sorted = sorted.OrderBy(x => -Intersect(v1, v2, x.v1, x.v2).Y).ToList(); // order from bottom to top sorted = sorted.Where(x => x.nodes != loopRef.nodes).ToList(); // ignore our own loop List<int> prevSwaps = new List<int>(); for (int i = 1; i < sorted.Count; i++) { // swap perfectly adjacent if necessary if ((sorted[i - 1].v2 == sorted[i].v1 && sorted[i - 1].v2.X == node.X && sorted[i - 1].V1Y() < sorted[i].V2Y()) || (sorted[i - 1].v1 == sorted[i].v2 && sorted[i - 1].v1.X == node.X && sorted[i - 1].V2Y() < sorted[i].V1Y())) { var temp = sorted[i - 1]; sorted[i - 1] = sorted[i]; sorted[i] = temp; prevSwaps.Add(i - 1); } } var validateStack = new List<LoopRef>(); var contains = new List<LoopRef>(); if (sorted.Count % 2 != 0) throw new NotImplementedException(); // malformed shape for (int i = 0; i < sorted.Count; i++) { bool outer = !sorted[i].isCW; // we will no longer be checking for outers immediately within outers, etc. because sometimes people mess up bool opens = outer == sorted[i].IsLeftToRight(); if (opens) { validateStack.Add(sorted[i]); } else { if (validateStack.Last().nodes != sorted[i].nodes) throw new NotImplementedException(); // malformed shape if (Intersect(v1, v2, validateStack.Last().v1, validateStack.Last().v2).Y > node.Y && Intersect(v1, v2, sorted[i].v1, sorted[i].v2).Y < node.Y) { contains.Add(sorted[i]); // add the one that's above it, sure } validateStack.RemoveAt(validateStack.Count - 1); } } if (validateStack.Count > 0) throw new NotImplementedException(); // malformed shape // remove duplicates that overlap perfectly for (int i = sorted.Count - 1; i > 0; i--) { if (sorted[i].ContainsNode(sorted[i - 1].v1) || sorted[i].ContainsNode(sorted[i - 1].v2)) { Vector2d inCommon = sorted[i].ContainsNode(sorted[i - 1].v1) ? sorted[i - 1].v1 : sorted[i - 1].v2; if (inCommon.X == node.X) { sorted.RemoveRange(i - 1, 2); i -= 2; } } } if (contains.Count == 0 && isOwnGraph && loopRef.isCW) doRemove = true; if (contains.Count == 0) continue; var immediate = contains.First(); if (isOwnGraph && immediate.isCW == loopRef.isCW) doRemove = true; // remove the outermost invalid loop if (!isOwnGraph && !immediate.isCW) doRemove = true; // remove anything immediately contained by an outer } if (doRemove) remove.Add(loopRef); } foreach (var r in remove) { foreach (var node in r.nodes) { r.graph.nodes[node.id].Remove(node); if (r.graph.nodes[node.id].Count == 0) r.graph.nodes.Remove(node.id); } } }