@@ -10,13 +10,19 @@ Enum for the orientation of a line with respect to a curve. A line can be
10
10
@enum LineOrientation line_cross= 1 line_hinge= 2 line_over= 3 line_out= 4
11
11
12
12
"""
13
- intersection(geom_a, geom_b, [T::Type]; target::Type)
13
+ intersection(geom_a, geom_b, [T::Type]; target::Type, fix_multipoly = UnionIntersectingPolygons() )
14
14
15
15
Return the intersection between two geometries as a list of geometries. Return an empty list
16
16
if none are found. The type of the list will be constrained as much as possible given the
17
17
input geometries. Furthermore, the user can provide a `target` type as a keyword argument and
18
18
a list of target geometries found in the intersection will be returned. The user can also
19
- provide a float type that they would like the points of returned geometries to be.
19
+ provide a float type that they would like the points of returned geometries to be. If the
20
+ user is taking a intersection involving one or more multipolygons, and the multipolygon
21
+ might be comprised of polygons that intersect, if `fix_multipoly` is set to an
22
+ `IntersectingPolygons` correction (the default is `UnionIntersectingPolygons()`), then the
23
+ needed multipolygons will be fixed to be valid before performing the intersection to ensure
24
+ a correct answer. Only set `fix_multipoly` to nothing if you know that the multipolygons are
25
+ valid, as it will avoid unneeded computation.
20
26
21
27
## Example
22
28
@@ -34,16 +40,17 @@ GI.coordinates.(inter_points)
34
40
```
35
41
"""
36
42
function intersection (
37
- geom_a, geom_b, :: Type{T} = Float64; target= nothing ,
43
+ geom_a, geom_b, :: Type{T} = Float64; target= nothing , kwargs ... ,
38
44
) where {T<: AbstractFloat }
39
- return _intersection (TraitTarget (target), T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b)
45
+ return _intersection (TraitTarget (target), T, GI. trait (geom_a), geom_a, GI. trait (geom_b), geom_b; kwargs ... )
40
46
end
41
47
42
48
# Curve-Curve Intersections with target Point
43
49
_intersection (
44
50
:: TraitTarget{GI.PointTrait} , :: Type{T} ,
45
51
trait_a:: Union{GI.LineTrait, GI.LineStringTrait, GI.LinearRingTrait} , geom_a,
46
- trait_b:: Union{GI.LineTrait, GI.LineStringTrait, GI.LinearRingTrait} , geom_b,
52
+ trait_b:: Union{GI.LineTrait, GI.LineStringTrait, GI.LinearRingTrait} , geom_b;
53
+ kwargs... ,
47
54
) where T = _intersection_points (T, trait_a, geom_a, trait_b, geom_b)
48
55
49
56
#= Polygon-Polygon Intersections with target Polygon
@@ -53,7 +60,8 @@ DOI: https://doi.org/10.1145/274363.274364 =#
53
60
function _intersection (
54
61
:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
55
62
:: GI.PolygonTrait , poly_a,
56
- :: GI.PolygonTrait , poly_b,
63
+ :: GI.PolygonTrait , poly_b;
64
+ kwargs... ,
57
65
) where {T}
58
66
# First we get the exteriors of 'poly_a' and 'poly_b'
59
67
ext_a = GI. getexterior (poly_a)
@@ -98,11 +106,65 @@ _inter_delay_bounce_f(x, _) = x
98
106
point, else step backwards where x is the entry/exit status. =#
99
107
_inter_step (x, _) = x ? 1 : (- 1 )
100
108
109
+ #= Polygon with multipolygon intersection - note that all intersection regions between
110
+ `poly_a` and any of the sub-polygons of `multipoly_b` are counted as intersection polygons.
111
+ Unless specified with `fix_multipoly = nothing`, `multipolygon_b` will be validated using
112
+ the given (default is `UnionIntersectingPolygons()`) correction. =#
113
+ function _intersection (
114
+ target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
115
+ :: GI.PolygonTrait , poly_a,
116
+ :: GI.MultiPolygonTrait , multipoly_b;
117
+ fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
118
+ ) where T
119
+ if ! isnothing (fix_multipoly) # Fix multipoly_b to prevent duplicated intersection regions
120
+ multipoly_b = fix_multipoly (multipoly_b)
121
+ end
122
+ polys = Vector {_get_poly_type(T)} ()
123
+ for poly_b in GI. getpolygon (multipoly_b)
124
+ append! (polys, intersection (poly_a, poly_b; target))
125
+ end
126
+ return polys
127
+ end
128
+
129
+ #= Multipolygon with polygon intersection is equivalent to taking the intersection of the
130
+ poylgon with the multipolygon and thus simply switches the order of operations and calls the
131
+ above method. =#
132
+ _intersection (
133
+ target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
134
+ :: GI.MultiPolygonTrait , multipoly_a,
135
+ :: GI.PolygonTrait , poly_b;
136
+ kwargs... ,
137
+ ) where T = intersection (poly_b, multipoly_a; target , kwargs... )
138
+
139
+ #= Multipolygon with multipolygon intersection - note that all intersection regions between
140
+ any sub-polygons of `multipoly_a` and any of the sub-polygons of `multipoly_b` are counted
141
+ as intersection polygons. Unless specified with `fix_multipoly = nothing`, both
142
+ `multipolygon_a` and `multipolygon_b` will be validated using the given (default is
143
+ `UnionIntersectingPolygons()`) correction. =#
144
+ function _intersection (
145
+ target:: TraitTarget{GI.PolygonTrait} , :: Type{T} ,
146
+ :: GI.MultiPolygonTrait , multipoly_a,
147
+ :: GI.MultiPolygonTrait , multipoly_b;
148
+ fix_multipoly = UnionIntersectingPolygons (), kwargs... ,
149
+ ) where T
150
+ if ! isnothing (fix_multipoly) # Fix both multipolygons to prevent duplicated regions
151
+ multipoly_a = fix_multipoly (multipoly_a)
152
+ multipoly_b = fix_multipoly (multipoly_b)
153
+ fix_multipoly = nothing
154
+ end
155
+ polys = Vector {_get_poly_type(T)} ()
156
+ for poly_a in GI. getpolygon (multipoly_a)
157
+ append! (polys, intersection (poly_a, multipoly_b; target, fix_multipoly))
158
+ end
159
+ return polys
160
+ end
161
+
101
162
# Many type and target combos aren't implemented
102
163
function _intersection (
103
164
:: TraitTarget{Target} , :: Type{T} ,
104
165
trait_a:: GI.AbstractTrait , geom_a,
105
- trait_b:: GI.AbstractTrait , geom_b,
166
+ trait_b:: GI.AbstractTrait , geom_b;
167
+ kwargs... ,
106
168
) where {Target, T}
107
169
@assert (
108
170
false ,
0 commit comments