@@ -462,6 +462,71 @@ function split_mesh(mesh::Mesh, views::Vector{<: UnitRange{<: Integer}} = mesh.v
462462 end
463463end
464464
465+
466+
467+ # two faces are the same if they match or they just cycle indices
468+ """
469+ cyclic_equal(face1, face2)
470+
471+ Returns true if two faces are equal up to a cyclic permutation of their indices.
472+ E.g. considers `GLTriangleFace(2,3,1)` equal to `GLTriangleFace(1,2,3)` but not
473+ `GLTriangleFace(2,1,3)`.
474+ """
475+ function cyclic_equal (f1:: FT , f2:: FT ) where {N, FT <: AbstractFace{N} }
476+ _, min_i1 = findmin (f1. data)
477+ _, min_i2 = findmin (f2. data)
478+ @inbounds for i in 1 : N
479+ if f1[mod1 (min_i1 + i, end )] != = f2[mod1 (min_i2 + i, end )]
480+ return false
481+ end
482+ end
483+ return true
484+ end
485+
486+ """
487+ cyclic_hash(face[, h::UInt = hash(0)])
488+
489+ Creates a hash for the given face that is equal under cyclic permutation of the
490+ faces indices.
491+ For example `GLTriangleFace(1,2,3)` will have the same hash as `(2,3,1)` and
492+ `(3,1,2)`, but be different from `(1,3,2)` and its cyclic permutations.
493+ """
494+ function cyclic_hash (f:: AbstractFace{N} , h:: UInt = hash (0 )) where {N}
495+ _, min_i = findmin (f. data)
496+ @inbounds for i in min_i: N
497+ h = hash (f[i], h)
498+ end
499+ @inbounds for i in 1 : min_i- 1
500+ h = hash (f[i], h)
501+ end
502+ return h
503+ end
504+
505+ # Fastpaths
506+ cyclic_equal (f1:: FT , f2:: FT ) where {FT <: AbstractFace{2} } = minmax (f1. data... ) == minmax (f2. data... )
507+ cyclic_hash (f:: AbstractFace{2} , h:: UInt = hash (0 )) = hash (minmax (f. data... ), h)
508+
509+ function cyclic_equal (f1:: FT , f2:: FT ) where {FT <: AbstractFace{3} }
510+ return (f1. data == f2. data) || (f1. data == (f2[2 ], f2[3 ], f2[1 ])) ||
511+ (f1. data == (f2[3 ], f2[1 ], f2[2 ]))
512+ end
513+ function cyclic_hash (f:: AbstractFace{3} , h:: UInt = hash (0 ))
514+ if f[1 ] < f[2 ]
515+ if f[1 ] < f[3 ]
516+ return hash (f. data, h)
517+ else
518+ return hash ((f[3 ], f[1 ], f[2 ]), h)
519+ end
520+ else
521+ if f[2 ] < f[3 ]
522+ return hash ((f[2 ], f[3 ], f[1 ]), h)
523+ else
524+ return hash ((f[3 ], f[1 ], f[2 ]), h)
525+ end
526+ end
527+ end
528+
529+
465530"""
466531 remove_duplicates(faces)
467532
0 commit comments