Skip to content

Commit

Permalink
Refactor winding number
Browse files Browse the repository at this point in the history
  • Loading branch information
juliohm committed Dec 26, 2023
1 parent 079848b commit 8919b3f
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 50 deletions.
25 changes: 14 additions & 11 deletions src/Meshes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,11 @@ include("neighborsearch.jl")
include("predicates.jl")

# operations
include("winding.jl")
include("sideof.jl")
include("orientation.jl")
include("measures.jl")
include("boundary.jl")
include("orientation.jl")
include("merging.jl")
include("clipping.jl")
include("intersections.jl")
Expand Down Expand Up @@ -199,7 +200,6 @@ export
vertex,
vertices,
nvertices,
windingnumber,
rings,
segments,
angles,
Expand Down Expand Up @@ -372,6 +372,9 @@ export
iscollinear,
iscoplanar,

# winding number
winding,

# sideof
sideof,
SideType,
Expand All @@ -381,15 +384,6 @@ export
LEFT,
RIGHT,

# measures
measure,
area,
volume,
perimeter,

# boundary
boundary,

# orientation
OrientationMethod,
WindingOrientation,
Expand All @@ -399,6 +393,15 @@ export
CW,
CCW,

# measures
measure,
area,
volume,
perimeter,

# boundary
boundary,

# clipping
ClippingMethod,
SutherlandHodgman,
Expand Down
2 changes: 1 addition & 1 deletion src/orientation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function orientation(r::Ring{2,T}, ::WindingOrientation) where {T}
# pick any segment
x1, x2 = r.vertices[1:2]
= center(Segment(x1, x2))
w = T(2π) * windingnumber(x̄, r) - (x1, x̄, x2)
w = T(2π) * winding(x̄, r) - (x1, x̄, x2)
isapprox(w, T(π), atol=atol(T)) ? CCW : CW
end

Expand Down
7 changes: 0 additions & 7 deletions src/polytopes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,6 @@ Return the outer and inner rings of the polygon.
"""
function rings end

"""
windingnumber(point, polygon)
Winding number of `point` with respect to the `polygon`.
"""
function windingnumber end

# implementations of Polygon
include("polytopes/ngon.jl")
include("polytopes/polyarea.jl")
Expand Down
2 changes: 0 additions & 2 deletions src/polytopes/polyarea.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ centroid(p::PolyArea) = centroid(first(p.rings))

rings(p::PolyArea) = p.rings

windingnumber(point::Point, p::PolyArea) = windingnumber(point, first(p.rings))

function Base.unique!(p::PolyArea)
foreach(unique!, p.rings)
inds = findall(r -> nvertices(r) 2, p.rings)
Expand Down
21 changes: 0 additions & 21 deletions src/polytopes/ring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,27 +55,6 @@ function Random.rand(rng::Random.AbstractRNG, ::Random.SamplerType{<:Ring{Dim,T}
Ring(v)
end

"""
windingnumber(point, ring)
Winding number of `point` with respect to the `ring`.
The winding number is the total number of times that
the ring travels counterclockwise around the point.
See https://en.wikipedia.org/wiki/Winding_number.
## References
* Balbes, R. and Siegel, J. 1990. [A robust method for calculating
the simplicity and orientation of planar polygons]
(https://www.sciencedirect.com/science/article/abs/pii/0167839691900198)
"""
function windingnumber(p::Point{2,T}, r::Ring{2,T}) where {T}
v = r.vertices
n = length(v)
= sum((v[i], p, v[i + 1]) for i in 1:n)
/ T(2π)
end

"""
innerangles(ring)
Expand Down
2 changes: 1 addition & 1 deletion src/sideof.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Determines on which side the `point` is in relation to the `ring`.
Possible results are `IN` or `OUT` the `ring`.
"""
function sideof(point::Point{2,T}, ring::Ring{2,T}) where {T}
w = windingnumber(point, ring)
w = winding(point, ring)
ifelse(isapprox(w, zero(T), atol=atol(T)), OUT, IN)
end

Expand Down
21 changes: 21 additions & 0 deletions src/winding.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
winding(points, object)
Generalized winding number of `points` with respect to the geometric `object`.
## References
* Barill et al. 2018. [Fast winding numbers for soups and clouds]
(https://dl.acm.org/doi/10.1145/3197517.3201337)
"""
function winding end

function winding(p::Point{2,T}, r::Ring{2,T}) where {T}
v = vertices(r)
n = length(v)
sum((v[i], p, v[i + 1]) for i in 1:n) / T(2π)
end
7 changes: 0 additions & 7 deletions test/polytopes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,6 @@
@test angles(c) [-atan(2), -π / 2, +π / 2, -π / 2, -π / 2, -- atan(2))]
@test innerangles(c) [atan(2), π / 2, 3π / 2, π / 2, π / 2, π - atan(2)]

c = Ring(P2[(0, 0), (1, 0), (1, 1), (0, 1)])
@test windingnumber(P2(0.5, 0.5), c) 1
@test windingnumber(P2(0.5, 0.5), reverse(c)) -1
c = Ring(P2[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 1)])
@test windingnumber(P2(0.5, 0.5), c) 2
@test windingnumber(P2(0.5, 0.5), reverse(c)) -2

c1 = Ring(P2[(0, 0), (1, 0), (1, 1), (0, 1)])
c2 = Ring(vertices(c1))
@test c1 == c2
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ testfiles = [
"neighborhoods.jl",
"neighborsearch.jl",
"predicates.jl",
"winding.jl",
"sideof.jl",
"orientation.jl",
"merging.jl",
Expand Down
8 changes: 8 additions & 0 deletions test/winding.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@testset "winding" begin
c = Ring(P2[(0, 0), (1, 0), (1, 1), (0, 1)])
@test winding(P2(0.5, 0.5), c) 1
@test winding(P2(0.5, 0.5), reverse(c)) -1
c = Ring(P2[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 1)])
@test winding(P2(0.5, 0.5), c) 2
@test winding(P2(0.5, 0.5), reverse(c)) -2
end

0 comments on commit 8919b3f

Please sign in to comment.