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.

   NOTE: minConvexHull does not remove unreferenced vertices, etc. The
   function trimMesh can be subsequently applied to the mesh to adress
   this.

   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 %   NOTE: minConvexHull does not remove unreferenced vertices, etc. The
0012 %   function trimMesh can be subsequently applied to the mesh to adress
0013 %   this.
0014 %
0015 %   FACES = minConvexHull(PTS, PRECISION)
0016 %   Adjust the threshold for deciding if two faces are coplanar or
0017 %   parallel. Default value is 1e-14.
0018 %
0019 %   Example
0020 %     % extract square faces from a cube
0021 %     [n, e, f] = createCube;
0022 %     f2 = minConvexHull(n);
0023 %     drawMesh(n, f2);
0024 %
0025 %     % Subdivides and smooths a mesh rpresenting a cube
0026 %     [n, e, f] = createCube;
0027 %     [n2, f2] = subdivideMesh(n, triangulateFaces(f), 4);
0028 %     [n3, f3] = smoothMesh(n2, f2);
0029 %     figure; drawMesh(n3, f3);
0030 %     axis equal; view(3);
0031 %     % merge coplanar faces, making apparent the faces of the original cube
0032 %     f4 = minConvexHull(n3);
0033 %     figure; drawMesh(n3, f4);
0034 %     axis equal; view(3);
0035 %
0036 %
0037 %   See also
0038 %   meshes3d, mergeCoplanarFaces, drawMesh, convhull, convhulln
0039 %
0040 
0041 % ------
0042 % Author: David Legland
0043 % E-mail: david.legland@inrae.fr
0044 % Created: 2006-07-05
0045 % Copyright 2006-2024 INRA - CEPIA Nantes - MIAJ (Jouy-en-Josas)
0046 
0047 % set up precision
0048 acc = 1e-14;
0049 if ~isempty(varargin)
0050     acc = varargin{1};
0051 end
0052 
0053 % triangulated convex hull. It is not uniquely defined.
0054 faces = convhulln(points);
0055 
0056 % compute centroid of the nodes
0057 pointsCentroid = centroid(points);
0058 
0059 % number of base triangular faces
0060 N = size(faces, 1);
0061 
0062 % compute normals of given faces
0063 normals = planeNormal(createPlane(...
0064     points(faces(:,1),:), points(faces(:,2),:), points(faces(:,3),:)));
0065 
0066 % initialize empty faces
0067 newFaces = {};
0068 
0069 
0070 % Processing flag for each triangle
0071 % 1 : triangle to process, 0 : already processed
0072 % in the beginning, every triangle face need to be processed
0073 flag = ones(N, 1);
0074 
0075 % iterate on each triangular face of the convex hull
0076 for iFace = 1:N
0077     
0078     % check if face was already performed
0079     if ~flag(iFace)
0080         continue;
0081     end
0082 
0083     % indices of faces with same normal
0084     ind = find(abs(vectorNorm3d(cross(repmat(normals(iFace, :), [N 1]), normals)))<acc);
0085     ind = ind(ind~=iFace);
0086     
0087     % keep only coplanar faces (test coplanarity of points in both face)
0088     ind2 = iFace;
0089     for j = 1:length(ind)
0090         if isCoplanar(points([faces(iFace,:) faces(ind(j),:)], :), acc)
0091             ind2 = [ind2 ind(j)]; %#ok<AGROW>
0092         end
0093     end
0094     
0095     
0096     % compute order of the vertices in current face
0097     faceVertices = unique(faces(ind2, :));
0098     [tmp, I]  = angleSort3d(points(faceVertices, :)); %#ok<ASGLU>
0099     
0100     % create the new face, ensuring it is a row vector
0101     face = faceVertices(I);
0102     face = face(:)';
0103     
0104     % ensure face has normal pointing outwards
0105     outerNormal = meshFaceCentroids(points, face) - pointsCentroid;
0106     if dot(meshFaceNormals(points, face), outerNormal, 2) < 0
0107         face = face([1 end:-1:2]);
0108     end
0109     
0110     % add a new face to the list
0111     newFaces = [newFaces {face}]; %#ok<AGROW>
0112     
0113     % mark processed faces
0114     flag(ind2) = 0;
0115 end

Generated on Thu 21-Nov-2024 11:30:22 by m2html © 2003-2022