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 void Run() { hpRtree = new HPRtree <string>(); stRtree = new STRtree <string>(); //loadRandom(NUM_ITEMS); LoadGrid(NUM_ITEMS); var sw = new Stopwatch(); sw.Start(); stRtree.Build(); sw.Stop(); Console.WriteLine($"STRtree build time: {sw.ElapsedMilliseconds}ms"); sw.Restart(); hpRtree.Build(); sw.Stop(); Console.WriteLine($"HPRtree build time: {sw.ElapsedMilliseconds}ms"); sw.Restart(); for (int i = 0; i < NUM_QUERY; i++) { QueryRandom(); } sw.Stop(); Console.WriteLine($"Query time: {sw.ElapsedMilliseconds}ms"); }
protected override void AddCells_internal() { foreach (var cell in CellList) { var cellPos = cell.PositionWithSize; NTSSTRTreeCellTree.Insert(new Envelope(cellPos[0].MinVal, cellPos[0].MaxVal, cellPos[1].MinVal, cellPos[1].MaxVal), cell); } NTSSTRTreeCellTree.Build(); }
// ReSharper restore InconsistentNaming /// <summary> /// /// </summary> /// <param name="g"></param> /// <returns></returns> public static STRtree<FacetSequence> BuildSTRtree(IGeometry g) { var tree = new STRtree<FacetSequence>(STRtreeNodeCapacity); var sections = ComputeFacetSequences(g); foreach (var section in sections) { tree.Insert(section.Envelope, section); } tree.Build(); return tree; }
public MapGeometry(MapData map) { Map = map; Vertices = map.Vertices.Select(v => v.ToVector2()).ToArray(); var minX = Vertices.Min(p => p.X); var maxX = Vertices.Max(p => p.X); var minY = Vertices.Min(p => p.Y); var maxY = Vertices.Max(p => p.Y); BottomLeftCorner = new Vector2(minX, minY); Area = new Vector2(maxX - minX, maxY - minY); var lines = new List <Line>(); for (int lineDefId = 0; lineDefId < Map.LineDefs.Count; lineDefId++) { var lineDef = Map.LineDefs[lineDefId]; var frontSide = Map.SideDefs[lineDef.SideFront]; if (!lineDef.TwoSided) { lines.Add(new Line(lineDefId, frontSide.Sector, lineDef.V1, Map.Vertices[lineDef.V1], lineDef.V2, Map.Vertices[lineDef.V2])); } else { var backSide = Map.SideDefs[lineDef.SideBack]; lines.Add(new Line(lineDefId, frontSide.Sector, lineDef.V1, Map.Vertices[lineDef.V1], lineDef.V2, Map.Vertices[lineDef.V2], portalToSectorId: backSide.Sector)); lines.Add(new Line(lineDefId, backSide.Sector, lineDef.V1, Map.Vertices[lineDef.V1], lineDef.V2, Map.Vertices[lineDef.V2], portalToSectorId: frontSide.Sector)); } } Lines = lines.ToArray(); Sectors = new SectorInfo[map.Sectors.Count]; foreach (var sectorIndex in Enumerable.Range(0, Sectors.Length)) { var linesForSector = Lines.Where(line => line.SectorId == sectorIndex); Sectors[sectorIndex] = new SectorInfo(map.Sectors[sectorIndex], linesForSector); _sectorIdLookup.Insert(GetSectorMinimumBoundingRectangle(sectorIndex), sectorIndex); } _sectorIdLookup.Build(); ThingToSectorId = new int[map.Things.Count]; foreach (var thingIndex in Enumerable.Range(0, map.Things.Count)) { ThingToSectorId[thingIndex] = FindSurroundingSector(map.Things[thingIndex].GetPosition()); } }
/// <summary> /// /// </summary> /// <param name="g"></param> /// <returns></returns> public static STRtree <FacetSequence> BuildSTRtree(Geometry g) // ReSharper restore InconsistentNaming { var tree = new STRtree <FacetSequence>(STRtreeNodeCapacity); var sections = ComputeFacetSequences(g); foreach (var section in sections) { tree.Insert(section.Envelope, section); } tree.Build(); return(tree); }
public void LoadMap() { using (var wad = WadReader.Read("freedoom2-udmf.wad")) { _map = new MapGeometry(MapData.LoadFrom(wad.GetTextmapStream("MAP28"))); } _sectorBounds = new STRtree <int>(); for (int sectorId = 0; sectorId < _map.Sectors.Length; sectorId++) { _sectorBounds.Insert(_map.GetSectorMinimumBoundingRectangle(sectorId), sectorId); } _sectorBounds.Build(); }
//public static ISpatialIndex<IFeature> spatialIndex(IFeatureSet set) //{ // var tree = new STRtree<IFeature>(set.NumRows()); // foreach (var m in set.Features) // { // tree.Insert(m.Geometry.EnvelopeInternal, m); // } // tree.Build(); // return tree; //} public static ISpatialIndex <IFeature> spatialIndex(params IFeatureSet[] set) { var tree = new STRtree <IFeature>(); foreach (var fs in set) { foreach (var m in fs.Features) { tree.Insert(m.Geometry.EnvelopeInternal, m); } } tree.Build(); return(tree); }
public override void StartRun(int size) { Console.WriteLine($"----- Tree size: {size}"); _index = new STRtree <object>(NODE_SIZE); int side = (int)Math.Sqrt(size); LoadGrid(side, _index); var sw = new Stopwatch(); sw.Start(); _index.Build(); sw.Stop(); Console.WriteLine($"Build time = {sw.ElapsedMilliseconds}ms"); }
/// <summary> /// Create a geographical view of the network /// </summary> /// <param name="topology"></param> public NetworkGeography(NetworkTopology topology) { foreach (var device in topology.Devices.Values) { // Add the device to the spatial index _geospatialElements.Insert(device.Envelope, device); // Add the edges to the tree (check on Id is due to edges being bi-directional, only want to add once) foreach (var adjacentDevice in device.AdjacentDevices.Where(ad => ad.Id > device.Id)) { var edge = new Edge(device, adjacentDevice); _geospatialElements.Insert(edge.Envelope, edge); } } _geospatialElements.Build(); }
public async Task <STRtree <SlimAccommodationData> > GetCountryAccommodationsTree(string countryCode, string supplier, CancellationToken cancellationToken) { var countryAccommodations = new List <SlimAccommodationData>(); var accommodations = new List <SlimAccommodationData>(); var skip = 0; do { accommodations = await _context.Accommodations.Where(ac => ac.CountryCode == countryCode && !EF.Functions.JsonExists(ac.SupplierAccommodationCodes, supplier) && ac.IsActive) .OrderBy(ac => ac.Id) .Skip(skip) .Take(_batchSize) .Select(ac => new SlimAccommodationData { HtId = ac.Id, KeyData = ac.KeyData, SupplierAccommodationCodes = ac.SupplierAccommodationCodes }) .ToListAsync(cancellationToken); skip += _batchSize; countryAccommodations.AddRange(accommodations); } while (accommodations.Count > 0); if (!countryAccommodations.Any() || countryAccommodations.Count == 1) { return(new STRtree <SlimAccommodationData>()); } var tree = new STRtree <SlimAccommodationData>(countryAccommodations.Count); foreach (var ac in countryAccommodations) { if (!ac.KeyData.Coordinates.IsEmpty() && ac.KeyData.Coordinates.IsValid()) { tree.Insert(new Point(ac.KeyData.Coordinates.Longitude, ac.KeyData.Coordinates.Latitude).EnvelopeInternal, ac); } } tree.Build(); return(tree); }
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"); } }
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); }
public void FinishInserting() { _index.Build(); }
// 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); } } }
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 }