export.hpp 29.7 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1
2
3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
Pierre Kraemer's avatar
Pierre Kraemer committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
Pierre Kraemer's avatar
Pierre Kraemer committed
21
22
23
24
25
26
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#include "Topology/generic/attributeHandler.h"
#include "Topology/generic/autoAttributeHandler.h"
27
28
#include "Topology/generic/traversorCell.h"
#include "Topology/generic/traversor2.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
29
30
31
32
33
34
35
36
37
38
39
40
#include "Topology/generic/cellmarker.h"

namespace CGoGN
{

namespace Algo
{

namespace Export
{

template <typename PFP>
41
bool exportPLY(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, bool binary, const FunctorSelect& good)
Pierre Kraemer's avatar
Pierre Kraemer committed
42
43
44
45
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
	
46
	// open file
47
	std::ofstream out ;
48
	if (!binary)
49
		out.open(filename, std::ios::out) ;
50
51
52
	else
		out.open(filename, std::ios::out | std::ios::binary) ;

Pierre Kraemer's avatar
Pierre Kraemer committed
53
54
	if (!out.good())
	{
55
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
56
57
58
59
60
61
62
63
64
65
66
67
68
		return false ;
	}

	unsigned int nbDarts = map.getNbDarts() ;
	std::vector<unsigned int> facesSize ;
	std::vector<std::vector<unsigned int> > facesIdx ;
	facesSize.reserve(nbDarts/3) ;
	facesIdx.reserve(nbDarts/3) ;
	std::map<unsigned int, unsigned int> vIndex ;
	unsigned int vCpt = 0 ;
	std::vector<unsigned int> vertices ;
	vertices.reserve(nbDarts/6) ;

69
	// Go over all faces
70
	CellMarker markV(map, VERTEX) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
71
	TraversorF<MAP> t(map, good) ;
72
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
73
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
74
75
76
77
78
		std::vector<unsigned int> fidx ;
		fidx.reserve(8) ;
		unsigned int degree = 0 ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
79
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
80
81
82
			++degree ;
			unsigned int vNum = map.getEmbedding(VERTEX, it) ;
			if(!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
83
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
84
85
86
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
87
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
88
			fidx.push_back(vIndex[vNum]) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
89
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
90
91
		facesSize.push_back(degree) ;
		facesIdx.push_back(fidx) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
92
93
	}

94
	// Start writing the file
95
	out << "ply" << std::endl ;
96
	// ascii or binary
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
	if (!binary)
		out << "format ascii 1.0" << std::endl ;
	else
	{	// test endianness
		union
		{
		    uint32_t i ;
		    char c[4] ;
		} bint = {0x01020304} ;
		if (bint.c[0] == 1) // big endian
			out << "format binary_big_endian 1.0" << std::endl ;
		else
			out << "format binary_little_endian 1.0" << std::endl ;
	}

