CUTMESHBYPLANE Cut a mesh by a plane. [ABOVE, IN, BELOW] = cutMeshByPlane(MESH, PLANE) where MESH, ABOVE, IN, BELOW are structs with the fields vertices and faces, and PLANE is given as a row containing initial point and 2 direction vectors. ABOVE, IN, BELOW contain the corresponding parts of the input mesh. [ABOVE_V, ABOVE_F, IN_V, IN_F, BELOW_V,BELOW_F] = ... cutMeshByPlane(V, F, PLANE) where V is a [NVx3] array containing coordinates and F is a [NFx3] array containing indices of vertices of the triangular faces. BELOW = cutMeshByPlane(V, F, PLANE, 'part', 'below') BELOW is a struct with the fields vertices and faces. Other options are: 'part' - 'above': Faces above the plane - 'in' : Faces in the plane - 'below': Faces below the plane [BELOW_V, BELOW_F] = cutMeshByPlane(MESH, PLANE, 'part', 'below') is possible, too.
0001 function varargout = cutMeshByPlane(v, f, plane, varargin) 0002 %CUTMESHBYPLANE Cut a mesh by a plane. 0003 % 0004 % [ABOVE, IN, BELOW] = cutMeshByPlane(MESH, PLANE) 0005 % where MESH, ABOVE, IN, BELOW are structs with the fields vertices and 0006 % faces, and PLANE is given as a row containing initial point and 2 0007 % direction vectors. ABOVE, IN, BELOW contain the corresponding parts of 0008 % the input mesh. 0009 % 0010 % [ABOVE_V, ABOVE_F, IN_V, IN_F, BELOW_V,BELOW_F] = ... 0011 % cutMeshByPlane(V, F, PLANE) where V is a [NVx3] array containing 0012 % coordinates and F is a [NFx3] array containing indices of vertices of 0013 % the triangular faces. 0014 % 0015 % BELOW = cutMeshByPlane(V, F, PLANE, 'part', 'below') BELOW is a struct 0016 % with the fields vertices and faces. Other options are: 0017 % 'part' - 'above': Faces above the plane 0018 % - 'in' : Faces in the plane 0019 % - 'below': Faces below the plane 0020 % 0021 % [BELOW_V, BELOW_F] = cutMeshByPlane(MESH, PLANE, 'part', 'below') is 0022 % possible, too. 0023 % 0024 0025 % --------- 0026 % Authors: oqilipo, David Legland 0027 % Created: 2017-07-09 0028 % Copyright 2017 0029 0030 narginchk(2,5) 0031 nargoutchk(1,6) 0032 0033 0034 %% Parse inputs 0035 % If first argument is a struct 0036 if nargin == 2 || nargin == 4 0037 if ~isempty(varargin) 0038 varargin = [{plane}, varargin(:)']; 0039 end 0040 plane = f; 0041 [v, f] = parseMeshData(v); 0042 end 0043 0044 p = inputParser; 0045 addRequired(p,'plane',@isPlane) 0046 validStrings = {'above','in','below'}; 0047 addParameter(p,'part','above',@(x) any(validatestring(x, validStrings))) 0048 parse(p, plane, varargin{:}); 0049 part=p.Results.part; 0050 0051 0052 %% Algorithm 0053 % Logical index to the vertices below the plane 0054 VBPl_LI = isBelowPlane(v, plane); 0055 0056 % Logical index to three vertices of each face 0057 FBP_LI = VBPl_LI(f); 0058 switch nargout 0059 case {1, 2} 0060 switch part 0061 case 'above' 0062 % Faces above the plane, all three vertices == 0 -> sum has to be 0 0063 above = removeMeshFaces(v, f, ~(sum(FBP_LI, 2) == 0) ); 0064 case 'in' 0065 % Faces in the plane, 1 or 2 vertices == 0 -> sum can be 1 or 2 0066 inside = removeMeshFaces(v, f, ~((sum(FBP_LI, 2) > 0 & sum(FBP_LI, 2) < 3))); 0067 case 'below' 0068 % Faces below the plane, all three vertices == 1 -> sum has to be 3 0069 below = removeMeshFaces(v, f, ~(sum(FBP_LI, 2) == 3) ); 0070 end 0071 case {3, 6} 0072 % Faces above the plane, all three vertices == 0 -> sum has to be 0 0073 above = removeMeshFaces(v, f, ~(sum(FBP_LI, 2) == 0) ); 0074 % Faces in the plane, 1 or 2 vertices == 0 -> sum can be 1 or 2 0075 inside = removeMeshFaces(v, f, ~((sum(FBP_LI, 2) > 0 & sum(FBP_LI, 2) < 3))); 0076 % Faces below the plane, all three vertices == 1 -> sum has to be 3 0077 below = removeMeshFaces(v, f, ~(sum(FBP_LI, 2) == 3) ); 0078 otherwise 0079 error('Invalid number of output arguments') 0080 end 0081 0082 0083 %% Parse outputs 0084 switch nargout 0085 case 1 0086 switch part 0087 case 'above' 0088 varargout{1}=above; 0089 case 'in' 0090 varargout{1}=inside; 0091 case 'below' 0092 varargout{1}=below; 0093 end 0094 case 2 0095 switch part 0096 case 'above' 0097 varargout{1}=above.vertices; 0098 varargout{2}=above.faces; 0099 case 'in' 0100 varargout{1}=inside.vertices; 0101 varargout{2}=inside.faces; 0102 case 'below' 0103 varargout{1}=below.vertices; 0104 varargout{2}=below.faces; 0105 end 0106 case 3 0107 varargout{1}=above; 0108 varargout{2}=inside; 0109 varargout{3}=below; 0110 case 6 0111 varargout{1}=above.vertices; 0112 varargout{2}=above.faces; 0113 varargout{3}=inside.vertices; 0114 varargout{4}=inside.faces; 0115 varargout{5}=below.vertices; 0116 varargout{6}=below.faces; 0117 otherwise 0118 error('Invalid number of output arguments') 0119 end 0120 0121 end