Skip to content

Commit 60eabb9

Browse files
committed
Fix touches for multi geoms
Only one of the geoms in g2 MUST touch the geom in g1, all others MUST be disjoint or touching. This could potentially be accelerated by building an STRtree if the query width is long enough, or we may also need some tree interface / preparation here. E.g. Canada has a lot of islands that a tree approach could get rid of.
1 parent 18c4bbc commit 60eabb9

File tree

1 file changed

+44
-6
lines changed

1 file changed

+44
-6
lines changed

src/methods/geom_relations/touches.jl

+44-6
Original file line numberDiff line numberDiff line change
@@ -225,19 +225,49 @@ _touches(
225225

226226
# # Geometries touch multi-geometry/geometry collections
227227

228-
#= Geometry touch a multi-geometry or a collection if the geometry touches at
229-
least one of the elements of the collection. =#
228+
#=
229+
230+
A geometry touches a multi-geometry or a collection if the geometry touches at
231+
least one of the elements of the collection.
232+
233+
This is a bit tricky to implement - we have to actually check every geometry,
234+
and make sure that each geom is either disjoint or touching.
235+
236+
Problem here is that we would end up doing double the work.
237+
238+
Either you check disjointness first, and then check touches - in which case
239+
you have already done the work for the touches check, but can't take advantage of it.
240+
241+
Or you check touches first, and if that is false, you check disjointness. But if touches failed,
242+
and you don't know _why_ it was false (disjoint or contained / intersecting), you have to iterate
243+
over every point twice -- again!
244+
245+
246+
At this point we actually need a fast return function...or some more detail returned from the process functions.
247+
248+
That's a project for later though. Right now we need to get this correct, so I'm going to do the dumb thing.
249+
250+
=#
230251
function _touches(
231252
::Union{GI.PointTrait, GI.AbstractCurveTrait, GI.PolygonTrait}, g1,
232253
::Union{
233254
GI.MultiPointTrait, GI.AbstractMultiCurveTrait,
234255
GI.MultiPolygonTrait, GI.GeometryCollectionTrait,
235256
}, g2,
236257
)
258+
has_touched = false
237259
for sub_g2 in GI.getgeom(g2)
238-
!touches(g1, sub_g2) && return false
260+
if touches(g1, sub_g2)
261+
has_touched = true
262+
else
263+
# if not touching, they are either intersecting or disjoint
264+
# if disjoint, then we can continue
265+
# else, we can short circuit, since the geoms are not touching and not disjoint
266+
# i.e. they are intersecting
267+
disjoint(g1, sub_g2) || return false
268+
end
239269
end
240-
return true
270+
return has_touched
241271
end
242272

243273
# # Multi-geometry/geometry collections cross geometries
@@ -251,8 +281,16 @@ function _touches(
251281
}, g1,
252282
::GI.AbstractGeometryTrait, g2,
253283
)
284+
has_touched = false
254285
for sub_g1 in GI.getgeom(g1)
255-
!touches(sub_g1, g2) && return false
286+
if touches(sub_g1, g2)
287+
has_touched = true
288+
else
289+
# if not touching, they are either intersecting or disjoint
290+
# if disjoint, then we can continue
291+
# else, we can short circuit, since the geoms are not touching and not disjoint
292+
disjoint(sub_g1, g2) || return false
293+
end
256294
end
257-
return true
295+
return has_touched
258296
end

0 commit comments

Comments
 (0)