@@ -126,3 +126,90 @@ function _point_in_extent(p, extent::Extents.Extent)
126
126
(x1, x2), (y1, y2) = extent. X, extent. Y
127
127
return x1 ≤ GI. x (p) ≤ x2 && y1 ≤ GI. y (p) ≤ y2
128
128
end
129
+
130
+ #=
131
+ # `eachedge`, `to_edgelist`
132
+
133
+ These functions are used to decompose geometries into lists of edges.
134
+ Currently they only work on linear rings.
135
+ =#
136
+
137
+ """
138
+ eachedge(geom, [::Type{T}])
139
+
140
+ Decompose a geometry into a list of edges.
141
+ Currently only works for LineString and LinearRing.
142
+
143
+ Returns some iterator, which yields tuples of points. Each tuple is an edge.
144
+
145
+ It goes `(p1, p2), (p2, p3), (p3, p4), ...` etc.
146
+ """
147
+ eachedge (geom) = eachedge (GI. trait (geom), geom, Float64)
148
+
149
+ function eachedge (geom, :: Type{T} ) where T
150
+ eachedge (GI. trait (geom), geom, T)
151
+ end
152
+
153
+ # implementation for LineString and LinearRing
154
+ function eachedge (trait:: GI.AbstractCurveTrait , geom, :: Type{T} ) where T
155
+ return (_tuple_point .((GI. getpoint (geom, i), GI. getpoint (geom, i+ 1 )), T) for i in 1 : GI. npoint (geom)- 1 )
156
+ end
157
+
158
+ # implementation for Polygon, MultiPolygon, MultiLineString, GeometryCollection
159
+ function eachedge (trait:: GI.AbstractGeometryTrait , geom, :: Type{T} ) where T
160
+ return Iterators. flatten ((eachedge (r, T) for r in flatten (GI. AbstractCurveTrait, geom)))
161
+ end
162
+
163
+ function eachedge (trait:: GI.PointTrait , geom, :: Type{T} ) where T
164
+ return ArgumentError (" Can't get edges from points, $geom was a PointTrait." )
165
+ end
166
+
167
+ function eachedge (trait:: GI.MultiPointTrait , geom, :: Type{T} ) where T
168
+ return ArgumentError (" Can't get edges from MultiPoint, $geom was a MultiPointTrait." )
169
+ end
170
+
171
+ """
172
+ to_edgelist(geom, [::Type{T}])
173
+
174
+ Convert a geometry into a vector of `GI.Line` objects with attached extents.
175
+ """
176
+ to_edgelist (geom, :: Type{T} ) where T =
177
+ [_lineedge (ps, T) for ps in eachedge (geom, T)]
178
+ function to_edgelist (ext:: E , geom, :: Type{T} ) where {E<: Extents.Extent ,T}
179
+ edges_in = eachedge (geom, T)
180
+ l1 = _lineedge (first (edges_in), T)
181
+ edges_out = typeof (l1)[]
182
+ indices = Int[]
183
+ for (i, ps) in enumerate (edges_in)
184
+ l = _lineedge (ps, T)
185
+ if Extents. intersects (ext, GI. extent (l))
186
+ push! (edges_out, l)
187
+ push! (indices, i)
188
+ end
189
+ end
190
+ return edges_out, indices
191
+ end
192
+
193
+ function _lineedge (ps:: Tuple , :: Type{T} ) where T
194
+ l = GI. Line (SVector {2,NTuple{2, T}} (ps)) # TODO : make this flexible in dimension
195
+ e = GI. extent (l)
196
+ return GI. Line (l. geom; extent= e)
197
+ end
198
+
199
+ function lazy_edgelist (geom, :: Type{T} ) where T
200
+ (_lineedge (ps, T) for ps in eachedge (geom, T))
201
+ end
202
+
203
+ function edge_extents (geom)
204
+ return [begin
205
+ Extents. Extent (X= extrema (GI. x, edge), Y= extrema (GI. y, edge))
206
+ end
207
+ for edge in eachedge (geom, Float64)]
208
+ end
209
+
210
+ function lazy_edge_extents (geom)
211
+ return (begin
212
+ Extents. Extent (X= extrema (GI. x, edge), Y= extrema (GI. y, edge))
213
+ end
214
+ for edge in eachedge (geom, Float64))
215
+ end
0 commit comments