Skip to content

Commit

Permalink
Add Weiler-Atherton clipping algorithm
Browse files Browse the repository at this point in the history
Changes the default clipping algorithm for intersections.
  • Loading branch information
Nemanja Jovanovic committed Sep 1, 2024
1 parent 7761035 commit 42c354f
Show file tree
Hide file tree
Showing 10 changed files with 647 additions and 21 deletions.
24 changes: 24 additions & 0 deletions docs/src/algorithms/clipping.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,30 @@ other = Box((0,1), (3,7))
# clipped polygon
clipped = clip(poly, other, SutherlandHodgmanClipping())
viz(poly)
viz!(other, color = :black, alpha = 0.2)
viz!(boundary(clipped), color = :red, segmentsize = 3)
Mke.current_figure()
```

## Weiler-Atherton

```@docs
WeilerAthertonClipping
```

```@example clipping
# polygon to clip
outer = Ring((8, 0), (4, 8), (2, 8), (-2, 0), (0, 0), (1, 2), (5, 2), (6, 0))
inner = Ring((4, 4), (2, 4), (3, 6))
poly = PolyArea([outer, inner])
# clipping geometry can be a polygon with holes
other = poly |> Rotate(π) |> Translate(8, 8)
# clipped polygon
clipped = clip(poly, other, WeilerAthertonClipping())
viz(poly)
viz!(other, color = :black, alpha = 0.2)
viz!(boundary(clipped), color = :red, segmentsize = 3)
Expand Down
1 change: 1 addition & 0 deletions src/Meshes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ export
# clipping
ClippingMethod,
SutherlandHodgmanClipping,
WeilerAthertonClipping,
clip,

# intersections
Expand Down
28 changes: 28 additions & 0 deletions src/clipping.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,36 @@ Clip the subject `geometry` with `other` geometry using clipping `method`.
"""
function clip end

function clip(poly::Polygon, other::Geometry, method::ClippingMethod)
b = boundary(other)
if b isa Multi
for r in parent(b)
poly = clip(poly, r, method)
if isnothing(poly)
return nothing
end
end
return poly
else
return clip(poly, b, method)
end
end

function clip(gs::Domain, other::Geometry, method::ClippingMethod)
polys = PolyArea[]
for i in 1:nelements(gs)
poly = clip(element(gs, i), other, method)
if !isnothing(poly)
push!(polys, poly)
end
end
n = length(polys)
return n == 0 ? nothing : (n == 1 ? polys[1] : GeometrySet(polys))
end

# ----------------
# IMPLEMENTATIONS
# ----------------

include("clipping/sutherlandhodgman.jl")
include("clipping/weileratherton.jl")
15 changes: 11 additions & 4 deletions src/clipping/sutherlandhodgman.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ The Sutherland-Hodgman algorithm for clipping polygons.
"""
struct SutherlandHodgmanClipping <: ClippingMethod end

function clip(poly::Polygon, other::Geometry, method::SutherlandHodgmanClipping)
c = [clip(ring, boundary(other), method) for ring in rings(poly)]
r = [r for r in c if !isnothing(r)]
isempty(r) ? nothing : PolyArea(r)
# function clip(poly::Polygon, other::Geometry, method::SutherlandHodgmanClipping)
# c = [clip(ring, boundary(other), method) for ring in rings(poly)]
# r = [r for r in c if !isnothing(r)]
# isempty(r) ? nothing : PolyArea(r)
# end


function clip(poly::Polygon, other::Ring, method::SutherlandHodgmanClipping)
c = [clip(ring, other, method) for ring in rings(poly)]
r = [r for r in c if !isnothing(r)]
isempty(r) ? nothing : PolyArea(r)
end

function clip(ring::Ring, other::Ring, ::SutherlandHodgmanClipping)
Expand Down
Loading

0 comments on commit 42c354f

Please sign in to comment.