Coupure prévue mardi 3 Août au matin pour maintenance du serveur. Nous faisons au mieux pour que celle-ci soit la plus brève possible.

export.hpp 23.3 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
41
42
43
44
45
46
47
48
#include "Topology/generic/cellmarker.h"

namespace CGoGN
{

namespace Algo
{

namespace Export
{

template <typename PFP>
bool exportPLY(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())
	{
49
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
50
51
52
53
54
55
56
57
58
59
60
61
62
		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) ;

63
	CellMarker markV(map, VERTEX) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
64
	TraversorF<MAP> t(map, good) ;
65
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
66
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
67
68
69
70
71
		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
72
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
73
74
75
			++degree ;
			unsigned int vNum = map.getEmbedding(VERTEX, it) ;
			if(!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
76
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
77
78
79
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
80
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
81
			fidx.push_back(vIndex[vNum]) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
82
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
83
84
		facesSize.push_back(degree) ;
		facesIdx.push_back(fidx) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
85
86
	}

87
88
89
90
91
92
93
94
95
96
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
	out << "comment no comment" << 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 << "element face " << facesSize.size() << std::endl ;
	out << "property list uchar int vertex_indices" << std::endl ;
	out << "end_header" << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
97
98
99
100

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		const VEC3& v = position[vertices[i]] ;
101
		out << v[0] << " " << v[1] << " " << v[2] << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
102
103
104
105
106
107
	}
	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] ;
108
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
	}

	out.close() ;
	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())
	{
124
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
125
126
127
128
129
130
131
132
133
134
135
136
137
		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) ;

138
	CellMarker markV(map, VERTEX) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
139
	TraversorF<MAP> t(map, good) ;
140
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
141
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
142
143
144
145
146
		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
147
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
148
149
150
			++degree ;
			unsigned int vNum = map.getEmbedding(VERTEX, it) ;
			if(!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
151
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
152
153
154
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
155
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
156
			fidx.push_back(vIndex[vNum]) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
157
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
158
159
		facesSize.push_back(degree) ;
		facesIdx.push_back(fidx) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
160
161
	}

162
163
	out << "OFF" << std::endl ;
	out << vertices.size() << " " << facesSize.size() << " " << 0 << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
164
165
166
167

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		const VEC3& v = position[vertices[i]] ;
168
		out << v[0] << " " << v[1] << " " << v[2] << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
169
170
171
172
173
174
	}
	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] ;
175
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
176
177
178
179
180
181
	}

	out.close() ;
	return true ;
}

182
template <typename PFP>
183
bool exportPlyPTMgeneric(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, const FunctorSelect& good)
184
185
186
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
187
188
189
	typedef typename PFP::TVEC3 TVEC3;
	typedef typename PFP::REAL REAL;
	typedef typename PFP::TREAL TREAL;
190
191
192
193

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

198
	AutoAttributeHandler<unsigned int> tableVertLab(map, VERTEX);
199
200
201
202
203
204
205
206
207
208


	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);

209
	CellMarker markV(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
210
	TraversorF<MAP> t(map, good) ;
211
212
	unsigned int lab = 0;
	unsigned int nbf = 0;
213
	for(Dart d = t.begin(); d != t.end(); d = t.next())
214
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
215
216
217
		std::vector<unsigned int> face ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
218
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
219
			if (!markV.isMarked(it))
220
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
221
222
223
				markV.mark(it);
				tableVertLab[it] = lab++;
				vertices.push_back(map.getEmbedding(VERTEX, it));
224
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
225
226
			face.push_back(tableVertLab[it]);
		}
227

Pierre Kraemer's avatar
Pierre Kraemer committed
228
229
230
		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;
231

Pierre Kraemer's avatar
Pierre Kraemer committed
232
		++nbf;
233
234
	}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
235
236
237
238
239
240
241
242
243
244
245
246
	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()) ;
	}
247
	const unsigned int nbCoefs = colorPTM[14].isValid() ? 15 : (colorPTM[9].isValid() ? 10 : 6) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
248

249
250
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
251
	out << "comment ply PTM (K. Vanhoey generic format)" << std::endl ;
252
253
254
255
256
257
258
259
260
261
262
263
264
	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 ;
265
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
266
		out << "property float C0_a" << coefI << std::endl ;
267
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
268
		out << "property float C1_a" << coefI << std::endl ;
269
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
270
		out << "property float C2_a" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
271
272
273

	TREAL errL2 = map.template getAttribute<REAL>(VERTEX,"errL2") ;
	TREAL errLmax = map.template getAttribute<REAL>(VERTEX,"errLmax") ;
274
	TREAL stdDev = map.template getAttribute<REAL>(VERTEX,"stdDev") ;
275
276
277
278
279
280
	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 ;
281
282
283
284
285

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

286
287
288
	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
289
290
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
291
			out << position[vi][coord] << " " ;
292
293
294
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
295
				out << frame[axis][vi][coord] << " " ;
296
297
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
298
299
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
				out << colorPTM[coefI][vi][channel] << " "  ;
