public void TestRemoveSTRtree() { var tree = new STRtree<string>(); tree.Insert(new Envelope(0, 10, 0, 10), "1"); tree.Insert(new Envelope(5, 15, 5, 15), "2"); tree.Insert(new Envelope(10, 20, 10, 20), "3"); tree.Insert(new Envelope(15, 25, 15, 25), "4"); Assert.DoesNotThrow(() => tree.Remove(new Envelope(10, 20, 10, 20), "4")); Assert.AreEqual(3, tree.Count); }
// 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 async Task Initialize(string supplier, string countryCode, CancellationToken cancellationToken) { NotSupplierAccommodationsTree = new STRtree <SlimAccommodationData>(); _supplierActiveAccommodations.Clear(); _supplierInvalidAccommodations.Clear(); _supplierDeprecatedToActivateAccommodations.Clear(); await InitializeNotSupplierAccommodationsTree(supplier, countryCode, cancellationToken); await InitializeSupplierAccommodations(supplier, countryCode, cancellationToken); await InitializeActiveUncertainMatches(supplier, countryCode, cancellationToken); }
public void TestRemoveSTRtree() { var tree = new STRtree <string>(); tree.Insert(new Envelope(0, 10, 0, 10), "1"); tree.Insert(new Envelope(5, 15, 5, 15), "2"); tree.Insert(new Envelope(10, 20, 10, 20), "3"); tree.Insert(new Envelope(15, 25, 15, 25), "4"); Assert.DoesNotThrow(() => tree.Remove(new Envelope(10, 20, 10, 20), "4")); Assert.AreEqual(3, tree.Count); }
private STRtree <Geometry> CreateTree(Geometry items) { var tree = new STRtree <Geometry>(); for (int i = 0; i < items.NumGeometries; i++) { var item = items.GetGeometryN(i); tree.Insert(item.EnvelopeInternal, item); } return(tree); }
/// <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(); }
private static STRtree<IGeometry> BuildSTRtree(IGeometry geom) { var index = new STRtree<IGeometry>(); geom.Apply(new DelegateGeometryFilter { DoFilter = delegate(IGeometry tmpGeometry) { // only insert atomic geometries if (tmpGeometry is IGeometryCollection) return; index.Insert(tmpGeometry.EnvelopeInternal, tmpGeometry); } }); return index; }
//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"); }
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"); } }
private static STRtree <Geometry> BuildSTRtree(Geometry geom) { var index = new STRtree <Geometry>(); geom.Apply(new DelegateGeometryFilter { DoFilter = delegate(Geometry tmpGeometry) { // only insert atomic geometries if (tmpGeometry is GeometryCollection) { return; } index.Insert(tmpGeometry.EnvelopeInternal, tmpGeometry); } }); return(index); }
public static STRtree <string> Build(IEnumerable <NatureAreaDto> natureAreas) { var stRtree = new STRtree <string>(); var parsedEnvelopes = new ConcurrentDictionary <string, Envelope>(); Parallel.ForEach(natureAreas, (na) => { var envelopeGeometry = ReadWkt(na.Envelope); parsedEnvelopes.TryAdd(CodePrefixes.GetNatureAreaCode(na.Id), envelopeGeometry); }); foreach (var kvp in parsedEnvelopes) { stRtree.Insert(kvp.Value, kvp.Key); } return(stRtree); }
/// <summary> /// Setup for element-search /// </summary> public void SetupElementSearch() { #if NTS173 _elementSearchTree = new STRtree(); #else _elementSearchTree = new STRtree <MeshElement>(); #endif for (int i = 0; i < _mesh.Elements.Count; i++) { MeshElement element = _mesh.Elements[i]; double x = element.Nodes[0].X; double y = element.Nodes[0].Y; Envelope extent = new Envelope(x, x, y, y); for (int j = 1; j < element.Nodes.Count; j++) { extent.ExpandToInclude(element.Nodes[j].X, element.Nodes[j].Y); } _elementSearchTree.Insert(extent, element); } }
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 static void AddGeomToCache(string table, int id, SqlGeometry geom) { if (!_geomCacheByTableThenId.ContainsKey(table)) { _geomCacheByTableThenId[table] = new Dictionary <int, SqlGeometry>(); _geomEnvelopeAreaCacheByTableThenId[table] = new Dictionary <int, double>(); _geomCentroidCacheByTableThenId[table] = new Dictionary <int, Models.Geometry.Point>(); _spatialIndexSTR[table] = new STRtree <int>(); } SqlGeometry envelope = geom.STEnvelope(); Envelope env = new Envelope(envelope.STPointN(1).STX.Value, envelope.STPointN(3).STX.Value, envelope.STPointN(1).STY.Value, envelope.STPointN(3).STY.Value); _geomCacheByTableThenId[table][id] = geom; _geomEnvelopeAreaCacheByTableThenId[table][id] = envelope.STArea().Value; SqlGeometry envelopeCentroid = envelope.STCentroid().STPointN(1); _geomCentroidCacheByTableThenId[table][id] = new Models.Geometry.Point((float)envelopeCentroid.STX.Value, (float)envelopeCentroid.STY.Value); _spatialIndexSTR[table].Insert(env, id); }
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); } }
/// <summary> /// Initializes a new instance of the <see cref="MCIndexPointSnapper"/> class. /// </summary> /// <param name="index"></param> public MCIndexPointSnapper(ISpatialIndex <MonotoneChain> index) { //_monoChains = monoChains; _index = (STRtree <MonotoneChain>)index; }
/// <summary> /// Creates a new distance-finding instance for a given target <see cref="Geometry"/>. /// </summary> /// <remarks> /// <para> /// Distances will be computed to all facets of the input geometry. /// The facets of the geometry are the discrete segments and points /// contained in its components. </para> /// <para> /// In the case of <see cref="ILineal"/> and <see cref="IPuntal"/> inputs, /// this is equivalent to computing the conventional distance. /// </para><para> /// In the case of <see cref="IPolygonal"/> inputs, this is equivalent /// to computing the distance to the polygon boundaries. /// </para> /// </remarks> /// <param name="g1">A Geometry, which may be of any type.</param> public IndexedFacetDistance(Geometry g1) { baseGeometry = g1; _cachedTree = FacetSequenceTreeBuilder.BuildSTRtree(g1); }
/// <summary> /// Computes the union of the input geometries. /// </summary> /// <returns> /// <remarks> /// This method discards the input geometries as they are processed. /// In many input cases this reduces the memory retained /// as the operation proceeds. /// Optimal memory usage is achieved /// by disposing of the original input collection /// before calling this method. /// </remarks> /// The union of the input geometries, /// or <c>null</c> if no input geometries were provided /// </returns> /// <exception cref="InvalidOperationException">if this method is called more than once</exception> public IGeometry Union() { if (_inputPolys == null) throw new InvalidOperationException("Union() method cannot be called twice"); if (_inputPolys.Count == 0) return null; _geomFactory = Factory(); /* * A spatial index to organize the collection * into groups of close geometries. * This makes unioning more efficient, since vertices are more likely * to be eliminated on each round. */ var index = new STRtree<object>(StrtreeNodeCapacity); foreach (IGeometry item in _inputPolys) index.Insert(item.EnvelopeInternal, item); // To avoiding holding memory remove references to the input geometries, _inputPolys = null; var itemTree = index.ItemsTree(); var unionAll = UnionTree(itemTree); return unionAll; }
protected override void Init_internal() { NTSSTRTreeCellTree = new STRtree <Cell>(); }
// 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); } } }
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 STRtreeIndex(int nodeCapacity) { _index = new STRtree <T>(nodeCapacity); }
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 }
/// <summary> /// Initializes a new instance of the <see cref="MCIndexPointSnapper"/> class. /// </summary> /// <param name="monoChains"></param> /// <param name="index"></param> public MCIndexPointSnapper(IList monoChains, ISpatialIndex index) { this.monoChains = monoChains; this.index = (STRtree)index; }
protected override void Clean_internal() { NTSSTRTreeCellTree = null; }
// special case for streets public static bool CheckForIntersection(Geometry geometry, STRtree <Geometry> possibleIntersections) { return(possibleIntersections.Query(geometry.EnvelopeInternal).Any(x => x.Intersects(geometry))); }