	out << "comment File generated by the CGoGN library" << std::endl ;
	out << "comment See : http://cgogn.unistra.fr/" << std::endl ;
114
115
	out << "comment or contact : cgogn@unistra.fr" << std::endl ;
	// Vertex elements
116
	out << "element vertex " << vertices.size() << std::endl ;
117
	// Position property
118
119
	if (position.isValid())
	{
120
121
122
		out << "property " << nameOfTypePly(position[0][0]) << " x" << std::endl ;
		out << "property " << nameOfTypePly(position[0][1]) << " y" << std::endl ;
		out << "property " << nameOfTypePly(position[0][2]) << " z" << std::endl ;
123
	}
124
	// Face element
125
	out << "element face " << facesSize.size() << std::endl ;
126
	out << "property list uint8 uint" << 8 * sizeof(facesIdx[0][0]) << " vertex_indices" << std::endl ;
127
	out << "end_header" << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
128

129
	if (!binary)	// ascii
Pierre Kraemer's avatar
Pierre Kraemer committed
130
	{
131
		// ascii vertices
132
133
134
		for(unsigned int i = 0; i < vertices.size(); ++i)
			out << position[vertices[i]] << std::endl ;

135
		// ascii faces
136
137
138
139
140
141
142
		for(unsigned int i = 0; i < facesSize.size(); ++i)
		{
			out << facesSize[i] ;
			for(unsigned int j = 0; j < facesIdx[i].size(); ++j)
				out << " " << facesIdx[i][j] ;
			out << std::endl ;
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
143
	}
144
	else // binary
Pierre Kraemer's avatar
Pierre Kraemer committed
145
	{
146
		// binary vertices
147
148
149
		for(unsigned int i = 0; i < vertices.size(); ++i)
		{
			Geom::Vec3f v = position[vertices[i]] ;
150
			out.write((char*)(&(v[0])), sizeof(v)) ;
151
152
		}

153
		// binary faces
154
155
156
157
		for(unsigned int i = 0; i < facesSize.size(); ++i)
		{
			unsigned char nbe = facesSize[i] ;
			out.write((char*)(&nbe), sizeof(unsigned char)) ;
158
159
160
161
162
163
164
165
166
167
			out.write((char*)(&(facesIdx[i][0])), facesSize[i] * sizeof(facesIdx[i][0])) ;
		}
	}

	out.close() ;

	return true ;
}

template <typename PFP>
168
bool exportPLYnew(typename PFP::MAP& map, const std::vector<typename PFP::TVEC3*>& attributeHandlers, const char* filename, bool binary, const FunctorSelect& good)
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;

	// open file
	std::ofstream out ;
	if (!binary)
		out.open(filename, std::ios::out) ;
	else
		out.open(filename, std::ios::out | std::ios::binary) ;

	if (!out.good())
	{
		CGoGNerr << "Unable to open file " << CGoGNendl ;
		return false ;
	}

	unsigned int nbDarts = map.getNbDarts() ;
	std::vector<unsigned int> facesSize ;
	std::vector<std::vector<unsigned int> > facesIdx ;
	facesSize.reserve(nbDarts/3) ;
	facesIdx.reserve(nbDarts/3) ;
	std::map<unsigned int, unsigned int> vIndex ;
	unsigned int vCpt = 0 ;
	std::vector<unsigned int> vertices ;
	vertices.reserve(nbDarts/6) ;

	// Go over all faces
	CellMarker markV(map, VERTEX) ;
	TraversorF<MAP> t(map, good) ;
	for(Dart d = t.begin(); d != t.end(); d = t.next())
	{
		std::vector<unsigned int> fidx ;
		fidx.reserve(8) ;
		unsigned int degree = 0 ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
		{
			++degree ;
			unsigned int vNum = map.getEmbedding(VERTEX, it) ;
			if(!markV.isMarked(it))
			{
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
			}
			fidx.push_back(vIndex[vNum]) ;
		}
		facesSize.push_back(degree) ;
		facesIdx.push_back(fidx) ;
	}

	// Start writing the file
	out << "ply" << std::endl ;
	// ascii or binary
	if (!binary)
		out << "format ascii 1.0" << std::endl ;
	else
	{	// test endianness
		union
		{
		    uint32_t i ;
		    char c[4] ;
		} bint = {0x01020304} ;
		if (bint.c[0] == 1) // big endian
			out << "format binary_big_endian 1.0" << std::endl ;
		else
			out << "format binary_little_endian 1.0" << std::endl ;
	}

	out << "comment File generated by the CGoGN library" << std::endl ;
	out << "comment See : http://cgogn.unistra.fr/" << std::endl ;
	out << "comment or contact : cgogn@unistra.fr" << std::endl ;
	// Vertex elements
	out << "element vertex " << vertices.size() << std::endl ;
244
	for (typename std::vector<typename PFP::TVEC3* >::const_iterator attrHandler = attributeHandlers.begin() ; attrHandler != attributeHandlers.end() ; ++attrHandler)
245
	{
246
		if ((*attrHandler)->isValid() && ((*attrHandler)->getOrbit() == VERTEX) )
247
		{
248
			if ((*attrHandler)->name().compare("position") == 0)  // Vertex position property
249
			{
250
251
252
				out << "property " << nameOfTypePly((*(*attrHandler))[0][0]) << " x" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][1]) << " y" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][2]) << " z" << std::endl ;
253
			}
254
			else if ((*attrHandler)->name().compare("normal") == 0)	// normal property
255
			{
256
257
258
				out << "property " << nameOfTypePly((*(*attrHandler))[0][0]) << " nx" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][1]) << " ny" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][2]) << " nz" << std::endl ;