300
301
		 // fitting errors (if any)
		if (errL2.isValid())
302
303
304
305
306
307
			out << errL2[vi] << " " ;
		if (errLmax.isValid())
			out << errLmax[vi] << " " ;
		if (stdDev.isValid())
			out << stdDev[vi] << " " ;
		out << std::endl ;
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
	}

	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 ;
}
323

324
template <typename PFP>
325
bool exportPlySLFgeneric(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, const FunctorSelect& good)
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
{
	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] ;
378
	std::vector<TVEC3> coefs ;
379
380
381
382

	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") ;
383
384
385

	unsigned int i = 0 ;
	do {
386
		std::stringstream name ;
387
388
389
390
391
392
393
		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()) ;
394

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

399
400
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
401
	out << "comment ply SLF (K. Vanhoey generic format): SLF_" << ((extension == ".plyPTMext") ? "PTMext" : "SHreal") << std::endl ;
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
	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
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
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;

	std::ofstream out(filename, std::ios::out | std::ios::binary) ;
	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) ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
533
534
	std::string tmp ;
	tmp = std::string("ply") ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
535
	std::cout << tmp.length() << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
536
	out.write(tmp.c_str(),tmp.length()*sizeof(char)) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
537
	tmp = std::string("format binary_little_endian 1.0") ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
538
	out.write(tmp.c_str(),tmp.length()*sizeof(char)) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
539

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
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
	std::stringstream header ;
	header << "comment ply SLF (K. Vanhoey generic format): SLF_" << ((extension == ".plyPTMext") ? "PTMext" : "SHreal") << std::endl ;
	header << "element vertex " << vertices.size() << std::endl ;
	header << "property float x" << std::endl ;
	header << "property float y" << std::endl ;
	header << "property float z" << std::endl ;
	header << "property float tx" << std::endl ;
	header << "property float ty" << std::endl ;
	header << "property float tz" << std::endl ;
	header << "property float bx" << std::endl ;
	header << "property float by" << std::endl ;
	header << "property float bz" << std::endl ;
	header << "property float nx" << std::endl ;
	header << "property float ny" << std::endl ;
	header << "property float nz" << std::endl ;
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
		header << "property float C0_" << coefI << std::endl ;
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
		header << "property float C1_" << coefI << std::endl ;
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
		header << "property float C2_" << coefI << std::endl ;

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

	size_t nbCharsOfHeader = header.str().size() ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
567
	out.write((char*)&nbCharsOfHeader, sizeof(size_t)) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
	out.write((char*)(header.str().c_str()), nbCharsOfHeader*sizeof(char)) ;

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
			out.write((char*)(&(position[vi][coord])), sizeof(float)) ;
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
				out.write((char*)(&(frame[axis][vi][coord])), sizeof(float)) ;
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
583
				out.write((char*)(&(coefs[coefI][vi][channel])), sizeof(float)) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
584
585
586
587
588
589
	}

	std::vector<unsigned int>::iterator it = faces.begin();
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
590
		out.write((char*)&nbe, sizeof(unsigned int)) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
591
		for(unsigned int j = 0; j < nbe; ++j)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
592
593
594
595
		{
			unsigned int index = *it++ ;
			out.write((char*)(&index), sizeof(unsigned int)) ;
		}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
596
597
598
599
600
601
	}

	out.close() ;
	return true ;
}

602

Pierre Kraemer's avatar
Pierre Kraemer committed
603
template <typename PFP>
604
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
605
606
607
608
609
610
611
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;

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

616
	AutoAttributeHandler<unsigned int> tableVertLab(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
617
618
619
620
621
622
623
624
625

	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);

626
	CellMarker markV(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
627
	TraversorF<MAP> t(map, good) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
628
629
	unsigned int lab = 0;
	unsigned int nbf = 0;
630
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
631
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
632
633
634
		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
635
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
636
			if (!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
637
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
638
639
640
				markV.mark(it);
				tableVertLab[it] = lab++;
				vertices.push_back(map.getEmbedding(VERTEX, it));
641
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
642
643
			face.push_back(tableVertLab[it]);
		}
644

Pierre Kraemer's avatar
Pierre Kraemer committed
645
646
647
		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;
648

Pierre Kraemer's avatar
Pierre Kraemer committed
649
		++nbf;
Pierre Kraemer's avatar
Pierre Kraemer committed
650
651
	}

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
	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
689
690
691
692

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
693
694
695
696
697
698
		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] <<" " ;
699
		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
700
701
	}

702
	std::vector<unsigned int>::iterator it = faces.begin();
Pierre Kraemer's avatar
Pierre Kraemer committed
703
704
705
706
707
708
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
		out << nbe ;
		for(unsigned int j = 0; j < nbe; ++j)
			out << " " << *it++;
709
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
710
711
712
713
	}

	out.close() ;
	return true ;
714
}
Pierre Kraemer's avatar
Pierre Kraemer committed
715
716
717
718
719
720

} // namespace Export

} // namespace Algo

} // namespace CGoGN