@@ -216,57 +216,64 @@ function HalfEdgeTopology(elems::AbstractVector{<:Connectivity}; sort=true)
216
216
end
217
217
218
218
function adjsortperm (elems:: AbstractVector{<:Connectivity} )
219
+ reduce (vcat, connected_components (elems))
220
+ end
221
+
222
+ function connected_components (elems:: AbstractVector{<:Connectivity} )
219
223
# remaining list of elements to process
220
224
oinds = collect (eachindex (elems)[2 : end ])
221
225
222
226
# initialize list of adjacent elements
223
227
# 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} ()
226
232
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
229
233
found = false
230
- lastfound = firstindex (elems)
234
+ for v in indices (elems[firstindex (elems)])
235
+ push! (seen, v)
236
+ end
231
237
232
- # lookup all elements that share at least
233
- # two vertices (i.e., edge) with the last
234
- # adjacent element
235
238
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
256
255
end
257
256
end
258
257
259
258
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
260
262
found = false
261
263
elseif ! isempty (oinds)
262
264
# we are done with this connected component
263
265
# 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
266
274
found = false
267
275
end
268
276
end
269
- push! (einds, lastfound)
270
277
271
278
einds
272
279
end
0 commit comments