259
			}
260
			else if ((*attrHandler)->name().compare("color") == 0)	// vertex color property
261
			{
262
263
264
				out << "property " << nameOfTypePly((*(*attrHandler))[0][0]) << " red" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][1]) << " green" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][2]) << " blue" << std::endl ;
265
266
267
			}
			else // other vertex properties
			{
268
269
270
				out << "property " << nameOfTypePly((*(*attrHandler))[0][0]) << " " << (*attrHandler)->name() << "_0" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][1]) << " " << (*attrHandler)->name() << "_1" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][2]) << " " << (*attrHandler)->name() << "_2" << std::endl ;
271
272
273
274
275
276
			}
		}
	}

	// Face element
	out << "element face " << facesSize.size() << std::endl ;
277
	out << "property list uint8 " << nameOfTypePly(facesIdx[0][0]) << " vertex_indices" << std::endl ;
278
279
280
281
282
283
	out << "end_header" << std::endl ;

	if (!binary)	// ascii
	{
		// ascii vertices
		for(unsigned int i = 0; i < vertices.size(); ++i)
284
		{
285
286
			for (typename std::vector<typename PFP::TVEC3* >::const_iterator attrHandler = attributeHandlers.begin() ; attrHandler != attributeHandlers.end() ; ++attrHandler)
				if ((*attrHandler)->isValid() && (*attrHandler)->getOrbit() == VERTEX)
287
288
289
					out << (*(*attrHandler))[vertices[i]] ;
			out << std::endl ;
		}
290
291
292
293
294
295
296
297
298
299
300
301
302
303

		// ascii faces
		for(unsigned int i = 0; i < facesSize.size(); ++i)
		{
			out << facesSize[i] ;
			for(unsigned int j = 0; j < facesIdx[i].size(); ++j)
				out << " " << facesIdx[i][j] ;
			out << std::endl ;
		}
	}
	else // binary
	{
		// binary vertices
		for(unsigned int i = 0; i < vertices.size(); ++i)
304
			for (typename std::vector<typename PFP::TVEC3*>::const_iterator attrHandler = attributeHandlers.begin() ; attrHandler != attributeHandlers.end() ; ++attrHandler)
305
			{
306
				if ((*attrHandler)->isValid() && (*attrHandler)->getOrbit() == VERTEX)
307
				{
308
					const typename PFP::VEC3& v = (*(*attrHandler))[vertices[i]] ;
309
310
					out.write((char*)(&(v[0])), sizeof(v)) ;
				}
311
			}
312
313
314
315

		// binary faces
		for(unsigned int i = 0; i < facesSize.size(); ++i)
		{
316
			uint8_t nbe = facesSize[i] ;
317
			out.write((char*)(&nbe), sizeof(uint8_t)) ;
318
			out.write((char*)(&(facesIdx[i][0])), facesSize[i] * sizeof(facesIdx[i][0])) ;
319
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
320
321
322
	}

	out.close() ;
323

Pierre Kraemer's avatar
Pierre Kraemer committed
324
325
326
327
328
329
330
331
332
333
334
335
	return true ;
}

template <typename PFP>
bool exportOFF(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, const FunctorSelect& good)
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
	
	std::ofstream out(filename, std::ios::out) ;
	if (!out.good())
	{
336
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
337
338
339
340
341
342
343
344
345
346
347
348
349
		return false ;
	}

	unsigned int nbDarts = map.getNbDarts() ;
	std::vector<unsigned int> facesSize ;
	std::vector<std::vector<unsigned int> > facesIdx ;
	facesSize.reserve(nbDarts/3) ;
	facesIdx.reserve(nbDarts/3) ;
	std::map<unsigned int, unsigned int> vIndex ;
	unsigned int vCpt = 0 ;
	std::vector<unsigned int> vertices ;
	vertices.reserve(nbDarts/6) ;

