Skip to content

Commit 605f785

Browse files
committed
Experimental implementation of spatial tree acceleration for point in polygon
This still has one Core.Box that I cant seem to get rid of...
1 parent 1d71304 commit 605f785

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

src/GeometryOps.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ include("utils/UnitSpherical/UnitSpherical.jl")
4848

4949
# Load utility modules in
5050
using .LoopStateMachine, .SpatialTreeInterface, .UnitSpherical
51+
const LSM = LoopStateMachine
52+
const STI = SpatialTreeInterface
5153

5254
include("utils/NaturalIndexing.jl")
5355
using .NaturalIndexing

src/methods/geom_relations/geom_geom_processors.jl

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ passes through an odd number of edges, it is within the curve, else outside of
492492
of the curve if it didn't return 'on'.
493493
See paper for more information on cases denoted in comments.
494494
=#
495+
495496
function _point_filled_curve_orientation(
496497
::Planar, point, curve;
497498
in::T = point_in, on::T = point_on, out::T = point_out, exact,
@@ -527,6 +528,54 @@ function _point_filled_curve_orientation(
527528
end
528529
return iseven(k) ? out : in
529530
end
531+
532+
# Specialized implementation for NaturallyIndexedRing
533+
# This relies on multidispatch.
534+
# TODO: remove?
535+
function _point_filled_curve_orientation(
536+
::Planar, point, curve::NaturalIndexing.NaturallyIndexedRing;
537+
in::T = point_in, on::T = point_on, out::T = point_out, exact,
538+
) where {T}
539+
x, y = GI.x(GI.PointTrait(), point), GI.y(GI.PointTrait(), point)
540+
k::Int = 0 # counter for ray crossings
541+
542+
tree = curve.index
543+
544+
function per_edge_function(i)
545+
p_start = _tuple_point(GI.getpoint(curve, i))
546+
p_end = _tuple_point(GI.getpoint(curve, i + 1))
547+
v1 = GI.y(p_start) - y
548+
v2 = GI.y(p_end) - y
549+
if !((v1 < 0 && v2 < 0) || (v1 > 0 && v2 > 0)) # if not cases 11 or 26
550+
u1, u2 = GI.x(p_start) - x, GI.x(p_end) - x
551+
f = Predicates.orient(p_start, p_end, (x, y); exact)
552+
if v2 > 0 && v1 0 # Case 3, 9, 16, 21, 13, or 24
553+
f == 0 && return LSM.Action{T}(:full_return, on) # Case 16 or 21
554+
f > 0 && (k += 1) # Case 3 or 9
555+
elseif v1 > 0 && v2 0 # Case 4, 10, 19, 20, 12, or 25
556+
f == 0 && return LSM.Action{T}(:full_return, on) # Case 19 or 20
557+
f < 0 && (k += 1) # Case 4 or 10
558+
elseif v2 == 0 && v1 < 0 # Case 7, 14, or 17
559+
f == 0 && return LSM.Action{T}(:full_return, on) # Case 17
560+
elseif v1 == 0 && v2 < 0 # Case 8, 15, or 18
561+
f == 0 && return LSM.Action{T}(:full_return, on) # Case 18
562+
elseif v1 == 0 && v2 == 0 # Case 1, 2, 5, 6, 22, or 23
563+
u2 0 && u1 0 && return LSM.Action{T}(:full_return, on) # Case 1
564+
u1 0 && u2 0 && return LSM.Action{T}(:full_return, on) # Case 2
565+
end
566+
return LSM.Action(:continue, on)
567+
end
568+
p_start = p_end
569+
end
570+
571+
result = SpatialTreeInterface.depth_first_search(per_edge_function,extent -> extent.Y[1] <= y <= extent.Y[2], tree)
572+
573+
if result isa LoopStateMachine.Action
574+
return result.x
575+
else
576+
return iseven(k) ? out : in
577+
end
578+
end
530579
_point_filled_curve_orientation(
531580
point, curve;
532581
in::T = point_in, on::T = point_on, out::T = point_out, exact,

0 commit comments

Comments
 (0)