1use crate::*;
26
27use super::types::*;
28
29use std::io::Write;
30
31pub fn save_ply_ascii<M, P, W>(write: &mut W, mesh: &M) -> PlyResult<()>
35where
36 M: IsMesh<P, Face3>,
37 P: IsBuildable3D,
38 W: Write,
39{
40 let header = "ply\n".to_string()
41 + "format ascii 1.0\n"
42 + "comment Created by rust-3d\n"
43 + "element vertex "
44 + &mesh.num_vertices().to_string()
45 + "\n"
46 + "property float x\n"
47 + "property float y\n"
48 + "property float z\n"
49 + "element face "
50 + &mesh.num_faces().to_string()
51 + "\n"
52 + "property list uchar uint vertex_indices\n"
53 + "end_header\n";
54 write.write_all(header.as_bytes())?;
55
56 for i in 0..mesh.num_vertices() {
57 let vertex = mesh.vertex(VId { val: i }).unwrap(); write.write_all((vertex.to_str() + "\n").as_bytes())?;
59 }
60
61 for i in 0..mesh.num_faces() {
62 let face = mesh.face_vertex_ids(FId { val: i }).unwrap(); write.write_all(
64 ("3 ".to_string()
65 + &face.a.to_string()
66 + " "
67 + &face.b.to_string()
68 + " "
69 + &face.c.to_string()
70 + "\n")
71 .as_bytes(),
72 )?;
73 }
74 Ok(())
75}
76
77pub fn save_ply_ascii_colored<M, P, W>(write: &mut W, mesh: &M, colors: &Vec<Rgb>) -> PlyResult<()>
81where
82 M: IsMesh<P, Face3>,
83 P: IsBuildable3D,
84 W: Write,
85{
86 let n_vertices = mesh.num_vertices();
87 let n_faces = mesh.num_faces();
88
89 if n_vertices != colors.len() {
90 return Err(PlyError::ColorArrayIncorrectLength);
91 }
92
93 let header = "ply\n".to_string()
94 + "format ascii 1.0\n"
95 + "comment Created by rust-3d\n"
96 + "element vertex "
97 + &n_vertices.to_string()
98 + "\n"
99 + "property float x\n"
100 + "property float y\n"
101 + "property float z\n"
102 + "property uchar red\n"
103 + "property uchar green\n"
104 + "property uchar blue\n"
105 + "element face "
106 + &n_faces.to_string()
107 + "\n"
108 + "property list uchar uint vertex_indices\n"
109 + "end_header\n";
110 write.write_all(header.as_bytes())?;
111
112 for i in 0..n_vertices {
113 let vertex = mesh.vertex(VId { val: i }).unwrap(); let color = &colors[i];
115 write.write_all(
116 format!(
117 "{} {} {} {} {} {}\n",
118 vertex.x(),
119 vertex.y(),
120 vertex.z(),
121 color.r,
122 color.g,
123 color.b
124 )
125 .as_bytes(),
126 )?;
127 }
128
129 for i in 0..n_faces {
130 let face = mesh.face_vertex_ids(FId { val: i }).unwrap(); write.write_all(
132 ("3 ".to_string()
133 + &face.a.to_string()
134 + " "
135 + &face.b.to_string()
136 + " "
137 + &face.c.to_string()
138 + "\n")
139 .as_bytes(),
140 )?;
141 }
142 Ok(())
143}
144
145pub fn save_ply_binary<M, P, W>(write: &mut W, mesh: &M, precision: &Precision) -> PlyResult<()>
149where
150 M: IsMesh<P, Face3>,
151 P: IsBuildable3D,
152 W: Write,
153{
154 let header = match precision {
155 Precision::P32 => {
156 "ply\n".to_string()
157 + "format binary_big_endian 1.0\n"
158 + "comment Created by rust-3d\n"
159 + "element vertex "
160 + &mesh.num_vertices().to_string()
161 + "\n"
162 + "property float x\n"
163 + "property float y\n"
164 + "property float z\n"
165 + "element face "
166 + &mesh.num_faces().to_string()
167 + "\n"
168 + "property list uint8 uint32 vertex_indices\n"
169 + "end_header\n"
170 }
171 Precision::P64 => {
172 "ply\n".to_string()
173 + "format binary_big_endian 1.0\n"
174 + "comment Created by rust-3d\n"
175 + "element vertex "
176 + &mesh.num_vertices().to_string()
177 + "\n"
178 + "property double x\n"
179 + "property double y\n"
180 + "property double z\n"
181 + "element face "
182 + &mesh.num_faces().to_string()
183 + "\n"
184 + "property list uint8 uint32 vertex_indices\n"
185 + "end_header\n"
186 }
187 };
188
189 write.write_all(header.as_bytes())?;
190
191 match precision {
192 Precision::P32 => {
193 for i in 0..mesh.num_vertices() {
194 let vertex = mesh.vertex(VId { val: i }).unwrap(); write.write(&(vertex.x() as f32).to_be_bytes())?;
196 write.write(&(vertex.y() as f32).to_be_bytes())?;
197 write.write(&(vertex.z() as f32).to_be_bytes())?;
198 }
199 }
200
201 Precision::P64 => {
202 for i in 0..mesh.num_vertices() {
203 let vertex = mesh.vertex(VId { val: i }).unwrap(); write.write(&(vertex.x()).to_be_bytes())?;
205 write.write(&(vertex.y()).to_be_bytes())?;
206 write.write(&(vertex.z()).to_be_bytes())?;
207 }
208 }
209 }
210
211 for i in 0..mesh.num_faces() {
212 let face = mesh.face_vertex_ids(FId { val: i }).unwrap(); write.write(&3u8.to_be_bytes())?;
214 write.write(&(face.a.val as u32).to_be_bytes())?;
215 write.write(&(face.b.val as u32).to_be_bytes())?;
216 write.write(&(face.c.val as u32).to_be_bytes())?;
217 }
218
219 Ok(())
220}
221
222pub fn save_ply_binary_colored<M, P, W>(
226 write: &mut W,
227 mesh: &M,
228 precision: &Precision,
229 colors: &Vec<Rgb>,
230) -> PlyResult<()>
231where
232 M: IsMesh<P, Face3>,
233 P: IsBuildable3D,
234 W: Write,
235{
236 let n_vertices = mesh.num_vertices();
237 let n_faces = mesh.num_faces();
238
239 if n_vertices != colors.len() {
240 return Err(PlyError::ColorArrayIncorrectLength);
241 }
242
243 let header = match precision {
244 Precision::P32 => {
245 "ply\n".to_string()
246 + "format binary_big_endian 1.0\n"
247 + "comment Created by rust-3d\n"
248 + "element vertex "
249 + &n_vertices.to_string()
250 + "\n"
251 + "property float x\n"
252 + "property float y\n"
253 + "property float z\n"
254 + "property uchar red\n"
255 + "property uchar green\n"
256 + "property uchar blue\n"
257 + "element face "
258 + &n_faces.to_string()
259 + "\n"
260 + "property list uint8 uint32 vertex_indices\n"
261 + "end_header\n"
262 }
263 Precision::P64 => {
264 "ply\n".to_string()
265 + "format binary_big_endian 1.0\n"
266 + "comment Created by rust-3d\n"
267 + "element vertex "
268 + &n_vertices.to_string()
269 + "\n"
270 + "property double x\n"
271 + "property double y\n"
272 + "property double z\n"
273 + "property uchar red\n"
274 + "property uchar green\n"
275 + "property uchar blue\n"
276 + "element face "
277 + &n_faces.to_string()
278 + "\n"
279 + "property list uint8 uint32 vertex_indices\n"
280 + "end_header\n"
281 }
282 };
283
284 write.write_all(header.as_bytes())?;
285
286 match precision {
287 Precision::P32 => {
288 for i in 0..n_vertices {
289 let vertex = mesh.vertex(VId { val: i }).unwrap(); let color = &colors[i];
291 write.write(&(vertex.x() as f32).to_be_bytes())?;
292 write.write(&(vertex.y() as f32).to_be_bytes())?;
293 write.write(&(vertex.z() as f32).to_be_bytes())?;
294 write.write(&color.r.to_be_bytes())?;
295 write.write(&color.g.to_be_bytes())?;
296 write.write(&color.b.to_be_bytes())?;
297 }
298 }
299
300 Precision::P64 => {
301 for i in 0..n_vertices {
302 let vertex = mesh.vertex(VId { val: i }).unwrap(); let color = &colors[i];
304 write.write(&(vertex.x()).to_be_bytes())?;
305 write.write(&(vertex.y()).to_be_bytes())?;
306 write.write(&(vertex.z()).to_be_bytes())?;
307 write.write(&color.r.to_be_bytes())?;
308 write.write(&color.g.to_be_bytes())?;
309 write.write(&color.b.to_be_bytes())?;
310 }
311 }
312 }
313
314 for i in 0..n_faces {
315 let face = mesh.face_vertex_ids(FId { val: i }).unwrap(); write.write(&3u8.to_be_bytes())?;
317 write.write(&(face.a.val as u32).to_be_bytes())?;
318 write.write(&(face.b.val as u32).to_be_bytes())?;
319 write.write(&(face.c.val as u32).to_be_bytes())?;
320 }
321
322 Ok(())
323}