350
	CellMarker markV(map, VERTEX) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
351
	TraversorF<MAP> t(map, good) ;
352
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
353
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
354
355
356
357
358
		std::vector<unsigned int> fidx ;
		fidx.reserve(8) ;
		unsigned int degree = 0 ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
359
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
360
361
362
			++degree ;
			unsigned int vNum = map.getEmbedding(VERTEX, it) ;
			if(!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
363
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
364
365
366
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
367
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
368
			fidx.push_back(vIndex[vNum]) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
369
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
370
371
		facesSize.push_back(degree) ;
		facesIdx.push_back(fidx) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
372
373
	}

374
375
	out << "OFF" << std::endl ;
	out << vertices.size() << " " << facesSize.size() << " " << 0 << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
376
377
378
379

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		const VEC3& v = position[vertices[i]] ;
380
		out << v[0] << " " << v[1] << " " << v[2] << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
381
382
383
384
385
386
	}
	for(unsigned int i = 0; i < facesSize.size(); ++i)
	{
		out << facesSize[i] ;
		for(unsigned int j = 0; j < facesIdx[i].size(); ++j)
			out << " " << facesIdx[i][j] ;
387
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
388
389
390
391
392
393
	}

	out.close() ;
	return true ;
}

394
template <typename PFP>
395
bool exportPlyPTMgeneric(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, const FunctorSelect& good)
396
397
398
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
399
400
401
	typedef typename PFP::TVEC3 TVEC3;
	typedef typename PFP::REAL REAL;
	typedef typename PFP::TREAL TREAL;
402
403
404
405

	std::ofstream out(filename, std::ios::out) ;
	if (!out.good())
	{
406
		CGoGNerr << "Unable to open file " << filename << CGoGNendl ;
407
408
409
		return false ;
	}

410
	AutoAttributeHandler<unsigned int> tableVertLab(map, VERTEX);
411
412
413
414
415
416
417
418
419
420


	unsigned int nbDarts = map.getNbDarts() ;

	std::vector<unsigned int> vertices;
	std::vector<unsigned int> faces;

	vertices.reserve(nbDarts/5);	// TODO non optimal reservation
	faces.reserve(nbDarts/3);

421
	CellMarker markV(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
422
	TraversorF<MAP> t(map, good) ;
423
424
	unsigned int lab = 0;
	unsigned int nbf = 0;
425
	for(Dart d = t.begin(); d != t.end(); d = t.next())
426
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
427
428
429
		std::vector<unsigned int> face ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
430
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
431
			if (!markV.isMarked(it))
432
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
433
434
435
				markV.mark(it);
				tableVertLab[it] = lab++;
				vertices.push_back(map.getEmbedding(VERTEX, it));
436
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
437
438
			face.push_back(tableVertLab[it]);
		}
439

Pierre Kraemer's avatar
Pierre Kraemer committed
440
441
442
		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;
443

Pierre Kraemer's avatar
Pierre Kraemer committed
444
		++nbf;
445
446
	}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
447
448
449
450
451
452
453
454
455
456
457
458
	TVEC3 frame[3] ;
	TVEC3 colorPTM[15] ;

	frame[0] = map.template getAttribute<VEC3>(VERTEX, "frame_T") ;
	frame[1] = map.template getAttribute<VEC3>(VERTEX, "frame_B") ;
	frame[2] = map.template getAttribute<VEC3>(VERTEX, "frame_N") ;
	for (unsigned i = 0 ; i < 15 ; ++i)
	{
		std::stringstream name ;
		name << "colorPTM_a" << i ;
		colorPTM[i] = map.template getAttribute<VEC3>(VERTEX,name.str()) ;
	}
459
	const unsigned int nbCoefs = colorPTM[14].isValid() ? 15 : (colorPTM[9].isValid() ? 10 : 6) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
460

