Home > matGeom > meshes3d > minConvexHull.m

minConvexHull

PURPOSE ^

MINCONVEXHULL Return the unique minimal convex hull of a set of 3D points.

SYNOPSIS ^

function newFaces = minConvexHull(points, varargin)

DESCRIPTION ^

MINCONVEXHULL Return the unique minimal convex hull of a set of 3D points.

   FACES = minConvexHull(PTS)
   NODES is a set of 3D points  (as a Nx3 array). The function computes
   the convex hull, and merge contiguous coplanar faces. The result is a
   set of polygonal faces, such that there are no coplanar faces.
   FACES is a cell array, each cell containing the vector of indices of
   nodes given in NODES for the corresponding face.

   FACES = minConvexHull(PTS, PRECISION)
   Adjust the threshold for deciding if two faces are coplanar or
   parallel. Default value is 1e-14.

   Example
     % extract square faces from a cube
     [n, e, f] = createCube;
     f2 = minConvexHull(n);
     drawMesh(n, f2);

     % Subdivides and smooths a mesh rpresenting a cube
     [n, e, f] = createCube;
     [n2, f2] = subdivideMesh(n, triangulateFaces(f), 4);
     [n3, f3] = smoothMesh(n2, f2);
     figure; drawMesh(n3, f3);
     axis equal; view(3);
     % merge coplanar faces, making apparent the faces of the original cube
     f4 = minConvexHull(n3);
     figure; drawMesh(n3, f4);
     axis equal; view(3);


   See also
   meshes3d, mergeCoplanarFaces, drawMesh, convhull, convhulln

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function newFaces = minConvexHull(points, varargin)
0002 %MINCONVEXHULL Return the unique minimal convex hull of a set of 3D points.
0003 %
0004 %   FACES = minConvexHull(PTS)
0005 %   NODES is a set of 3D points  (as a Nx3 array). The function computes
0006 %   the convex hull, and merge contiguous coplanar faces. The result is a
0007 %   set of polygonal faces, such that there are no coplanar faces.
0008 %   FACES is a cell array, each cell containing the vector of indices of
0009 %   nodes given in NODES for the corresponding face.
0010 %
0011 %   FACES = minConvexHull(PTS, PRECISION)
0012 %   Adjust the threshold for deciding if two faces are coplanar or
0013 %   parallel. Default value is 1e-14.
0014 %
0015 %   Example
0016 %     % extract square faces from a cube
0017 %     [n, e, f] = createCube;
0018 %     f2 = minConvexHull(n);
0019 %     drawMesh(n, f2);
0020 %
0021 %     % Subdivides and smooths a mesh rpresenting a cube
0022 %     [n, e, f] = createCube;
0023 %     [n2, f2] = subdivideMesh(n, triangulateFaces(f), 4);
0024 %     [n3, f3] = smoothMesh(n2, f2);
0025 %     figure; drawMesh(n3, f3);
0026 %     axis equal; view(3);
0027 %     % merge coplanar faces, making apparent the faces of the original cube
0028 %     f4 = minConvexHull(n3);
0029 %     figure; drawMesh(n3, f4);
0030 %     axis equal; view(3);
0031 %
0032 %
0033 %   See also
0034 %   meshes3d, mergeCoplanarFaces, drawMesh, convhull, convhulln
0035 %
0036 
0037 
0038 % ------
0039 % Author: David Legland
0040 % e-mail: david.legland@inra.fr
0041 % Created: 2006-07-05
0042 % Copyright 2006 INRA - CEPIA Nantes - MIAJ (Jouy-en-Josas).
0043 
0044 % HISTORY
0045 %   20/07/2006 add tolerance for coplanarity test
0046 %   21/08/2006 fix small bug due to difference of methods to test
0047 %       coplanarity, sometimes resulting in 3 points of a face being not
0048 %       coplanar! Also add control on precision
0049 %   18/09/2007 ensure faces are given as horizontal vectors
0050 
0051 % set up precision
0052 acc = 1e-14;
0053 if ~isempty(varargin)
0054     acc = varargin{1};
0055 end
0056 
0057 % triangulated convex hull. It is not uniquely defined.
0058 faces = convhulln(points);
0059 
0060 % compute centroid of the nodes
0061 pointsCentroid = centroid(points);
0062 
0063 % number of base triangular faces
0064 N = size(faces, 1);
0065 
0066 % compute normals of given faces
0067 normals = planeNormal(createPlane(...
0068     points(faces(:,1),:), points(faces(:,2),:), points(faces(:,3),:)));
0069 
0070 % initialize empty faces
0071 newFaces = {};
0072 
0073 
0074 % Processing flag for each triangle
0075 % 1 : triangle to process, 0 : already processed
0076 % in the beginning, every triangle face need to be processed
0077 flag = ones(N, 1);
0078 
0079 % iterate on each triangular face of the convex hull
0080 for iFace = 1:N
0081     
0082     % check if face was already performed
0083     if ~flag(iFace)
0084         continue;
0085     end
0086 
0087     % indices of faces with same normal
0088     ind = find(abs(vectorNorm3d(cross(repmat(normals(iFace, :), [N 1]), normals)))<acc);
0089     ind = ind(ind~=iFace);
0090     
0091     % keep only coplanar faces (test coplanarity of points in both face)
0092     ind2 = iFace;
0093     for j = 1:length(ind)
0094         if isCoplanar(points([faces(iFace,:) faces(ind(j),:)], :), acc)
0095             ind2 = [ind2 ind(j)]; %#ok<AGROW>
0096         end
0097     end
0098     
0099     
0100     % compute order of the vertices in current face
0101     faceVertices = unique(faces(ind2, :));
0102     [tmp, I]  = angleSort3d(points(faceVertices, :)); %#ok<ASGLU>
0103     
0104     % create the new face, ensuring it is a row vector
0105     face = faceVertices(I);
0106     face = face(:)';
0107     
0108     % ensure face has normal pointing outwards
0109     outerNormal = meshFaceCentroids(points, face) - pointsCentroid;
0110     if dot(meshFaceNormals(points, face), outerNormal, 2) < 0
0111         face = face([1 end:-1:2]);
0112     end
0113     
0114     % add a new face to the list
0115     newFaces = [newFaces {face}]; %#ok<AGROW>
0116     
0117     % mark processed faces
0118     flag(ind2) = 0;
0119 end
0120

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