Skip to content

Commit 71a2312

Browse files
Refactor adjsort to work with indices directly and return a sort-perm
1 parent 934f123 commit 71a2312

File tree

1 file changed

+39
-29
lines changed

1 file changed

+39
-29
lines changed

src/topologies/halfedge.jl

+39-29
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,20 @@ function HalfEdgeTopology(elems::AbstractVector{<:Connectivity}; sort=true)
134134

135135
# sort elements to make sure that they
136136
# are traversed in adjacent-first order
137-
adjelems = sort ? adjsort(elems)::typeof(elems) : elems
138-
eleminds = sort ? indexin(adjelems, elems) : 1:length(elems)
137+
if sort
138+
eleminds = adjsortperm(elems)
139+
adjelems = map(collect indices, elems[eleminds])::Vector{Vector{Int}}
140+
else
141+
adjelems, eleminds = map(collect indices, elems)::Vector{Vector{Int}}, eachindex(elems)
142+
end
139143

140144
# start assuming that all elements are
141145
# oriented consistently as CCW
142146
CCW = trues(length(adjelems))
143147

144148
# initialize with first element
145149
half4pair = Dict{Tuple{Int,Int},HalfEdge}()
146-
elem = first(adjelems)
147-
inds::Vector{Int} = collect(indices(elem))
150+
inds = first(adjelems)
148151
v = CircularVector(inds)
149152
n = length(v)
150153
for i in 1:n
@@ -153,8 +156,7 @@ function HalfEdgeTopology(elems::AbstractVector{<:Connectivity}; sort=true)
153156

154157
# insert all other elements
155158
for e in 2:length(adjelems)
156-
elem = adjelems[e]
157-
inds = collect(indices(elem))
159+
inds = adjelems[e]
158160
v = CircularVector(inds)
159161
n = length(v)
160162
for i in 1:n
@@ -183,8 +185,8 @@ function HalfEdgeTopology(elems::AbstractVector{<:Connectivity}; sort=true)
183185
end
184186

185187
# add missing pointers
186-
for (e, elem) in Iterators.enumerate(adjelems)
187-
inds = CCW[e] ? collect(indices(elem)) : reverse(collect(indices(elem)))
188+
for (e, inds) in Iterators.enumerate(adjelems)
189+
inds = CCW[e] ? inds : reverse(inds)
188190
v = CircularVector(inds)
189191
n = length(v)
190192
for i in 1:n
@@ -217,42 +219,50 @@ function HalfEdgeTopology(elems::AbstractVector{<:Connectivity}; sort=true)
217219
HalfEdgeTopology(halves)
218220
end
219221

220-
function adjsort(elems::AbstractVector{<:Connectivity})
222+
function adjsortperm(elems::AbstractVector{<:Connectivity})
223+
listi = collect(eachindex(elems)[2:end])
221224
# initialize list of adjacent elements
222225
# with first element from original list
223-
list::Vector{Tuple{Vararg{Int}}} = map(indices, elems)
224-
adjs = similar(list, 0)
225-
push!(adjs, popfirst!(list))
226-
227-
# the loop will terminate if the mesh
228-
# is manifold, and that is always true
229-
# with half-edge topology
230-
while !isempty(list)
226+
adjs = Int[1]
227+
sizehint!(adjs, length(elems))
228+
229+
# found minimizes adjacency discontinuities. if `found == true` for the last edge in an
230+
# element, then we continue from that new element adjacent to that edge
231+
found = false
232+
while !isempty(listi)
231233
# lookup all elements that share at least
232234
# one vertex with the last adjacent element
233-
found = false
234-
vinds = last(adjs)
235+
adj = last(adjs)
236+
vinds::Tuple{Vararg{Int}} = indices(elems[adj])
235237
for i in vinds
236238
not_i = filter(!=(i), vinds)
237-
for j in reverse(eachindex(list))
239+
j = 1
240+
while j length(listi)
238241
# equivalent to `length(vinds ∩ list[j]) > 1` but more efficient (no allocs(?))
239-
any(==(i), list[j]) || continue
240-
isdisjoint(not_i, list[j]) && continue
241-
242-
# implicitly `list[j]` contains `i` and at least one other vertex
243-
found = true
244-
push!(adjs, popat!(list, j))
242+
elem = indices(elems[listi[j]])
243+
if any(==(i), elem) && !isdisjoint(not_i, elem)::Bool
244+
# `list[j]` contains `i` and at least one other vertex
245+
push!(adjs, popat!(listi, j))
246+
found = true
247+
# don't increment j here because `popat!` just put the j+1 element at j
248+
# (avoids the need to reverse the array)
249+
else
250+
j += 1
251+
found = false
252+
continue
253+
end
245254
end
246255
end
247256

248-
if !found && !isempty(list)
257+
if !found && !isempty(listi)
249258
# we are done with this connected component
250259
# pop a new element from the original list
251-
push!(adjs, popfirst!(list))
260+
push!(adjs, popfirst!(listi))
261+
found = false
252262
end
253263
end
254264

255-
map(connect, adjs)
265+
adjs
256266
end
257267

258268
paramdim(::HalfEdgeTopology) = 2

0 commit comments

Comments
 (0)