461
462
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
463
	out << "comment ply PTM (K. Vanhoey generic format)" << std::endl ;
464
465
466
467
468
469
470
471
472
473
474
475
476
	out << "element vertex " << vertices.size() << std::endl ;
	out << "property float x" << std::endl ;
	out << "property float y" << std::endl ;
	out << "property float z" << std::endl ;
	out << "property float tx" << std::endl ;
	out << "property float ty" << std::endl ;
	out << "property float tz" << std::endl ;
	out << "property float bx" << std::endl ;
	out << "property float by" << std::endl ;
	out << "property float bz" << std::endl ;
	out << "property float nx" << std::endl ;
	out << "property float ny" << std::endl ;
	out << "property float nz" << std::endl ;
477
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
478
		out << "property float C0_a" << coefI << std::endl ;
479
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
480
		out << "property float C1_a" << coefI << std::endl ;
481
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
482
		out << "property float C2_a" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
483
484
485

	TREAL errL2 = map.template getAttribute<REAL>(VERTEX,"errL2") ;
	TREAL errLmax = map.template getAttribute<REAL>(VERTEX,"errLmax") ;
486
	TREAL stdDev = map.template getAttribute<REAL>(VERTEX,"stdDev") ;
487
488
489
490
491
492
	if (errL2.isValid())
		out << "property float errL2" << std::endl ;
	if (errLmax.isValid())
		out << "property float errLmax" << std::endl ;
	if (stdDev.isValid())
		out << "property float stdDev" << std::endl ;
493
494
495
496
497

	out << "element face " << nbf << std::endl ;
	out << "property list uchar int vertex_indices" << std::endl ;
	out << "end_header" << std::endl ;

498
499
500
	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
501
502
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
503
			out << position[vi][coord] << " " ;
504
505
506
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
507
				out << frame[axis][vi][coord] << " " ;
508
509
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
510
511
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
				out << colorPTM[coefI][vi][channel] << " "  ;
512
513
		 // fitting errors (if any)
		if (errL2.isValid())
