1## Copyright (C) 2021 David Legland
2## All rights reserved.
3##
4## Redistribution and use in source and binary forms, with or without
5## modification, are permitted provided that the following conditions are met:
6##
7##     1 Redistributions of source code must retain the above copyright notice,
8##       this list of conditions and the following disclaimer.
9##     2 Redistributions in binary form must reproduce the above copyright
10##       notice, this list of conditions and the following disclaimer in the
11##       documentation and/or other materials provided with the distribution.
12##
13## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS''
14## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
17## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23##
24## The views and conclusions contained in the software and documentation are
25## those of the authors and should not be interpreted as representing official
26## policies, either expressed or implied, of the copyright holders.
27
28function writeMesh_ply(fileName, vertices, faces, varargin)
29%WRITEMESH_PLY Write a mesh into a file in PLY format.
30%
31%   writeMesh_ply(FNAME, VERTICES, FACES)
32%
33%   writeMesh_ply(FNAME, MESH)
34%
35%   writeMesh_ply(..., FORMAT) also specifies a file format for the written
36%   file. FORMAT can be either 'binary' (default) or 'ascii'.
37%
38%   Example
39%   mesh = createSoccerBall;
40%   fileName = 'SoccerBall.ply';
41%   writeMesh_ply(fileName, mesh, 'Bin');
42%   mesh2 = readMesh(fileName);
43%   drawMesh(mesh2); axis equal
44%
45%   See also
46%   meshes3d, writeMesh, readMesh_ply, writeMesh_off, writeMesh_stl
47
48% ------
49% Author: David Legland, oqilipo
50% e-mail: david.legland@inrae.fr
51% Created: 2018-04-26,    using Matlab 9.4.0.813654 (R2018a)
52% Copyright 2018 INRA - Cepia Software Platform.
53
54
55%% Check inputs
56
57% optionnaly parses data
58if isstruct(vertices)
59    if nargin > 2
60        varargin = [{faces} varargin{:}];
61    end
62    faces = vertices.faces;
63    vertices = vertices.vertices;
64end
65
66% Parsing
67p = inputParser;
68addRequired(p,'fileName',@(x) validateattributes(x,{'char'},{'nonempty'}));
69suppModes = {'ascii','binary_little_endian'};
70addOptional(p,'mode','binary_little_endian',@(x) any(validatestring(x,suppModes)));
71parse(p,fileName,varargin{:});
72fileName = p.Results.fileName;
73mode = suppModes{startsWith(suppModes, p.Results.mode, 'IgnoreCase',1)};
74
75%% Initializations
76
77% number of vertices and faces
78nVertices = size(vertices, 1);
79nFaces = size(faces, 1);
80if iscell(faces)
81    nFaces = length(faces);
82end
83
84% open file for writing text
85f = fopen(fileName, 'wt');
86if (f == -1)
87    error('Couldn''t open the file %s', fileName);
88end
89
90
91%% Write Header
92
93% write the header line
94fprintf(f, 'ply\n');
95
96% write format (only ASCII supported)
97fprintf(f, 'format %s 1.0\n', mode);
98
99% some comments
100fprintf(f, 'comment Created by MatGeom for MATLAB\n');
101
102% write declaration for vertices
103fprintf(f, 'element vertex %d\n', nVertices);
104fprintf(f, 'property double x\n');
105fprintf(f, 'property double y\n');
106fprintf(f, 'property double z\n');
107
108% write declaration for faces
109fprintf(f, 'element face %d\n', nFaces);
110fprintf(f, 'property list int int vertex_index\n');
111
112% end of header
113fprintf(f, 'end_header\n');
114
115%% Write data
116
117switch mode
118    case 'ascii'
119        % write vertex info
120        format = '%0.17f %0.17f %0.17f\n';
121        fprintf(f, format, vertices');
122
123        % write face info
124        if isnumeric(faces)
125            % simply write face vertex indices
126            ns = size(faces, 2);
127            plyFaces = [ns * ones(nFaces, 1) faces-1];
128            format = ['%d' repmat(' %d', 1, ns) '\n'];
129            fprintf(f, format, plyFaces');
130        else
131            % if faces are stored in a cell array, the number of vertices in each
132            % face may be different, and we need to process each face individually
133            for iFace = 1:nFaces
134                ns = length(faces{iFace});
135                format = ['%d' repmat(' %d', 1, ns) '\n'];
136                fprintf(f, format, ns, faces{iFace} - 1);
137            end
138        end
139    case 'binary_little_endian'
140        % close the file
141        fclose(f);
142        % open file with little-endian format
143        f = fopen(fileName,'a','ieee-le');
144        % write vertex info
145        fwrite(f, vertices', 'double');
146
147        % write face info
148        if isnumeric(faces)
149            % simply write face vertex indices
150            plyFaces = [size(faces, 2) * ones(nFaces, 1) faces-1];
151            fwrite(f, plyFaces', 'int');
152        else
153            % if faces are stored in a cell array, the number of vertices in each
154            % face may be different, and we need to process each face individually
155            for iFace = 1:nFaces
156                fwrite(f, [length(faces{iFace}), faces{iFace}-1], 'int');
157            end
158        end
159    otherwise
160        error(['Format ''' mode ''' is not supported'])
161end
162
163% close the file
164fclose(f);
165
166end
167