@@ -33,19 +33,24 @@ GI.coordinates.(diff_poly)
33
33
```
34
34
"""
35
35
function difference (
36
- geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs... ,
36
+ alg :: FosterHormannClipping , geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs... ,
37
37
) where {T<: AbstractFloat }
38
38
return _difference (
39
- TraitTarget (target), T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b;
39
+ alg, TraitTarget (target), T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b;
40
40
exact = True (), kwargs... ,
41
41
)
42
42
end
43
43
44
+ # fallback definitions
45
+ difference (geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs... ) where T = difference (FosterHormannClipping (Planar ()), geom_a, geom_b, T; target, kwargs... )
46
+ # if manifold but no algorithm - assume FosterHormannClipping with provided manifold.
47
+ difference (m:: Manifold , geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs... ) where T = difference (FosterHormannClipping (m), geom_a, geom_b, T; target, kwargs... )
48
+
44
49
#= The 'difference' function returns the difference of two polygons as a list of polygons.
45
50
The algorithm to determine the difference was adapted from "Efficient clipping of efficient
46
51
polygons," by Greiner and Hormann (1998). DOI: https://doi.org/10.1145/274363.274364 =#
47
52
function _difference (
48
- :: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
53
+ alg :: FosterHormannClipping , target :: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
49
54
:: GI.PolygonTrait , poly_a,
50
55
:: GI.PolygonTrait , poly_b;
51
56
exact, kwargs...
@@ -54,11 +59,11 @@ function _difference(
54
59
ext_a = GI. getexterior (poly_a)
55
60
ext_b = GI. getexterior (poly_b)
56
61
# Find the difference of the exterior of the polygons
57
- a_list, b_list, a_idx_list = _build_ab_list (T, ext_a, ext_b, _diff_delay_cross_f, _diff_delay_bounce_f; exact)
58
- polys = _trace_polynodes (T, a_list, b_list, a_idx_list, _diff_step, poly_a, poly_b)
62
+ a_list, b_list, a_idx_list = _build_ab_list (alg, T, ext_a, ext_b, _diff_delay_cross_f, _diff_delay_bounce_f; exact)
63
+ polys = _trace_polynodes (alg, T, a_list, b_list, a_idx_list, _diff_step, poly_a, poly_b)
59
64
# if no crossing points, determine if either poly is inside of the other
60
65
if isempty (polys)
61
- a_in_b, b_in_a = _find_non_cross_orientation (a_list, b_list, ext_a, ext_b; exact)
66
+ a_in_b, b_in_a = _find_non_cross_orientation (alg . manifold, a_list, b_list, ext_a, ext_b; exact)
62
67
# add case for if they polygons are the same (all intersection points!)
63
68
# add a find_first check to find first non-inter poly!
64
69
if b_in_a && ! a_in_b # b in a and can't be the same polygon
@@ -72,19 +77,19 @@ function _difference(
72
77
remove_idx = falses (length (polys))
73
78
# If the original polygons had holes, take that into account.
74
79
if GI. nhole (poly_a) != 0
75
- _add_holes_to_polys! (T, polys, GI. gethole (poly_a), remove_idx; exact)
80
+ _add_holes_to_polys! (alg, T, polys, GI. gethole (poly_a), remove_idx; exact)
76
81
end
77
82
if GI. nhole (poly_b) != 0
78
83
for hole in GI. gethole (poly_b)
79
84
hole_poly = GI. Polygon (StaticArrays. SVector (hole))
80
- new_polys = intersection (hole_poly, poly_a, T; target = GI. PolygonTrait)
85
+ new_polys = intersection (alg, hole_poly, poly_a, T; target = GI. PolygonTrait)
81
86
if length (new_polys) > 0
82
87
append! (polys, new_polys)
83
88
end
84
89
end
85
90
end
86
91
# Remove unneeded collinear points on same edge
87
- _remove_collinear_points! (polys, remove_idx, poly_a, poly_b)
92
+ _remove_collinear_points! (alg, polys, remove_idx, poly_a, poly_b)
88
93
return polys
89
94
end
90
95
@@ -110,15 +115,15 @@ _diff_step(x, y) = (x ⊻ y) ? 1 : (-1)
110
115
#= Polygon with multipolygon difference - note that all intersection regions between
111
116
`poly_a` and any of the sub-polygons of `multipoly_b` are removed from `poly_a`. =#
112
117
function _difference (
113
- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
118
+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
114
119
:: GI.PolygonTrait , poly_a,
115
120
:: GI.MultiPolygonTrait , multipoly_b;
116
121
kwargs... ,
117
122
) where T
118
123
polys = [tuples (poly_a, T)]
119
124
for poly_b in GI. getpolygon (multipoly_b)
120
125
isempty (polys) && break
121
- polys = mapreduce (p -> difference (p, poly_b; target), append!, polys)
126
+ polys = mapreduce (p -> difference (alg, p, poly_b; target), append!, polys)
122
127
end
123
128
return polys
124
129
end
@@ -128,7 +133,7 @@ sub-polygons of `multipoly_a` and `poly_b` will be removed from the correspondin
128
133
sub-polygon. Unless specified with `fix_multipoly = nothing`, `multipolygon_a` will be
129
134
validated using the given (default is `UnionIntersectingPolygons()`) correction. =#
130
135
function _difference (
131
- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
136
+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
132
137
:: GI.MultiPolygonTrait , multipoly_a,
133
138
:: GI.PolygonTrait , poly_b;
134
139
fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
@@ -139,7 +144,7 @@ function _difference(
139
144
polys = Vector {_get_poly_type(T)} ()
140
145
sizehint! (polys, GI. npolygon (multipoly_a))
141
146
for poly_a in GI. getpolygon (multipoly_a)
142
- append! (polys, difference (poly_a, poly_b; target))
147
+ append! (polys, difference (alg, poly_a, poly_b; target))
143
148
end
144
149
return polys
145
150
end
@@ -150,7 +155,7 @@ corresponding sub-polygon of `multipoly_a`. Unless specified with `fix_multipoly
150
155
`multipolygon_a` will be validated using the given (default is `UnionIntersectingPolygons()`)
151
156
correction. =#
152
157
function _difference (
153
- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
158
+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
154
159
:: GI.MultiPolygonTrait , multipoly_a,
155
160
:: GI.MultiPolygonTrait , multipoly_b;
156
161
fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
@@ -165,9 +170,9 @@ function _difference(
165
170
pieces of `multipolygon_a`` are removed, continue to take difference with new shape
166
171
`polys` =#
167
172
polys = if i == 1
168
- difference (multipoly_a, poly_b; target, fix_multipoly)
173
+ difference (alg, multipoly_a, poly_b; target, fix_multipoly)
169
174
else
170
- difference (GI. MultiPolygon (polys), poly_b; target, fix_multipoly)
175
+ difference (alg, GI. MultiPolygon (polys), poly_b; target, fix_multipoly)
171
176
end
172
177
#= One multipoly_a has been completely covered (and thus removed) there is no need to
173
178
continue taking the difference =#
@@ -176,15 +181,30 @@ function _difference(
176
181
return polys
177
182
end
178
183
184
+ function _difference (
185
+ alg:: FosterHormannClipping , :: TraitTarget{GI.MultiPolygonTrait} , :: Type{T} ,
186
+ trait_a:: Union{GI.PolygonTrait, GI.MultiPolygonTrait} , polylike_a,
187
+ trait_b:: Union{GI.PolygonTrait, GI.MultiPolygonTrait} , polylike_b;
188
+ fix_multipoly = UnionIntersectingPolygons (), kwargs...
189
+ ) where T
190
+ polys = _difference (alg, TraitTarget (GI. PolygonTrait ()), T, trait_a, polylike_a, trait_b, polylike_b; kwargs... )
191
+ if isnothing (fix_multipoly)
192
+ return GI. MultiPolygon (polys)
193
+ else
194
+ return fix_multipoly (GI. MultiPolygon (polys))
195
+ end
196
+ end
197
+
179
198
# Many type and target combos aren't implemented
180
199
function _difference (
181
- :: TraitTarget{Target} , :: Type{T} ,
200
+ alg :: GeometryOpsCore.Algorithm , target :: TraitTarget{Target} , :: Type{T} ,
182
201
trait_a:: GI.AbstractTrait , geom_a,
183
202
trait_b:: GI.AbstractTrait , geom_b,
203
+ kw...
184
204
) where {Target, T}
185
205
@assert (
186
206
false ,
187
- " Difference between $trait_a and $trait_b with target $Target isn't implemented yet." ,
207
+ " Difference between $trait_a and $trait_b with target $Target and algorithm $alg isn't implemented yet." ,
188
208
)
189
209
return nothing
190
210
end
0 commit comments