Skip to content

Commit 7677bf9

Browse files
committed
Merge branch 'pr-340' into claude/address-pr-340-comments-011CUwZdvq8ujMp8sR2ykC9s
2 parents 4e53492 + c187e37 commit 7677bf9

File tree

5 files changed

+63
-7
lines changed

5 files changed

+63
-7
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/distance.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ end
192192

193193
# Returns the Euclidean distance between two points.
194194
Base.@propagate_inbounds _euclid_distance(::Type{T}, p1, p2) where T =
195-
sqrt(_squared_euclid_distance(T, p1, p2))
195+
hypot(T(GI.x(p2)) - T(GI.x(p1)), T(GI.y(p2)) - T(GI.y(p1)))
196196

197197
# Returns the square of the euclidean distance between two points
198198
Base.@propagate_inbounds _squared_euclid_distance(::Type{T}, p1, p2) where T =

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,

src/transformations/tuples.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ geometries wrapping `Tuple` points.
1010
1111
# Keywords
1212
13-
$APPLY_KEYWORDS
13+
- `threaded`: `true` or `false`. Whether to use multithreading. Defaults to `false`.
14+
- `crs`: The CRS to attach to geometries. Defaults to `nothing`.
15+
- `calc_extent`: `true` or `false`. Whether to calculate the extent. Defaults to `true`.
1416
"""
15-
function tuples(geom, ::Type{T} = Float64; kw...) where T
17+
function tuples(geom, ::Type{T} = Float64; calc_extent = true, kw...) where T
1618
if _is3d(geom)
17-
return apply(PointTrait(), geom; kw...) do p
19+
return apply(PointTrait(), geom; calc_extent, kw...) do p
1820
(T(GI.x(p)), T(GI.y(p)), T(GI.z(p)))
1921
end
2022
else
21-
return apply(PointTrait(), geom; kw...) do p
23+
return apply(PointTrait(), geom; calc_extent, kw...) do p
2224
(T(GI.x(p)), T(GI.y(p)))
2325
end
2426
end

src/utils/NaturalIndexing.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,11 @@ GI.isgeometry(::Type{<: NaturallyIndexedRing}) = true
237237
GI.geomtrait(::NaturallyIndexedRing) = GI.LinearRingTrait()
238238

239239
function prepare_naturally(geom)
240-
return GO.apply(GI.PolygonTrait(), geom) do poly
241-
return GI.Polygon([GI.convert(NaturallyIndexedRing, GI.LinearRingTrait(), ring) for ring in GI.getring(poly)])
240+
crs = GI.crs(geom)
241+
return GO.apply(GI.PolygonTrait(), geom; calc_extent = true) do poly
242+
rings = [GI.convert(NaturallyIndexedRing, GI.LinearRingTrait(), ring) for ring in GI.getring(poly)]
243+
extent = mapreduce(GI.extent, Extents.union, rings)
244+
return GI.Polygon(rings; extent, crs)
242245
end
243246
end
244247

0 commit comments

Comments
 (0)