From dbf5c6273002ddd96ebadb8c0168c8292355db53 Mon Sep 17 00:00:00 2001 From: artemyev Date: Fri, 4 Jul 2025 14:18:58 +0700 Subject: [PATCH 1/2] feat: add new function mesh/sharp_halfedges.m This function is based on sharp_edges function. --- mesh/sharp_halfedges.m | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 mesh/sharp_halfedges.m diff --git a/mesh/sharp_halfedges.m b/mesh/sharp_halfedges.m new file mode 100644 index 00000000..f0ab7756 --- /dev/null +++ b/mesh/sharp_halfedges.m @@ -0,0 +1,58 @@ +function SHE = sharp_halfedges(V, F, angle, varargin) +% SHARP_HALFEDGES Compute sharp halfedges for a mesh based on dihedral angles. +% +% SHE = sharp_halfedges(V, F, angle) +% SHE = sharp_halfedges(V, F, angle, 'CornerIndexing') +% SHE = sharp_halfedges(V, F, angle, 'CyclicIndexing') +% +% This function marks "sharp" edges in a triangular mesh based on a given dihedral +% angle threshold. An edge is considered sharp if its dihedral angle exceeds the +% specified angle (in radians). +% +% Input: +% V #V by 3 matrix of vertex positions. +% F #F by 3 matrix of triangle vertex indices. +% angle Scalar threshold angle (in radians). An edge with a larger dihedral +% angle is marked as sharp. +% +% Optional argument (mode): +% 'CornerIndexing' (default) - Uses corner-based indexing convention: edge j +% is defined as the edge opposite vertex j in F(i,:). +% 'CyclicIndexing' - Uses edge-based cyclic indexing convention: local edge +% indices follow the order of edges (1→2, 2→3, 3→1) in each triangle. +% +% Output: +% SHE #F by 3 matrix, where SHE(i,j) = 1 if the j-th edge of face i is sharp +% (dihedral angle > angle), and 0 otherwise. Indexing depends on the mode. +% +% Example: +% SHE = sharp_halfedges(V, F, pi/6, 'CyclicIndexing'); + + % Default mode + mode = 'CornerIndexing'; + + % Parse optional argument + if ~isempty(varargin) + if ischar(varargin{1}) || isstring(varargin{1}) + mode = varargin{1}; + else + error('Optional argument must be a string: ''CornerIndexing'' or ''CyclicIndexing''.'); + end + end + + [A,C] = adjacency_dihedral_angle_matrix(V,F); + [AI,AJ,AV] = find(A); + keep = abs(AV-pi)>(angle) & ~isnan(AV); + A = sparse(AI(keep),AJ(keep),1,size(A,1),size(A,2)); + [CI,~,CV] = find(C.*A); + idx = sub2ind(size(C), CI, CV); + SHE = zeros(size(F)); + SHE(idx)=1; + + % Apply cyclic reordering if requested + if strcmpi(mode, 'CyclicIndexing') + SHE = [SHE(:,3), SHE(:,1), SHE(:,2)]; + elseif ~strcmpi(mode, 'CornerIndexing') + error('Unknown indexing mode. Use ''CornerIndexing'' or ''CyclicIndexing''.'); + end +end \ No newline at end of file From 8497f576f2bfb925814dbac617ed23c4984f7594 Mon Sep 17 00:00:00 2001 From: artemyev Date: Fri, 4 Jul 2025 15:01:15 +0700 Subject: [PATCH 2/2] feat(sharp_edges): improve example --- mesh/sharp_halfedges.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesh/sharp_halfedges.m b/mesh/sharp_halfedges.m index f0ab7756..19920bdf 100644 --- a/mesh/sharp_halfedges.m +++ b/mesh/sharp_halfedges.m @@ -26,7 +26,11 @@ % (dihedral angle > angle), and 0 otherwise. Indexing depends on the mode. % % Example: -% SHE = sharp_halfedges(V, F, pi/6, 'CyclicIndexing'); +% SHE = sharp_halfedges(V, F, pi/2-0.0001); +% [EF, EI, uE, EMAP] = edge_flaps(F); +% % isSharpEdge - mask of undirected sharp edges in uE. +% isSharpEdge = zeros(size(uE,1),1); +% isSharpEdge(EMAP(SHE==1)) = 1; % Default mode mode = 'CornerIndexing';