Line data Source code
1 : struct BoundaryLoopIter{M, H}
2 17 : mesh::M
3 : h0::HHnd
4 : end
5 :
6 4 : Base.eltype(::BoundaryLoopIter{M, H}) where {M, H} = H
7 4 : Base.IteratorSize(::BoundaryLoopIter) = Base.SizeUnknown()
8 :
9 16 : Base.iterate(iter::BoundaryLoopIter{M, H}) where {M, H} =
10 : (_loopitem(iter, iter.h0), iter.h0)
11 :
12 127 : function Base.iterate(iter::BoundaryLoopIter{M, H}, h::HHnd) where {M, H}
13 127 : h = next(iter.mesh, h)
14 127 : (h == iter.h0) && return nothing
15 :
16 111 : (_loopitem(iter, h), h)
17 : end
18 :
19 103 : _loopitem(::BoundaryLoopIter{M, HHnd}, h) where {M} = h
20 24 : _loopitem(iter::BoundaryLoopIter{M, VHnd}, h) where {M} =
21 : destination(iter.mesh, h)
22 :
23 : """
24 : for h in boundaryloop(mesh, h0)
25 : # ...
26 : end
27 :
28 : for v in vertices(boundaryloop(mesh, h0))
29 : # ...
30 : end
31 :
32 : Iterate boundary loop half-edges or [`vertices`](@ref) starting with
33 : boundary hald-edge `h0` counter-clockwise.
34 :
35 : !!! warning "precondition"
36 : Expects boundary half-edge `h0` ([`isboundary`](@ref)).
37 :
38 : !!! warning "precondition"
39 : The iteration is **undefined** if `mesh` is non-manifold.
40 :
41 : See also [`boundayloop`](@ref)
42 : """
43 14 : function boundaryloopccw(mesh::Mesh{V, F, H, E}, h::HHnd) where {V, F, H, E}
44 14 : @assert isboundary(mesh, h)
45 14 : BoundaryLoopIter{Mesh{V, F, H, E}, HHnd}(mesh, h)
46 : end
47 :
48 : """
49 : Synonym for [`boundaryloopccw`](@ref)
50 : """
51 4 : boundaryloop(mesh::Mesh, h::HHnd) = boundaryloopccw(mesh, h)
52 :
53 : """
54 : itr = vertices(boundaryloopccw(mesh, h0))
55 :
56 : Iterate boundary vertices instead of half-edges.
57 :
58 : See also [`boundaryloopccw`](@ref)
59 : """
60 3 : vertices(iter::BoundaryLoopIter{M, HHnd}) where {M} =
61 : BoundaryLoopIter{M, VHnd}(iter.mesh, iter.h0)
62 :
63 :
64 11 : function findboundaryloops(cb::Function, mesh::Mesh)
65 800 : processed = fill(false, n_total(eattr(mesh)))
66 :
67 21 : for e in edges(mesh)
68 775 : processed[Int(e)] && continue
69 :
70 706 : h0 = boundaryhalfedge(mesh, e)
71 :
72 706 : (h0 == NoH) && continue
73 :
74 10 : for h in boundaryloopccw(mesh, h0)
75 79 : e = edge(h)
76 79 : @massert !processed[Int(e)]
77 79 : processed[Int(e)] = true
78 79 : cb(h0, h)
79 79 : end
80 775 : end
81 :
82 0 : nothing
83 : end
84 :
85 : """
86 : seeds = findboundaryloopseeds(mesh)
87 :
88 : Find all boundary loops and return `Vector{HHnd}` of seeds, i.e.,
89 : some arbitrary half-edge per loop.
90 :
91 : !!! warning "precondition"
92 : The result is **undefined** if `mesh` is non-manifold.
93 :
94 : See also [`findboundaryloops`](@ref), [`boundaryloopccw`](@ref)
95 : """
96 1 : function findboundaryloopseeds(mesh::Mesh)
97 1 : seeds = HHnd[]
98 :
99 17 : function pushseeds!(h0::HHnd, h::HHnd)
100 16 : (h0 == h) && push!(seeds, h0)
101 : end
102 :
103 1 : findboundaryloops(pushseeds!, mesh)
104 :
105 1 : seeds
106 : end
107 :
108 10 : function findboundaryloops(mesh::Mesh)
109 10 : loops = Vector{HHnd}[]
110 :
111 73 : function pushloops!(h0::HHnd, h::HHnd)
112 63 : (h0 == h) && push!(loops, HHnd[])
113 63 : push!(loops[end], h)
114 : end
115 :
116 10 : findboundaryloops(pushloops!, mesh)
117 :
118 10 : loops
119 : end
120 :
121 : """
122 : loops = findboundaryloops(mesh)
123 :
124 : for loop in loops, h in loop
125 : # ...
126 : end
127 :
128 : Find boundary loops and return array of loops, where each loop is
129 : encoded as an array of `HHnd`.
130 :
131 : findboundaryloops(mesh) do h0, h
132 : if h == h0
133 : # new loop with seed h0
134 : end
135 :
136 : # process h as part of loop
137 : end
138 :
139 : Find boundary loops and evaluate callback for every boundary half-edfe
140 : with arguments `h0` (seed) and `h` current boundary half-edge: a new
141 : boundary loop is found whenever `h0 == h`. This method returns
142 : `nothing`.
143 :
144 : !!! warning "precondition"
145 : The result is **undefined** if `mesh` is non-manifold.
146 :
147 : See also [`findboundaryloopseeds`](@ref), [`boundaryloopccw`](@ref)
148 : """ findboundaryloops
149 :
150 :
151 : # TODO: longest ... --> length of ... (geometry)
|