@@ -40,28 +40,41 @@ GI.coordinates.(inter_points)
4040```
4141"""
4242function intersection (
43- geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs... ,
43+ alg :: FosterHormannClipping , geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs...
4444) where {T<: AbstractFloat }
4545 return _intersection (
46- TraitTarget (target), T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b;
46+ alg, TraitTarget (target), T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b;
4747 exact = True (), kwargs... ,
4848 )
4949end
5050
51+ # fallback definitions
52+ # if no manifold - assume planar (until we have best_manifold)
53+ function intersection (
54+ geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs...
55+ ) where {T<: AbstractFloat }
56+ return intersection (FosterHormannClipping (Planar ()), geom_a, geom_b; target, kwargs... )
57+ end
58+
59+ # if manifold but no algorithm - assume FosterHormannClipping with provided manifold.
60+ function intersection (m:: Manifold , geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs... ) where {T<: AbstractFloat }
61+ return intersection (FosterHormannClipping (m), geom_a, geom_b; target, kwargs... )
62+ end
63+
5164# Curve-Curve Intersections with target Point
5265_intersection (
53- :: TraitTarget{GI.PointTrait} , :: Type{T} ,
66+ alg :: FosterHormannClipping , :: TraitTarget{GI.PointTrait} , :: Type{T} ,
5467 trait_a:: Union{GI.LineTrait, GI.LineStringTrait, GI.LinearRingTrait} , geom_a,
5568 trait_b:: Union{GI.LineTrait, GI.LineStringTrait, GI.LinearRingTrait} , geom_b;
5669 kwargs... ,
57- ) where T = _intersection_points (T, trait_a, geom_a, trait_b, geom_b)
70+ ) where T = _intersection_points (alg . manifold, alg . accelerator, T, trait_a, geom_a, trait_b, geom_b)
5871
5972#= Polygon-Polygon Intersections with target Polygon
6073The algorithm to determine the intersection was adapted from "Efficient clipping
6174of efficient polygons," by Greiner and Hormann (1998).
6275DOI: https://doi.org/10.1145/274363.274364 =#
6376function _intersection (
64- :: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
77+ alg :: FosterHormannClipping , :: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
6578 :: GI.PolygonTrait , poly_a,
6679 :: GI.PolygonTrait , poly_b;
6780 exact, kwargs... ,
@@ -70,10 +83,10 @@ function _intersection(
7083 ext_a = GI. getexterior (poly_a)
7184 ext_b = GI. getexterior (poly_b)
7285 # Then we find the intersection of the exteriors
73- a_list, b_list, a_idx_list = _build_ab_list (T, ext_a, ext_b, _inter_delay_cross_f, _inter_delay_bounce_f; exact)
74- polys = _trace_polynodes (T, a_list, b_list, a_idx_list, _inter_step, poly_a, poly_b)
86+ a_list, b_list, a_idx_list = _build_ab_list (alg, T, ext_a, ext_b, _inter_delay_cross_f, _inter_delay_bounce_f; exact)
87+ polys = _trace_polynodes (alg, T, a_list, b_list, a_idx_list, _inter_step, poly_a, poly_b)
7588 if isempty (polys) # no crossing points, determine if either poly is inside the other
76- a_in_b, b_in_a = _find_non_cross_orientation (a_list, b_list, ext_a, ext_b; exact)
89+ a_in_b, b_in_a = _find_non_cross_orientation (alg, a_list, b_list, ext_a, ext_b; exact)
7790 if a_in_b
7891 push! (polys, GI. Polygon ([tuples (ext_a)]))
7992 elseif b_in_a
@@ -84,10 +97,10 @@ function _intersection(
8497 # If the original polygons had holes, take that into account.
8598 if GI. nhole (poly_a) != 0 || GI. nhole (poly_b) != 0
8699 hole_iterator = Iterators. flatten ((GI. gethole (poly_a), GI. gethole (poly_b)))
87- _add_holes_to_polys! (T, polys, hole_iterator, remove_idx; exact)
100+ _add_holes_to_polys! (alg, T, polys, hole_iterator, remove_idx; exact)
88101 end
89102 # Remove unneeded collinear points on same edge
90- _remove_collinear_points! (polys, remove_idx, poly_a, poly_b)
103+ _remove_collinear_points! (alg, polys, remove_idx, poly_a, poly_b)
91104 return polys
92105end
93106
@@ -112,7 +125,7 @@ _inter_step(x, _) = x ? 1 : (-1)
112125Unless specified with `fix_multipoly = nothing`, `multipolygon_b` will be validated using
113126the given (default is `UnionIntersectingPolygons()`) correction. =#
114127function _intersection (
115- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
128+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
116129 :: GI.PolygonTrait , poly_a,
117130 :: GI.MultiPolygonTrait , multipoly_b;
118131 fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
@@ -122,7 +135,7 @@ function _intersection(
122135 end
123136 polys = Vector {_get_poly_type(T)} ()
124137 for poly_b in GI. getpolygon (multipoly_b)
125- append! (polys, intersection (poly_a, poly_b; target))
138+ append! (polys, intersection (alg, poly_a, poly_b; target))
126139 end
127140 return polys
128141end
@@ -131,19 +144,19 @@ end
131144polygon with the multipolygon and thus simply switches the order of operations and calls the
132145above method. =#
133146_intersection (
134- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
147+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
135148 :: GI.MultiPolygonTrait , multipoly_a,
136149 :: GI.PolygonTrait , poly_b;
137150 kwargs... ,
138- ) where T = intersection (poly_b, multipoly_a; target , kwargs... )
151+ ) where T = intersection (alg, poly_b, multipoly_a; target , kwargs... )
139152
140153#= Multipolygon with multipolygon intersection - note that all intersection regions between
141154any sub-polygons of `multipoly_a` and any of the sub-polygons of `multipoly_b` are counted
142155as intersection polygons. Unless specified with `fix_multipoly = nothing`, both
143156`multipolygon_a` and `multipolygon_b` will be validated using the given (default is
144157`UnionIntersectingPolygons()`) correction. =#
145158function _intersection (
146- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
159+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
147160 :: GI.MultiPolygonTrait , multipoly_a,
148161 :: GI.MultiPolygonTrait , multipoly_b;
149162 fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
@@ -155,21 +168,37 @@ function _intersection(
155168 end
156169 polys = Vector {_get_poly_type(T)} ()
157170 for poly_a in GI. getpolygon (multipoly_a)
158- append! (polys, intersection (poly_a, multipoly_b; target, fix_multipoly))
171+ append! (polys, intersection (alg, poly_a, multipoly_b; target, fix_multipoly))
159172 end
160173 return polys
161174end
162175
176+ # catch-all method for multipolygontraits
177+ function intersection (
178+ alg:: FosterHormannClipping , :: TraitTarget{GI.MultiPolygonTrait} , :: Type{T} ,
179+ trait_a:: Union{GI.PolygonTrait, GI.MultiPolygonTrait} , polylike_a,
180+ trait_b:: Union{GI.PolygonTrait, GI.MultiPolygonTrait} , polylike_b;
181+ fix_multipoly = UnionIntersectingPolygons (), kwargs...
182+ ) where T
183+ polys = _intersection (alg, TraitTarget (GI. PolygonTrait ()), T, trait_a, polylike_a, trait_b, polylike_b; kwargs... )
184+ if isnothing (fix_multipoly)
185+ return GI. MultiPolygon (polys)
186+ else
187+ return fix_multipoly (GI. MultiPolygon (polys))
188+ end
189+ end
190+
191+
163192# Many type and target combos aren't implemented
164193function _intersection (
165- :: TraitTarget{Target} , :: Type{T} ,
194+ alg :: GeometryOpsCore.Algorithm , target :: TraitTarget{Target} , :: Type{T} ,
166195 trait_a:: GI.AbstractTrait , geom_a,
167196 trait_b:: GI.AbstractTrait , geom_b;
168197 kwargs... ,
169198) where {Target, T}
170199 @assert (
171200 false ,
172- " Intersection between $trait_a and $trait_b with target $Target isn't implemented yet." ,
201+ " Intersection between $trait_a and $trait_b with target $Target and algorithm $alg isn't implemented yet." ,
173202 )
174203 return nothing
175204end
@@ -193,13 +222,19 @@ inter_points = GO.intersection_points(line1, line2)
1932221-element Vector{Tuple{Float64, Float64}}:
194223 (125.58375366067548, -14.83572303404496)
195224"""
196- intersection_points (geom_a, geom_b, :: Type{T} = Float64) where T <: AbstractFloat =
197- _intersection_points (T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b)
225+ intersection_points (geom_a, geom_b, :: Type{T} = Float64) where T <: AbstractFloat = intersection_points (FosterHormannClipping (Planar ()), geom_a, geom_b, T)
226+ function intersection_points (alg:: FosterHormannClipping{M, A} , geom_a, geom_b, :: Type{T} = Float64) where {M, A, T <: AbstractFloat }
227+ return _intersection_points (alg. manifold, alg. accelerator, T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b)
228+ end
229+
230+ function intersection_points (m:: Manifold , a:: IntersectionAccelerator , geom_a, geom_b, :: Type{T} = Float64) where T <: AbstractFloat
231+ return _intersection_points (m, a, T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b)
232+ end
198233
199234
200235#= Calculates the list of intersection points between two geometries, including line
201236segments, line strings, linear rings, polygons, and multipolygons. =#
202- function _intersection_points (:: Type{T} , :: GI.AbstractTrait , a, :: GI.AbstractTrait , b; exact = True ()) where T
237+ function _intersection_points (manifold :: M , accelerator :: A , :: Type{T} , :: GI.AbstractTrait , a, :: GI.AbstractTrait , b; exact = True ()) where {M <: Manifold , A <: IntersectionAccelerator , T}
203238 # Initialize an empty list of points
204239 result = Tuple{T, T}[]
205240 # Check if the geometries extents even overlap
@@ -243,7 +278,7 @@ intersection point (x,y) while the second is the ratio along the initial lines (
243278that point.
244279
245280Calculation derivation can be found here: https://stackoverflow.com/questions/563198/ =#
246- function _intersection_point (:: Type{T} , (a1, a2):: Edge , (b1, b2):: Edge ; exact) where T
281+ function _intersection_point (manifold :: M , :: Type{T} , (a1, a2):: Edge , (b1, b2):: Edge ; exact) where {M <: Manifold , T}
247282 # Default answer for no intersection
248283 line_orient = line_out
249284 intr1 = ((zero (T), zero (T)), (zero (T), zero (T)))
@@ -266,7 +301,7 @@ function _intersection_point(::Type{T}, (a1, a2)::Edge, (b1, b2)::Edge; exact) w
266301 # Determine intersection type and intersection point(s)
267302 if a1_orient == a2_orient == b1_orient == b2_orient == 0
268303 # Intersection is collinear if all endpoints lie on the same line
269- line_orient, intr1, intr2 = _find_collinear_intersection (T, a1, a2, b1, b2, a_ext, b_ext, no_intr_result)
304+ line_orient, intr1, intr2 = _find_collinear_intersection (manifold, T, a1, a2, b1, b2, a_ext, b_ext, no_intr_result)
270305 elseif a1_orient == 0 || a2_orient == 0 || b1_orient == 0 || b2_orient == 0
271306 # Intersection is a hinge if the intersection point is an endpoint
272307 line_orient = line_hinge
@@ -279,13 +314,16 @@ function _intersection_point(::Type{T}, (a1, a2)::Edge, (b1, b2)::Edge; exact) w
279314 return line_orient, intr1, intr2
280315end
281316
317+ # TODO : deprecate this
318+ _intersection_point (:: Type{T} , (a1, a2):: Edge , (b1, b2):: Edge ; exact) where T = _intersection_point (Planar (), T, (a1, a2), (b1, b2); exact)
319+
282320#= If lines defined by (a1, a2) and (b1, b2) are collinear, find endpoints of overlapping
283321region if they exist. This could result in three possibilities. First, there could be no
284322overlapping region, in which case, the default 'no_intr_result' intersection information is
285323returned. Second, the two regions could just meet at one shared endpoint, in which case it
286324is a hinge intersection with one intersection point. Otherwise, it is a overlapping
287325intersection defined by two of the endpoints of the line segments. =#
288- function _find_collinear_intersection (:: Type{T} , a1, a2, b1, b2, a_ext, b_ext, no_intr_result) where T
326+ function _find_collinear_intersection (manifold :: M , :: Type{T} , a1, a2, b1, b2, a_ext, b_ext, no_intr_result) where {M <: Manifold , T}
289327 # Define default return for no intersection points
290328 line_orient, intr1, intr2 = no_intr_result
291329 # Determine collinear line overlaps
0 commit comments