Home > matGeom > meshes3d > meshVertexClustering.m

meshVertexClustering

PURPOSE ^

MESHVERTEXCLUSTERING Simplifies a mesh using vertex clustering.

SYNOPSIS ^

function varargout = meshVertexClustering(vertices, faces, spacing, varargin)

DESCRIPTION ^

MESHVERTEXCLUSTERING Simplifies a mesh using vertex clustering.

   [V2, F2] = meshVertexClustering(V, F, SPACING)
   [V2, F2] = meshVertexClustering(MESH, SPACING)
   MESH2 = meshVertexClustering(...)

   Simplifies a mesh using vertex clustering. Input mesh is specified
   either by a pair V, F containing the vertex coordinates and the faces
   informations, or by a structure with fields 'vertices' and 'faces'.

   The SPACING input defines the size of the grid. It can be either a
   scalar (uniform grid) or a 1-by-3 row vector. 

   The output is specified either in two outputs, or in a structure with
   fields 'vertices' and 'faces'.

   Example
     [x, y, z]  = meshgrid(1:100, 1:100, 1:100);
     img = hypot3(x-51.12, y-52.23, z-53.34);
     [faces, vertices] = isosurface(img, 45);
     [v2, f2] = meshVertexClustering(vertices, faces, 10);
     figure; axis equal; axis([0 100 0 100 0 100]);
     drawMesh(v2, f2);

   See also
     reducepatch, smoothMesh

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function varargout = meshVertexClustering(vertices, faces, spacing, varargin)
0002 %MESHVERTEXCLUSTERING Simplifies a mesh using vertex clustering.
0003 %
0004 %   [V2, F2] = meshVertexClustering(V, F, SPACING)
0005 %   [V2, F2] = meshVertexClustering(MESH, SPACING)
0006 %   MESH2 = meshVertexClustering(...)
0007 %
0008 %   Simplifies a mesh using vertex clustering. Input mesh is specified
0009 %   either by a pair V, F containing the vertex coordinates and the faces
0010 %   informations, or by a structure with fields 'vertices' and 'faces'.
0011 %
0012 %   The SPACING input defines the size of the grid. It can be either a
0013 %   scalar (uniform grid) or a 1-by-3 row vector.
0014 %
0015 %   The output is specified either in two outputs, or in a structure with
0016 %   fields 'vertices' and 'faces'.
0017 %
0018 %   Example
0019 %     [x, y, z]  = meshgrid(1:100, 1:100, 1:100);
0020 %     img = hypot3(x-51.12, y-52.23, z-53.34);
0021 %     [faces, vertices] = isosurface(img, 45);
0022 %     [v2, f2] = meshVertexClustering(vertices, faces, 10);
0023 %     figure; axis equal; axis([0 100 0 100 0 100]);
0024 %     drawMesh(v2, f2);
0025 %
0026 %   See also
0027 %     reducepatch, smoothMesh
0028  
0029 % ------
0030 % Author: David Legland
0031 % e-mail: david.legland@inra.fr
0032 % Created: 2019-01-28,    using Matlab 9.5.0.944444 (R2018b)
0033 % Copyright 2019 INRA - Cepia Software Platform.
0034 
0035 
0036 %% Initialisation
0037 
0038 if isstruct(vertices)
0039     if nargin > 2
0040         varargin = [{spacing} varargin(:)];
0041     end
0042     spacing = faces;
0043 
0044     mesh = vertices;
0045     vertices = mesh.vertices;
0046     faces = mesh.faces;
0047 end
0048 
0049 % ensure input mesh is a triangulation
0050 faces = triangulateFaces(faces);
0051 
0052 % ensure spacing is a 1-by-3 array
0053 if isscalar(spacing)
0054     spacing = [spacing spacing spacing];
0055 end
0056 
0057 % extract grid origin
0058 origin = [0 0 0];
0059 if ~isempty(varargin)
0060     origin = varargin{1};
0061 end
0062 
0063 
0064 %% Apply grid simplification
0065 
0066 % identify the vertices belonging to the same grid
0067 [v2, I, J] = unique(round(bsxfun(@rdivide, bsxfun(@minus, vertices, origin), spacing)), 'rows');
0068 
0069 
0070 %% compute reduced vertex coordinates
0071 
0072 % compute coordinates of new vertices
0073 for iVertex = 1:length(I)
0074     gridVertices = vertices(J == iVertex, :);
0075     v2(iVertex, :) = mean(gridVertices, 1);
0076 end
0077 
0078 
0079 %% Compute new faces
0080 
0081 % create empty array
0082 faces2 = zeros(0, 3);
0083 
0084 % iterate over old faces, and keep only faces whose vertices belong to
0085 % different cell grids
0086 nFaces = size(faces, 1);
0087 for iFace = 1:nFaces
0088     % current face
0089     face = faces(iFace, :);
0090     
0091     % equivalent face with new vertices
0092     face2 = J(face)';
0093     
0094     % some vertices may belong to same cell, so we need to adjust
0095     % processing
0096     nInds = length(unique(face2));
0097     if nInds == 3
0098         % vertices belong to three different cells -> create a new face
0099         
0100         % keep smaller vertex at first position
0101         [tmp, indMin] = min(face2); %#ok<ASGLU>
0102         face2 = circshift(face2, [1-indMin 0]);
0103         
0104         % append the new face to the array
0105         faces2 = [faces2 ; face2]; %#ok<AGROW>
0106     end
0107 end
0108 
0109 % remove duplicate faces
0110 faces2 = unique(faces2, 'rows');
0111 
0112 if nargout == 1
0113     varargout{1} = struct('vertices', v2, 'faces', faces2);
0114 else
0115     varargout = {v2, faces2};
0116 end

Generated on Wed 16-Feb-2022 15:10:47 by m2html © 2003-2019