514
515
516
517
518
519
			out << errL2[vi] << " " ;
		if (errLmax.isValid())
			out << errLmax[vi] << " " ;
		if (stdDev.isValid())
			out << stdDev[vi] << " " ;
		out << std::endl ;
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
	}

	std::vector<unsigned int>::iterator it = faces.begin();
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
		out << nbe ;
		for(unsigned int j = 0; j < nbe; ++j)
			out << " " << *it++;
		out << std::endl ;
	}

	out.close() ;
	return true ;
}
535
/*
536
template <typename PFP>
537
bool exportPlySLFgeneric(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, const FunctorSelect& good)
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
	typedef typename PFP::TVEC3 TVEC3;
	typedef typename PFP::REAL REAL;
	typedef typename PFP::TREAL TREAL;

	std::ofstream out(filename, std::ios::out) ;
	if (!out.good())
	{
		CGoGNerr << "Unable to open file " << filename << CGoGNendl ;
		return false ;
	}

	AutoAttributeHandler<unsigned int> tableVertLab(map, VERTEX);


	unsigned int nbDarts = map.getNbDarts() ;

	std::vector<unsigned int> vertices;
	std::vector<unsigned int> faces;

	vertices.reserve(nbDarts/5);	// TODO non optimal reservation
	faces.reserve(nbDarts/3);

	CellMarker markV(map, VERTEX);
	TraversorF<MAP> t(map, good) ;
	unsigned int lab = 0;
	unsigned int nbf = 0;
	for(Dart d = t.begin(); d != t.end(); d = t.next())
	{
		std::vector<unsigned int> face ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
		{
			if (!markV.isMarked(it))
			{
				markV.mark(it);
				tableVertLab[it] = lab++;
				vertices.push_back(map.getEmbedding(VERTEX, it));
			}
			face.push_back(tableVertLab[it]);
		}

		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;

		++nbf;
	}

	TVEC3 frame[3] ;
590
	std::vector<TVEC3> coefs ;
591
592
593
594

	frame[0] = map.template getAttribute<VEC3>(VERTEX, "frame_T") ;
	frame[1] = map.template getAttribute<VEC3>(VERTEX, "frame_B") ;
	frame[2] = map.template getAttribute<VEC3>(VERTEX, "frame_N") ;
595
596
597

	unsigned int i = 0 ;
	do {
598
		std::stringstream name ;
599
600
601
602
603
604
605
		name << "SLFcoefs_" << i++ ;
		coefs.push_back(map.template getAttribute<VEC3>(VERTEX, name.str())) ;
	} while (coefs[i-1].isValid()) ;
	const unsigned int nbCoefs = i - 1 ; // last valid one is i-2

	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
		assert(coefs[coefI].isValid()) ;
606

607
608
609
610
	std::string file(filename) ;
	size_t pos = file.rfind(".") ; // position of "." in filename
	std::string extension = file.substr(pos) ;

611
612
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
kenneth's avatar
kenneth committed
613
	out << "comment ply SLF (K. Vanhoey generic format): SLF_" << (((extension == ".plyPTMext") || extension == ".plyPTMextBin" ) ? "PTMext" : "SHreal") << std::endl ;
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
	out << "element vertex " << vertices.size() << std::endl ;
	out << "property float x" << std::endl ;
	out << "property float y" << std::endl ;
	out << "property float z" << std::endl ;
	out << "property float tx" << std::endl ;
	out << "property float ty" << std::endl ;
	out << "property float tz" << std::endl ;
	out << "property float bx" << std::endl ;
	out << "property float by" << std::endl ;
	out << "property float bz" << std::endl ;
	out << "property float nx" << std::endl ;
	out << "property float ny" << std::endl ;
	out << "property float nz" << std::endl ;
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
		out << "property float C0_" << coefI << std::endl ;
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
		out << "property float C1_" << coefI << std::endl ;
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
		out << "property float C2_" << coefI << std::endl ;

	out << "element face " << nbf << std::endl ;
	out << "property list uchar int vertex_indices" << std::endl ;
	out << "end_header" << std::endl ;

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
			out << position[vi][coord] << " " ;
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
				out << frame[axis][vi][coord] << " " ;
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
				out << coefs[coefI][vi][channel] << " "  ;

		out << std::endl ;
	}

	std::vector<unsigned int>::iterator it = faces.begin();
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
		out << nbe ;
		for(unsigned int j = 0; j < nbe; ++j)
			out << " " << *it++;
		out << std::endl ;
	}

	out.close() ;
	return true ;
}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
670
671
672
673
674
675
676
677
678
template <typename PFP>
bool exportPlySLFgenericBin(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, const FunctorSelect& good)
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
	typedef typename PFP::TVEC3 TVEC3;
	typedef typename PFP::REAL REAL;
	typedef typename PFP::TREAL TREAL;

679
	std::ofstream out(filename, std::ios::out) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
	if (!out.good())
	{
		CGoGNerr << "Unable to open file " << filename << CGoGNendl ;
		return false ;
	}

	AutoAttributeHandler<unsigned int> tableVertLab(map, VERTEX);

	unsigned int nbDarts = map.getNbDarts() ;

	std::vector<unsigned int> vertices;
	std::vector<unsigned int> faces;

	vertices.reserve(nbDarts/5);	// TODO non optimal reservation
	faces.reserve(nbDarts/3);

	CellMarker markV(map, VERTEX);
	TraversorF<MAP> t(map, good) ;
	unsigned int lab = 0;
	unsigned int nbf = 0;
	for(Dart d = t.begin(); d != t.end(); d = t.next())
	{
		std::vector<unsigned int> face ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
		{
			if (!markV.isMarked(it))
			{
				markV.mark(it);
				tableVertLab[it] = lab++;
				vertices.push_back(map.getEmbedding(VERTEX, it));
			}
			face.push_back(tableVertLab[it]);
		}

		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;

		++nbf;
	}

	TVEC3 frame[3] ;
	std::vector<TVEC3> coefs ;

	frame[0] = map.template getAttribute<VEC3>(VERTEX, "frame_T") ;
	frame[1] = map.template getAttribute<VEC3>(VERTEX, "frame_B") ;
	frame[2] = map.template getAttribute<VEC3>(VERTEX, "frame_N") ;

	unsigned int i = 0 ;
	do {
		std::stringstream name ;
		name << "SLFcoefs_" << i++ ;
		coefs.push_back(map.template getAttribute<VEC3>(VERTEX, name.str())) ;
	} while (coefs[i-1].isValid()) ;
	const unsigned int nbCoefs = i - 1 ; // last valid one is i-2

	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
		assert(coefs[coefI].isValid()) ;

	std::string file(filename) ;
	size_t pos = file.rfind(".") ; // position of "." in filename
	std::string extension = file.substr(pos) ;

744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
	out << "comment ply SLF (K. Vanhoey generic format): SLF_" << ((extension == ".plyPTMext") ? "PTMext" : "SHreal") << std::endl ;
	out << "element vertex " << vertices.size() << std::endl ;
	out << "property float x" << std::endl ;
	out << "property float y" << std::endl ;
	out << "property float z" << std::endl ;
	out << "property float tx" << std::endl ;
	out << "property float ty" << std::endl ;
	out << "property float tz" << std::endl ;
	out << "property float bx" << std::endl ;
	out << "property float by" << std::endl ;
	out << "property float bz" << std::endl ;
	out << "property float nx" << std::endl ;
	out << "property float ny" << std::endl ;
	out << "property float nz" << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
760
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
761
		out << "property float C0_" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
762
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
763
		out << "property float C1_" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
764
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
765
		out << "property float C2_" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
766

767
768
769
	out << "element face " << nbf << std::endl ;
	out << "property list uchar int vertex_indices" << std::endl ;
	out << "end_header" << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
770
771
772
773
774
775

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
776
777
778
779
		{
			const float& floatofdouble = position[vi][coord] ;
			out.write((char*)(&floatofdouble), sizeof(float)) ;
		}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
780
781
782
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
783
784
785
786
			{
				const float& floatofdouble = frame[axis][vi][coord] ;
				out.write((char*)(&floatofdouble), sizeof(float)) ;
			}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
787
788
789
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
790
791
792
793
			{
				const float& floatofdouble = coefs[coefI][vi][channel] ;
				out.write((char*)(&floatofdouble), sizeof(float)) ;
			}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
794
795
796
797
798
799
	}

	std::vector<unsigned int>::iterator it = faces.begin();
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
800
		out.write((char*)&nbe, sizeof(unsigned int)) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
801
		for(unsigned int j = 0; j < nbe; ++j)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
802
803
804
805
		{
			unsigned int index = *it++ ;
			out.write((char*)(&index), sizeof(unsigned int)) ;
		}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
806
807
808
809
810
	}

	out.close() ;
	return true ;
}
811
*/
812

