@@ -40,28 +40,41 @@ GI.coordinates.(inter_points)
40
40
```
41
41
"""
42
42
function 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...
44
44
) where {T<: AbstractFloat }
45
45
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;
47
47
exact = True (), kwargs... ,
48
48
)
49
49
end
50
50
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
+
51
64
# Curve-Curve Intersections with target Point
52
65
_intersection (
53
- :: TraitTarget{GI.PointTrait} , :: Type{T} ,
66
+ alg :: FosterHormannClipping , :: TraitTarget{GI.PointTrait} , :: Type{T} ,
54
67
trait_a:: Union{GI.LineTrait, GI.LineStringTrait, GI.LinearRingTrait} , geom_a,
55
68
trait_b:: Union{GI.LineTrait, GI.LineStringTrait, GI.LinearRingTrait} , geom_b;
56
69
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)
58
71
59
72
#= Polygon-Polygon Intersections with target Polygon
60
73
The algorithm to determine the intersection was adapted from "Efficient clipping
61
74
of efficient polygons," by Greiner and Hormann (1998).
62
75
DOI: https://doi.org/10.1145/274363.274364 =#
63
76
function _intersection (
64
- :: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
77
+ alg :: FosterHormannClipping , :: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
65
78
:: GI.PolygonTrait , poly_a,
66
79
:: GI.PolygonTrait , poly_b;
67
80
exact, kwargs... ,
@@ -70,10 +83,10 @@ function _intersection(
70
83
ext_a = GI. getexterior (poly_a)
71
84
ext_b = GI. getexterior (poly_b)
72
85
# 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)
75
88
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)
77
90
if a_in_b
78
91
push! (polys, GI. Polygon ([tuples (ext_a)]))
79
92
elseif b_in_a
@@ -84,10 +97,10 @@ function _intersection(
84
97
# If the original polygons had holes, take that into account.
85
98
if GI. nhole (poly_a) != 0 || GI. nhole (poly_b) != 0
86
99
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)
88
101
end
89
102
# 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)
91
104
return polys
92
105
end
93
106
@@ -112,7 +125,7 @@ _inter_step(x, _) = x ? 1 : (-1)
112
125
Unless specified with `fix_multipoly = nothing`, `multipolygon_b` will be validated using
113
126
the given (default is `UnionIntersectingPolygons()`) correction. =#
114
127
function _intersection (
115
- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
128
+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
116
129
:: GI.PolygonTrait , poly_a,
117
130
:: GI.MultiPolygonTrait , multipoly_b;
118
131
fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
@@ -122,7 +135,7 @@ function _intersection(
122
135
end
123
136
polys = Vector {_get_poly_type(T)} ()
124
137
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))
126
139
end
127
140
return polys
128
141
end
@@ -131,19 +144,19 @@ end
131
144
polygon with the multipolygon and thus simply switches the order of operations and calls the
132
145
above method. =#
133
146
_intersection (
134
- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
147
+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
135
148
:: GI.MultiPolygonTrait , multipoly_a,
136
149
:: GI.PolygonTrait , poly_b;
137
150
kwargs... ,
138
- ) where T = intersection (poly_b, multipoly_a; target , kwargs... )
151
+ ) where T = intersection (alg, poly_b, multipoly_a; target , kwargs... )
139
152
140
153
#= Multipolygon with multipolygon intersection - note that all intersection regions between
141
154
any sub-polygons of `multipoly_a` and any of the sub-polygons of `multipoly_b` are counted
142
155
as intersection polygons. Unless specified with `fix_multipoly = nothing`, both
143
156
`multipolygon_a` and `multipolygon_b` will be validated using the given (default is
144
157
`UnionIntersectingPolygons()`) correction. =#
145
158
function _intersection (
146
- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
159
+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
147
160
:: GI.MultiPolygonTrait , multipoly_a,
148
161
:: GI.MultiPolygonTrait , multipoly_b;
149
162
fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
@@ -155,21 +168,37 @@ function _intersection(
155
168
end
156
169
polys = Vector {_get_poly_type(T)} ()
157
170
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))
159
172
end
160
173
return polys
161
174
end
162
175
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
+
163
192
# Many type and target combos aren't implemented
164
193
function _intersection (
165
- :: TraitTarget{Target} , :: Type{T} ,
194
+ alg :: GeometryOpsCore.Algorithm , target :: TraitTarget{Target} , :: Type{T} ,
166
195
trait_a:: GI.AbstractTrait , geom_a,
167
196
trait_b:: GI.AbstractTrait , geom_b;
168
197
kwargs... ,
169
198
) where {Target, T}
170
199
@assert (
171
200
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." ,
173
202
)
174
203
return nothing
175
204
end
@@ -193,13 +222,19 @@ inter_points = GO.intersection_points(line1, line2)
193
222
1-element Vector{Tuple{Float64, Float64}}:
194
223
(125.58375366067548, -14.83572303404496)
195
224
"""
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
198
233
199
234
200
235
#= Calculates the list of intersection points between two geometries, including line
201
236
segments, 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}
203
238
# Initialize an empty list of points
204
239
result = Tuple{T, T}[]
205
240
# 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 (
243
278
that point.
244
279
245
280
Calculation 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}
247
282
# Default answer for no intersection
248
283
line_orient = line_out
249
284
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
266
301
# Determine intersection type and intersection point(s)
267
302
if a1_orient == a2_orient == b1_orient == b2_orient == 0
268
303
# 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)
270
305
elseif a1_orient == 0 || a2_orient == 0 || b1_orient == 0 || b2_orient == 0
271
306
# Intersection is a hinge if the intersection point is an endpoint
272
307
line_orient = line_hinge
@@ -279,13 +314,16 @@ function _intersection_point(::Type{T}, (a1, a2)::Edge, (b1, b2)::Edge; exact) w
279
314
return line_orient, intr1, intr2
280
315
end
281
316
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
+
282
320
#= If lines defined by (a1, a2) and (b1, b2) are collinear, find endpoints of overlapping
283
321
region if they exist. This could result in three possibilities. First, there could be no
284
322
overlapping region, in which case, the default 'no_intr_result' intersection information is
285
323
returned. Second, the two regions could just meet at one shared endpoint, in which case it
286
324
is a hinge intersection with one intersection point. Otherwise, it is a overlapping
287
325
intersection 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}
289
327
# Define default return for no intersection points
290
328
line_orient, intr1, intr2 = no_intr_result
291
329
# Determine collinear line overlaps
0 commit comments