@@ -33,19 +33,23 @@ GI.coordinates.(diff_poly)
3333```
3434"""
3535function 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... ,
3737) where {T<: AbstractFloat }
3838 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;
4040 exact = True (), kwargs... ,
4141 )
4242end
43+ # fallback definitions
44+ difference (geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs... ) where T = difference (FosterHormannClipping (Planar ()), geom_a, geom_b, T; target, kwargs... )
45+ # if manifold but no algorithm - assume FosterHormannClipping with provided manifold.
46+ 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... )
4347
4448#= The 'difference' function returns the difference of two polygons as a list of polygons.
4549The algorithm to determine the difference was adapted from "Efficient clipping of efficient
4650polygons," by Greiner and Hormann (1998). DOI: https://doi.org/10.1145/274363.274364 =#
4751function _difference (
48- :: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
52+ alg :: FosterHormannClipping , target :: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
4953 :: GI.PolygonTrait , poly_a,
5054 :: GI.PolygonTrait , poly_b;
5155 exact, kwargs...
@@ -54,11 +58,11 @@ function _difference(
5458 ext_a = GI. getexterior (poly_a)
5559 ext_b = GI. getexterior (poly_b)
5660 # 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)
61+ 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)
62+ polys = _trace_polynodes (alg, T, a_list, b_list, a_idx_list, _diff_step, poly_a, poly_b)
5963 # if no crossing points, determine if either poly is inside of the other
6064 if isempty (polys)
61- a_in_b, b_in_a = _find_non_cross_orientation (a_list, b_list, ext_a, ext_b; exact)
65+ a_in_b, b_in_a = _find_non_cross_orientation (alg . manifold, a_list, b_list, ext_a, ext_b; exact)
6266 # add case for if they polygons are the same (all intersection points!)
6367 # add a find_first check to find first non-inter poly!
6468 if b_in_a && ! a_in_b # b in a and can't be the same polygon
@@ -72,19 +76,19 @@ function _difference(
7276 remove_idx = falses (length (polys))
7377 # If the original polygons had holes, take that into account.
7478 if GI. nhole (poly_a) != 0
75- _add_holes_to_polys! (T, polys, GI. gethole (poly_a), remove_idx; exact)
79+ _add_holes_to_polys! (alg, T, polys, GI. gethole (poly_a), remove_idx; exact)
7680 end
7781 if GI. nhole (poly_b) != 0
7882 for hole in GI. gethole (poly_b)
7983 hole_poly = GI. Polygon (StaticArrays. SVector (hole))
80- new_polys = intersection (hole_poly, poly_a, T; target = GI. PolygonTrait)
84+ new_polys = intersection (alg, hole_poly, poly_a, T; target = GI. PolygonTrait)
8185 if length (new_polys) > 0
8286 append! (polys, new_polys)
8387 end
8488 end
8589 end
8690 # Remove unneeded collinear points on same edge
87- _remove_collinear_points! (polys, remove_idx, poly_a, poly_b)
91+ _remove_collinear_points! (alg, polys, remove_idx, poly_a, poly_b)
8892 return polys
8993end
9094
@@ -110,15 +114,15 @@ _diff_step(x, y) = (x ⊻ y) ? 1 : (-1)
110114#= Polygon with multipolygon difference - note that all intersection regions between
111115`poly_a` and any of the sub-polygons of `multipoly_b` are removed from `poly_a`. =#
112116function _difference (
113- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
117+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
114118 :: GI.PolygonTrait , poly_a,
115119 :: GI.MultiPolygonTrait , multipoly_b;
116120 kwargs... ,
117121) where T
118122 polys = [tuples (poly_a, T)]
119123 for poly_b in GI. getpolygon (multipoly_b)
120124 isempty (polys) && break
121- polys = mapreduce (p -> difference (p, poly_b; target), append!, polys)
125+ polys = mapreduce (p -> difference (alg, p, poly_b; target), append!, polys)
122126 end
123127 return polys
124128end
@@ -128,7 +132,7 @@ sub-polygons of `multipoly_a` and `poly_b` will be removed from the correspondin
128132sub-polygon. Unless specified with `fix_multipoly = nothing`, `multipolygon_a` will be
129133validated using the given (default is `UnionIntersectingPolygons()`) correction. =#
130134function _difference (
131- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
135+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
132136 :: GI.MultiPolygonTrait , multipoly_a,
133137 :: GI.PolygonTrait , poly_b;
134138 fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
@@ -139,7 +143,7 @@ function _difference(
139143 polys = Vector {_get_poly_type(T)} ()
140144 sizehint! (polys, GI. npolygon (multipoly_a))
141145 for poly_a in GI. getpolygon (multipoly_a)
142- append! (polys, difference (poly_a, poly_b; target))
146+ append! (polys, difference (alg, poly_a, poly_b; target))
143147 end
144148 return polys
145149end
@@ -150,7 +154,7 @@ corresponding sub-polygon of `multipoly_a`. Unless specified with `fix_multipoly
150154`multipolygon_a` will be validated using the given (default is `UnionIntersectingPolygons()`)
151155correction. =#
152156function _difference (
153- target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
157+ alg :: FosterHormannClipping , target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
154158 :: GI.MultiPolygonTrait , multipoly_a,
155159 :: GI.MultiPolygonTrait , multipoly_b;
156160 fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
@@ -165,26 +169,39 @@ function _difference(
165169 pieces of `multipolygon_a`` are removed, continue to take difference with new shape
166170 `polys` =#
167171 polys = if i == 1
168- difference (multipoly_a, poly_b; target, fix_multipoly)
172+ difference (alg, multipoly_a, poly_b; target, fix_multipoly)
169173 else
170- difference (GI. MultiPolygon (polys), poly_b; target, fix_multipoly)
174+ difference (alg, GI. MultiPolygon (polys), poly_b; target, fix_multipoly)
171175 end
172176 #= One multipoly_a has been completely covered (and thus removed) there is no need to
173177 continue taking the difference =#
174178 isempty (polys) && break
175179 end
176180 return polys
177181end
178-
182+ function _difference (
183+ alg:: FosterHormannClipping , :: TraitTarget{GI.MultiPolygonTrait} , :: Type{T} ,
184+ trait_a:: Union{GI.PolygonTrait, GI.MultiPolygonTrait} , polylike_a,
185+ trait_b:: Union{GI.PolygonTrait, GI.MultiPolygonTrait} , polylike_b;
186+ fix_multipoly = UnionIntersectingPolygons (), kwargs...
187+ ) where T
188+ polys = _difference (alg, TraitTarget (GI. PolygonTrait ()), T, trait_a, polylike_a, trait_b, polylike_b; kwargs... )
189+ if isnothing (fix_multipoly)
190+ return GI. MultiPolygon (polys)
191+ else
192+ return fix_multipoly (GI. MultiPolygon (polys))
193+ end
194+ end
179195# Many type and target combos aren't implemented
180196function _difference (
181- :: TraitTarget{Target} , :: Type{T} ,
197+ alg :: GeometryOpsCore.Algorithm , target :: TraitTarget{Target} , :: Type{T} ,
182198 trait_a:: GI.AbstractTrait , geom_a,
183199 trait_b:: GI.AbstractTrait , geom_b,
200+ kw...
184201) where {Target, T}
185202 @assert (
186203 false ,
187- " Difference between $trait_a and $trait_b with target $Target isn't implemented yet." ,
204+ " Difference between $trait_a and $trait_b with target $Target and algorithm $alg isn't implemented yet." ,
188205 )
189206 return nothing
190207end
0 commit comments