Pierre Kraemer's avatar
Pierre Kraemer committed
813
template <typename PFP>
814
bool exportPLYPTM(typename PFP::MAP& map, const char* filename, const typename PFP::TVEC3& position, const typename PFP::TVEC3 frame[3], const typename PFP::TVEC3 colorPTM[6], const FunctorSelect& good)
Pierre Kraemer's avatar
Pierre Kraemer committed
815
816
817
818
819
820
821
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;

	std::ofstream out(filename, std::ios::out) ;
	if (!out.good())
	{
822
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
823
824
825
		return false ;
	}

826
	AutoAttributeHandler<unsigned int> tableVertLab(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
827
828
829
830
831
832
833
834
835

	unsigned int nbDarts = map.getNbDarts() ;

	std::vector<unsigned int> vertices;
	std::vector<unsigned int> faces;

	vertices.reserve(nbDarts/5);	// TODO non optimal reservation
	faces.reserve(nbDarts/3);

836
	CellMarker markV(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
837
	TraversorF<MAP> t(map, good) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
838
839
	unsigned int lab = 0;
	unsigned int nbf = 0;
840
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
841
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
842
843
844
		std::vector<unsigned int> face ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
845
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
846
			if (!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
847
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
848
849
850
				markV.mark(it);
				tableVertLab[it] = lab++;
				vertices.push_back(map.getEmbedding(VERTEX, it));
851
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
852
853
			face.push_back(tableVertLab[it]);
		}
854

Pierre Kraemer's avatar
Pierre Kraemer committed
855
856
857
		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;
858

Pierre Kraemer's avatar
Pierre Kraemer committed
859
		++nbf;
Pierre Kraemer's avatar
Pierre Kraemer committed
860
861
	}

862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
	out << "comment ply PTM (F. Larue format)" << std::endl ;
	out << "element vertex " << vertices.size() << std::endl ;
	out << "property float x" << std::endl ;
	out << "property float y" << std::endl ;
	out << "property float z" << std::endl ;
	out << "property float tx" << std::endl ;
	out << "property float ty" << std::endl ;
	out << "property float tz" << std::endl ;
	out << "property float bx" << std::endl ;
	out << "property float by" << std::endl ;
	out << "property float bz" << std::endl ;
	out << "property float nx" << std::endl ;
	out << "property float ny" << std::endl ;
	out << "property float nz" << std::endl ;
	out << "property float L1_a" << std::endl ;
	out << "property float L1_b" << std::endl ;
	out << "property float L1_c" << std::endl ;
	out << "property float L1_d" << std::endl ;
	out << "property float L1_e" << std::endl ;
	out << "property float L1_f" << std::endl ;
	out << "property float L2_a" << std::endl ;
	out << "property float L2_b" << std::endl ;
	out << "property float L2_c" << std::endl ;
	out << "property float L2_d" << std::endl ;
	out << "property float L2_e" << std::endl ;
	out << "property float L2_f" << std::endl ;
	out << "property float L3_a" << std::endl ;
	out << "property float L3_b" << std::endl ;
	out << "property float L3_c" << std::endl ;
	out << "property float L3_d" << std::endl ;
	out << "property float L3_e" << std::endl ;
	out << "property float L3_f" << std::endl ;
	out << "element face " << nbf << std::endl ;
	out << "property list uchar int vertex_indices" << std::endl ;
	out << "end_header" << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
899
900
901
902

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
903
904
905
906
907
908
		out << position[vi][0] << " " << position[vi][1] << " " << position[vi][2] << " " ;
		out << frame[0][vi][0] << " " << frame[0][vi][1] << " " << frame[0][vi][2] << " " ;
		out << frame[1][vi][0] << " " << frame[1][vi][1] << " " << frame[1][vi][2] << " " ;
		out << frame[2][vi][0] << " " << frame[2][vi][1] << " " << frame[2][vi][2] << " " ;
		out << colorPTM[0][vi][0] << " " << colorPTM[1][vi][0] << " " << colorPTM[2][vi][0] << " " << colorPTM[3][vi][0] << " " << colorPTM[4][vi][0] << " " << colorPTM[5][vi][0] <<" " ;
		out << colorPTM[0][vi][1] << " " << colorPTM[1][vi][1] << " " << colorPTM[2][vi][1] << " " << colorPTM[3][vi][1] << " " << colorPTM[4][vi][1] << " " << colorPTM[5][vi][1] <<" " ;
909
		out << colorPTM[0][vi][2] << " " << colorPTM[1][vi][2] << " " << colorPTM[2][vi][2] << " " << colorPTM[3][vi][2] << " " << colorPTM[4][vi][2] << " " << colorPTM[5][vi][2] << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
910
911
	}

912
	std::vector<unsigned int>::iterator it = faces.begin();
Pierre Kraemer's avatar
Pierre Kraemer committed
913
914
915
916
917
918
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
		out << nbe ;
		for(unsigned int j = 0; j < nbe; ++j)
			out << " " << *it++;
919
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
920
921
922
923
	}

	out.close() ;
	return true ;
924
}
Pierre Kraemer's avatar
Pierre Kraemer committed
925
926
927
928
929
930

} // namespace Export

} // namespace Algo

} // namespace CGoGN