Skip to content

Commit 2b1d8a2

Browse files
Final(?) refactor of adjsortperm
1 parent 9946fdb commit 2b1d8a2

File tree

1 file changed

+38
-31
lines changed

1 file changed

+38
-31
lines changed

src/topologies/halfedge.jl

+38-31
Original file line numberDiff line numberDiff line change
@@ -216,57 +216,64 @@ function HalfEdgeTopology(elems::AbstractVector{<:Connectivity}; sort=true)
216216
end
217217

218218
function adjsortperm(elems::AbstractVector{<:Connectivity})
219+
reduce(vcat, connected_components(elems))
220+
end
221+
222+
function connected_components(elems::AbstractVector{<:Connectivity})
219223
# remaining list of elements to process
220224
oinds = collect(eachindex(elems)[2:end])
221225

222226
# initialize list of adjacent elements
223227
# with first element from original list
224-
einds = Int[]
225-
sizehint!(einds, length(elems))
228+
einds = Vector{Vector{Int}}(undef, 0)
229+
push!(einds, Int[firstindex(elems)])
230+
231+
seen = Set{Int}()
226232

227-
# `found` minimizes adjacency discontinuities. if `found == true` for the last edge in an
228-
# element, then we continue from that new element adjacent to that edge
229233
found = false
230-
lastfound = firstindex(elems)
234+
for v in indices(elems[firstindex(elems)])
235+
push!(seen, v)
236+
end
231237

232-
# lookup all elements that share at least
233-
# two vertices (i.e., edge) with the last
234-
# adjacent element
235238
while !isempty(oinds)
236-
lelem = elems[lastfound]
237-
vinds = indices(lelem)
238-
for v in vinds
239-
# vertices that are not `v`
240-
v! = filter(!=(v), vinds)
241-
242-
# iteratively test other elements
243-
iter = 1
244-
while iter length(oinds)
245-
oelem = elems[oinds[iter]]
246-
vinds′ = indices(oelem)
247-
if any(==(v), vinds′) && !isdisjoint(v!, vinds′)
248-
found = true
249-
push!(einds, lastfound)
250-
lastfound = popat!(oinds, iter)
251-
# don't increment j here because `popat!` just put the j+1 element at j
252-
# (avoids the need to reverse the array)
253-
else
254-
iter += 1
255-
end
239+
# iteratively test other elements
240+
iter = 1
241+
while iter length(oinds)
242+
lelem = elems[oinds[iter]]
243+
vinds = indices(lelem)
244+
cnt = count((seen), vinds)
245+
# add elements that share at least two vertices (i.e., edge) with the last
246+
# adjacent element
247+
if cnt > 1
248+
push!.((seen,), vinds)
249+
found = true
250+
push!(last(einds), popat!(oinds, iter))
251+
# don't increment j here because `popat!` just put the j+1 element at j
252+
# (avoids the need to reverse the array)
253+
else
254+
iter += 1
256255
end
257256
end
258257

259258
if found
259+
# new vertices were "seen" while iterating `oinds`, so we need to iterate
260+
# again because there may be elements which are now adjacent with the newly
261+
# "seen" vertices
260262
found = false
261263
elseif !isempty(oinds)
262264
# we are done with this connected component
263265
# pop a new element from the original list
264-
push!(einds, lastfound)
265-
lastfound = popfirst!(oinds)
266+
push!(einds, Int[])
267+
push!(last(einds), popfirst!(oinds))
268+
# a disconnected component means that ≥N-1 vertices in the newest element
269+
# haven't been "seen" (but its possible the new component is connected
270+
# by a single vertex)
271+
for v in indices(elems[last(last(einds))])
272+
push!(seen, v)
273+
end
266274
found = false
267275
end
268276
end
269-
push!(einds, lastfound)
270277

271278
einds
272279
end

0 commit comments

Comments
 (0)