Création d'un compte pour un collaborateur extérieur au laboratoire depuis l'intranet ICube : https://intranet.icube.unistra.fr/fr/labs/member/profile

export.hpp 24.1 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
47
48
49
50
	std::ofstream out ;
	//if (!binary)
		out.open(filename, std::ios::out) ;
	//else
		//out.open(filename, std::ios::out | std::ios::binary) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
51
52
	if (!out.good())
	{
53
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
54
55
56
57
58
59
60
61
62
63
64
65
66
		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) ;

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

91
	out << "ply" << std::endl ;
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

	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 ;
111
	out << "element vertex " << vertices.size() << std::endl ;
112
113
114
115
116
117
118
	if (position.isValid())
	{
		out << "property float32 x" << std::endl ;
		out << "property float32 y" << std::endl ;
		out << "property float32 z" << std::endl ;
	}

119
	out << "element face " << facesSize.size() << std::endl ;
120
	out << "property list uint8 uint32 vertex_indices" << std::endl ;
121
	out << "end_header" << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
122

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

		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
135
	}
136
	else
Pierre Kraemer's avatar
Pierre Kraemer committed
137
	{
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
		for(unsigned int i = 0; i < vertices.size(); ++i)
		{
			Geom::Vec3f v = position[vertices[i]] ;
			for (unsigned int c = 0 ; c < 3 ; ++c)
			{
				const float& floatofdouble = v[c] ;
				out.write((char*)(&floatofdouble), sizeof(float)) ;
			}
		}

		for(unsigned int i = 0; i < facesSize.size(); ++i)
		{
			unsigned char nbe = facesSize[i] ;
			out.write((char*)(&nbe), sizeof(unsigned char)) ;
			for(unsigned int j = 0 ; j < facesIdx[i].size() ; ++j)
				out.write((char*)(&(facesIdx[i][j])), sizeof(unsigned int)) ;
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
155
156
157
	}

	out.close() ;
158

Pierre Kraemer's avatar
Pierre Kraemer committed
159
160
161
162
163
164
165
166
167
168
169
170
	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())
	{
171
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
172
173
174
175
176
177
178
179
180
181
182
183
184
		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) ;

185
	CellMarker markV(map, VERTEX) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
186
	TraversorF<MAP> t(map, good) ;
187
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
188
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
189
190
191
192
193
		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
194
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
195
196
197
			++degree ;
			unsigned int vNum = map.getEmbedding(VERTEX, it) ;
			if(!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
198
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
199
200
201
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
202
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
203
			fidx.push_back(vIndex[vNum]) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
204
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
205
206
		facesSize.push_back(degree) ;
		facesIdx.push_back(fidx) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
207
208
	}

209
210
	out << "OFF" << std::endl ;
	out << vertices.size() << " " << facesSize.size() << " " << 0 << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
211
212
213
214

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		const VEC3& v = position[vertices[i]] ;
215
		out << v[0] << " " << v[1] << " " << v[2] << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
216
217
218
219
220
221
	}
	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] ;
222
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
223
224
225
226
227
228
	}

	out.close() ;
	return true ;
}

229
template <typename PFP>
230
bool exportPlyPTMgeneric(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, const FunctorSelect& good)
231
232
233
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
234
235
236
	typedef typename PFP::TVEC3 TVEC3;
	typedef typename PFP::REAL REAL;
	typedef typename PFP::TREAL TREAL;
237
238
239
240

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

245
	AutoAttributeHandler<unsigned int> tableVertLab(map, VERTEX);
246
247
248
249
250
251
252
253
254
255


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

256
	CellMarker markV(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
257
	TraversorF<MAP> t(map, good) ;
258
259
	unsigned int lab = 0;
	unsigned int nbf = 0;
260
	for(Dart d = t.begin(); d != t.end(); d = t.next())
261
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
262
263
264
		std::vector<unsigned int> face ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
265
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
266
			if (!markV.isMarked(it))
267
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
268
269
270
				markV.mark(it);
				tableVertLab[it] = lab++;
				vertices.push_back(map.getEmbedding(VERTEX, it));
271
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
272
273
			face.push_back(tableVertLab[it]);
		}
274

Pierre Kraemer's avatar
Pierre Kraemer committed
275
276
277
		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;
278

Pierre Kraemer's avatar
Pierre Kraemer committed
279
		++nbf;
280
281
	}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
282
283
284
285
286
287
288
289
290
291
292
293
	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()) ;
	}
294
	const unsigned int nbCoefs = colorPTM[14].isValid() ? 15 : (colorPTM[9].isValid() ? 10 : 6) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
295

296
297
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
298
	out << "comment ply PTM (K. Vanhoey generic format)" << std::endl ;
299
300
301
302
303
304
305
306
307
308
309
310
311
	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 ;
312
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
313
		out << "property float C0_a" << coefI << std::endl ;
314
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
315
		out << "property float C1_a" << coefI << std::endl ;
