From 32769726cccdc4666bf6a2dbcec4fc539a783810 Mon Sep 17 00:00:00 2001 From: Luiz Fernando Silva Date: Mon, 9 Dec 2024 10:50:53 -0300 Subject: [PATCH] [Clipping] Using lazy SpatialTree iteration in parametric intersection creation --- .../SpatialTree/SpatialTree.swift | 36 +++++++++++++++++++ .../2D/Graph/Simplex2Graph+Creation.swift | 22 +++++++----- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/Sources/GeometriaAlgorithms/SpatialPartitioning/SpatialTree/SpatialTree.swift b/Sources/GeometriaAlgorithms/SpatialPartitioning/SpatialTree/SpatialTree.swift index 3dde463e..a21f416a 100644 --- a/Sources/GeometriaAlgorithms/SpatialPartitioning/SpatialTree/SpatialTree.swift +++ b/Sources/GeometriaAlgorithms/SpatialPartitioning/SpatialTree/SpatialTree.swift @@ -112,6 +112,42 @@ public struct SpatialTree: SpatialTreeType where Element return result } + /// Performs a point query using a closure to be invoked for each element + /// found to intersect `point`. + @inlinable + public func lazyQueryPoint( + _ point: Vector, + _ closure: (Element) -> Void + ) { + root.queryPoint(point) { (_, element) in + closure(element) + } + } + + /// Performs a line query using a closure to be invoked for each element + /// found to intersect `line`. + @inlinable + public func lazyQueryLine( + _ line: Line, + _ closure: (Element) -> Void + ) where Line.Vector == Vector { + root.queryLine(line) { (_, element) in + closure(element) + } + } + + /// Performs a bound query using a closure to be invoked for each element + /// found to intersect `area`. + @inlinable + public func lazyQuery( + _ area: Bounds, + _ closure: (Element) -> Void + ) where Bounds.Vector == Vector { + root.query(area) { (_, element) in + closure(element) + } + } + // MARK: - Mutation @inlinable diff --git a/Sources/GeometriaClipping/2D/Graph/Simplex2Graph+Creation.swift b/Sources/GeometriaClipping/2D/Graph/Simplex2Graph+Creation.swift index 500502c1..8547cfba 100644 --- a/Sources/GeometriaClipping/2D/Graph/Simplex2Graph+Creation.swift +++ b/Sources/GeometriaClipping/2D/Graph/Simplex2Graph+Creation.swift @@ -289,14 +289,17 @@ extension Simplex2Graph { // MARK: Edge-vertex interferences for node in nodes { let nodeAABB = AABB2(center: node.location, size: .init(repeating: tolerance * 2)) - let edgesNearNode = edgeTree.query(nodeAABB) - for edge in edgesNearNode where edge.start != node && edge.end != node { + edgeTree.lazyQuery(nodeAABB) { edge in + guard edge.start != node && edge.end != node else { + return + } + let (ratio, distanceSquared) = edge.closestRatio(to: node.location) // Avoid attempts to split an edge at its end points. guard ratio > 0 && ratio < 1 else { - continue + return } if distanceSquared.squareRoot() < tolerance { @@ -414,12 +417,13 @@ extension Simplex2Graph { var edgesToCheck: OrderedSet> = [] for edge in edges { - let coincident = - edgeTree - .query(edge) - .filter({ next in - next.coincidenceRelationship(with: edge, tolerance: tolerance) == .sameSpan - }) + var coincident: [Edge] = [] + + edgeTree.lazyQuery(edge) { next in + if next.coincidenceRelationship(with: edge, tolerance: tolerance) == .sameSpan { + coincident.append(next) + } + } guard !coincident.isEmpty else { continue