316
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
317
		out << "property float C2_a" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
318
319
320

	TREAL errL2 = map.template getAttribute<REAL>(VERTEX,"errL2") ;
	TREAL errLmax = map.template getAttribute<REAL>(VERTEX,"errLmax") ;
321
	TREAL stdDev = map.template getAttribute<REAL>(VERTEX,"stdDev") ;
322
323
324
325
326
327
	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 ;
328
329
330
331
332

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

333
334
335
	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
336
337
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
338
			out << position[vi][coord] << " " ;
339
340
341
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
342
				out << frame[axis][vi][coord] << " " ;
343
344
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
345
346
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
				out << colorPTM[coefI][vi][channel] << " "  ;
347
348
		 // fitting errors (if any)
		if (errL2.isValid())
349
350
351
352
353
354
			out << errL2[vi] << " " ;
		if (errLmax.isValid())
			out << errLmax[vi] << " " ;
		if (stdDev.isValid())
			out << stdDev[vi] << " " ;
		out << std::endl ;
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
	}

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

371
template <typename PFP>
372
bool exportPlySLFgeneric(typename PFP::MAP& map, const typename PFP::TVEC3& position, const char* filename, const FunctorSelect& good)
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
{
	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] ;
425
	std::vector<TVEC3> coefs ;
426
427
428
429

	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") ;
430
431
432

	unsigned int i = 0 ;
	do {
433
		std::stringstream name ;
434
435
436
437
438
439
440
		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()) ;
441

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

446
447
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
kenneth's avatar
kenneth committed
448
	out << "comment ply SLF (K. Vanhoey generic format): SLF_" << (((extension == ".plyPTMext") || extension == ".plyPTMextBin" ) ? "PTMext" : "SHreal") << std::endl ;
449
450
451
452
453
454
455
456
457
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
	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
505
506
507
508
509
510
511
512
513
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;

514
	std::ofstream out(filename, std::ios::out) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
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
	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) ;

579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
	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
595
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
596
		out << "property float C0_" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
597
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
598
		out << "property float C1_" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
599
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
600
		out << "property float C2_" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
601

602
603
604
	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
605
606
607
608
609
610

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
611
612
613
614
		{
			const float& floatofdouble = position[vi][coord] ;
			out.write((char*)(&floatofdouble), sizeof(float)) ;
		}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
615
616
617
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
618
619
620
621
			{
				const float& floatofdouble = frame[axis][vi][coord] ;
				out.write((char*)(&floatofdouble), sizeof(float)) ;
			}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
622
623
624
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
625
626
627
628
			{
				const float& floatofdouble = coefs[coefI][vi][channel] ;
				out.write((char*)(&floatofdouble), sizeof(float)) ;
			}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
629
630
631
632
633
634
	}

	std::vector<unsigned int>::iterator it = faces.begin();
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
635
		out.write((char*)&nbe, sizeof(unsigned int)) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
636
		for(unsigned int j = 0; j < nbe; ++j)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
637
638
639
640
		{
			unsigned int index = *it++ ;
			out.write((char*)(&index), sizeof(unsigned int)) ;
		}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
641
642
643
644
645
646
	}

	out.close() ;
	return true ;
}

647

Pierre Kraemer's avatar
Pierre Kraemer committed
648
template <typename PFP>
649
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
650
651
652
653
654
655
656
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;

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

661
	AutoAttributeHandler<unsigned int> tableVertLab(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
662
663
664
665
666
667
668
669
670

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

671
	CellMarker markV(map, VERTEX);
Pierre Kraemer's avatar
Pierre Kraemer committed
672
	TraversorF<MAP> t(map, good) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
673
674
	unsigned int lab = 0;
	unsigned int nbf = 0;
675
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
676
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
677
678
679
		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
680
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
681
			if (!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
682
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
683
684
685
				markV.mark(it);
				tableVertLab[it] = lab++;
				vertices.push_back(map.getEmbedding(VERTEX, it));
686
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
687
688
			face.push_back(tableVertLab[it]);
		}
689

Pierre Kraemer's avatar
Pierre Kraemer committed
690
691
692
		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;
693

Pierre Kraemer's avatar
Pierre Kraemer committed
694
		++nbf;
Pierre Kraemer's avatar
Pierre Kraemer committed
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
	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
734
735
736
737

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
738
739
740
741
742
743
		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] <<" " ;
744
		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
745
746
	}

747
	std::vector<unsigned int>::iterator it = faces.begin();
Pierre Kraemer's avatar
Pierre Kraemer committed
748
749
750
751
752
753
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
		out << nbe ;
		for(unsigned int j = 0; j < nbe; ++j)
			out << " " << *it++;
754
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
755
756
757
758
	}

	out.close() ;
	return true ;
759
}
Pierre Kraemer's avatar
Pierre Kraemer committed
760
761
762
763
764
765

} // namespace Export

} // namespace Algo

} // namespace CGoGN