export.hpp 32.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/traversor/traversorCell.h"
#include "Topology/generic/traversor/traversor2.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
29 30
#include "Topology/generic/cellmarker.h"

Sylvain Thery's avatar
Sylvain Thery committed
31 32
#include "Utils/compress.h"

Pierre Kraemer's avatar
Pierre Kraemer committed
33 34 35 36 37 38
namespace CGoGN
{

namespace Algo
{

39 40 41
namespace Surface
{

Pierre Kraemer's avatar
Pierre Kraemer committed
42 43 44 45
namespace Export
{

template <typename PFP>
46
bool exportPLY(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const char* filename, bool binary)
Pierre Kraemer's avatar
Pierre Kraemer committed
47 48 49
{
	typedef typename PFP::MAP MAP;
	
50
	// open file
51
	std::ofstream out ;
52
	if (!binary)
53
		out.open(filename, std::ios::out) ;
54 55 56
	else
		out.open(filename, std::ios::out | std::ios::binary) ;

Pierre Kraemer's avatar
Pierre Kraemer committed
57 58
	if (!out.good())
	{
59
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
60 61 62 63 64 65 66 67 68 69 70 71 72
		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) ;

73
	// Go over all faces
Pierre Kraemer's avatar
Pierre Kraemer committed
74
	CellMarker<MAP, VERTEX> markV(map) ;
75
	TraversorF<MAP> t(map) ;
76
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
77
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
78 79 80 81 82
		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
83
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
84
			++degree ;
85
			unsigned int vNum = map.template getEmbedding<VERTEX>(it) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
86
			if(!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
87
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
88 89 90
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
91
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
92
			fidx.push_back(vIndex[vNum]) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
93
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
94 95
		facesSize.push_back(degree) ;
		facesIdx.push_back(fidx) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
96 97
	}

98
	// Start writing the file
99
	out << "ply" << std::endl ;
100
	// ascii or binary
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
	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 ;
118 119
	out << "comment or contact : cgogn@unistra.fr" << std::endl ;
	// Vertex elements
120
	out << "element vertex " << vertices.size() << std::endl ;
121
	// Position property
122 123
	if (position.isValid())
	{
124 125 126
		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 ;
127
	}
128
	// Face element
129
	out << "element face " << facesSize.size() << std::endl ;
130
	out << "property list uint8 uint" << 8 * sizeof(facesIdx[0][0]) << " vertex_indices" << std::endl ;
131
	out << "end_header" << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
132

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

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

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

	out.close() ;

	return true ;
}

template <typename PFP>
172
bool exportPLYnew(typename PFP::MAP& map, const std::vector<VertexAttribute<typename PFP::VEC3, typename PFP::MAP>*>& attributeHandlers, const char* filename, bool binary)
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
{
	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
Pierre Kraemer's avatar
Pierre Kraemer committed
201
	CellMarker<MAP, VERTEX> markV(map) ;
202
	TraversorF<MAP> t(map) ;
203 204 205 206 207
	for(Dart d = t.begin(); d != t.end(); d = t.next())
	{
		std::vector<unsigned int> fidx ;
		fidx.reserve(8) ;
		unsigned int degree = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
208
		Traversor2FV<MAP> tfv(map, d) ;
209 210 211
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
		{
			++degree ;
212
			unsigned int vNum = map.template getEmbedding<VERTEX>(it) ;
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 244 245 246 247
			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 ;
248
	for (typename std::vector<VertexAttribute<VEC3, MAP>* >::const_iterator attrHandler = attributeHandlers.begin() ; attrHandler != attributeHandlers.end() ; ++attrHandler)
249
	{
250
		if ((*attrHandler)->isValid() && ((*attrHandler)->getOrbit() == VERTEX) )
251
		{
252
			if ((*attrHandler)->name().compare("position") == 0)  // Vertex position property
253
			{
254 255 256
				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 ;
257
			}
258
			else if ((*attrHandler)->name().compare("normal") == 0)	// normal property
259
			{
260 261 262
				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 ;
263
			}
264
			else if ((*attrHandler)->name().compare("color") == 0)	// vertex color property
265
			{
266 267 268
				out << "property " << nameOfTypePly((*(*attrHandler))[0][0]) << " r" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][1]) << " g" << std::endl ;
				out << "property " << nameOfTypePly((*(*attrHandler))[0][2]) << " b" << std::endl ;
269 270 271
			}
			else // other vertex properties
			{
272 273 274
				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 ;
275 276 277 278 279 280
			}
		}
	}

	// Face element
	out << "element face " << facesSize.size() << std::endl ;
281
	out << "property list uint8 " << nameOfTypePly(facesIdx[0][0]) << " vertex_indices" << std::endl ;
282 283 284 285 286 287
	out << "end_header" << std::endl ;

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

		// 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)
308
			for (typename std::vector<VertexAttribute<VEC3, MAP>*>::const_iterator attrHandler = attributeHandlers.begin() ; attrHandler != attributeHandlers.end() ; ++attrHandler)
309
				if ((*attrHandler)->isValid() && (*attrHandler)->getOrbit() == VERTEX)
310
				{
Pierre Kraemer's avatar
Pierre Kraemer committed
311
					const VEC3& v = (*(*attrHandler))[vertices[i]] ;
312 313 314 315 316 317
					out.write((char*)(&(v[0])), sizeof(v)) ;
				}

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

	out.close() ;
325

Pierre Kraemer's avatar
Pierre Kraemer committed
326 327 328 329
	return true ;
}

template <typename PFP>
330
bool exportOFF(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const char* filename)
Pierre Kraemer's avatar
Pierre Kraemer committed
331 332 333 334 335 336 337
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
	
	std::ofstream out(filename, std::ios::out) ;
	if (!out.good())
	{
338
		CGoGNerr << "Unable to open file " << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
339 340 341 342 343 344 345 346 347 348 349 350 351
		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) ;

Pierre Kraemer's avatar
Pierre Kraemer committed
352
	CellMarker<MAP, VERTEX> markV(map) ;
353
	TraversorF<MAP> t(map) ;
354
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
355
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
356 357 358 359 360
		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
361
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
362
			++degree ;
363
			unsigned int vNum = map.template getEmbedding<VERTEX>(it) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
364
			if(!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
365
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
366 367 368
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
369
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
370
			fidx.push_back(vIndex[vNum]) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
371
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
372 373
		facesSize.push_back(degree) ;
		facesIdx.push_back(fidx) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
374 375
	}

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

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		const VEC3& v = position[vertices[i]] ;
382
		out << v[0] << " " << v[1] << " " << v[2] << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
383 384 385 386 387 388
	}
	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] ;
389
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
390 391 392 393 394
	}

	out.close() ;
	return true ;
}
395

396
template <typename PFP>
397
bool exportOBJ(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const char* filename)
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;

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

419
	CellMarker<typename PFP::MAP,VERTEX> markV(map) ;
420
	TraversorF<MAP> t(map) ;
421 422 423 424 425 426 427
	for(Dart d = t.begin(); d != t.end(); d = t.next())
	{
		std::vector<unsigned int> fidx ;
		fidx.reserve(8) ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
		{
428 429 430
//			unsigned int vNum = map.getEmbedding(VERTEX, it) ;
			unsigned int vNum = map. template getEmbedding<VERTEX>(it) ;

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 458 459 460 461 462
			if(!markV.isMarked(it))
			{
				markV.mark(it) ;
				vIndex[vNum] = vCpt++ ;
				vertices.push_back(vNum) ;
			}
			fidx.push_back(vIndex[vNum]+1) ;
		}
		facesIdx.push_back(fidx) ;
	}

	out << "#OBJ - Export from CGoGN" << std::endl ;

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		const VEC3& v = position[vertices[i]] ;
		out << "v " << v[0] << " " << v[1] << " " << v[2] << std::endl ;
	}

	out << std::endl;

	for(unsigned int i = 0; i < facesIdx.size(); ++i)
	{
		out << "f ";
		for(unsigned int j = 0; j < facesIdx[i].size(); ++j)
			out << " " << facesIdx[i][j] ;
		out << std::endl ;
	}

	out.close() ;
	return true ;
}
463
/*
464
template <typename PFP>
465
bool exportPlyPTMgeneric(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& position, const char* filename)
466 467 468
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
469
	typedef typename PFP::REAL REAL;
470 471 472 473

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

478
	VertexAutoAttribute<unsigned int> tableVertLab(map);
479 480 481 482 483 484 485 486 487

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

488
	CellMarker<VERTEX> markV(map);
489
	TraversorF<MAP> t(map) ;
490 491
	unsigned int lab = 0;
	unsigned int nbf = 0;
492
	for(Dart d = t.begin(); d != t.end(); d = t.next())
493
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
494 495 496
		std::vector<unsigned int> face ;
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
497
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
498
			if (!markV.isMarked(it))
499
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
500 501
				markV.mark(it);
				tableVertLab[it] = lab++;
502
				vertices.push_back(map.template getEmbedding<VERTEX>(it));
503
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
504 505
			face.push_back(tableVertLab[it]);
		}
506

Pierre Kraemer's avatar
Pierre Kraemer committed
507 508 509
		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;
510

Pierre Kraemer's avatar
Pierre Kraemer committed
511
		++nbf;
512 513
	}

514 515
	VertexAttribute<VEC3> frame[3] ;
	VertexAttribute<VEC3> colorPTM[15] ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
516 517 518 519

	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") ;
520
	for (unsigned int i = 0 ; i < 15 ; ++i)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
521 522 523 524 525
	{
		std::stringstream name ;
		name << "colorPTM_a" << i ;
		colorPTM[i] = map.template getAttribute<VEC3>(VERTEX,name.str()) ;
	}
526
	const unsigned int nbCoefs = colorPTM[14].isValid() ? 15 : (colorPTM[9].isValid() ? 10 : 6) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
527

528 529
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
530
	out << "comment ply PTM (K. Vanhoey generic format)" << std::endl ;
531 532 533 534 535 536 537 538 539 540 541 542 543
	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 ;
544
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
545
		out << "property float C0_a" << coefI << std::endl ;
546
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
547
		out << "property float C1_a" << coefI << std::endl ;
548
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
549
		out << "property float C2_a" << coefI << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
550

551 552 553
	VertexAttribute<REAL> errL2 = map.template getAttribute<REAL>(VERTEX, "errL2") ;
	VertexAttribute<REAL> errLmax = map.template getAttribute<REAL>(VERTEX, "errLmax") ;
	VertexAttribute<REAL> stdDev = map.template getAttribute<REAL>(VERTEX, "stdDev") ;
554 555 556 557 558 559
	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 ;
560 561 562 563 564

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

565 566 567
	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
568 569
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
570
			out << position[vi][coord] << " " ;
571 572 573
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
574
				out << frame[axis][vi][coord] << " " ;
575 576
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
577 578
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
				out << colorPTM[coefI][vi][channel] << " "  ;
579 580
		 // fitting errors (if any)
		if (errL2.isValid())
581 582 583 584 585 586
			out << errL2[vi] << " " ;
		if (errLmax.isValid())
			out << errLmax[vi] << " " ;
		if (stdDev.isValid())
			out << stdDev[vi] << " " ;
		out << std::endl ;
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
	}

	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
602
*/
603
/*
604
template <typename PFP>
605
bool exportPlySLFgeneric(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& position, const char* filename)
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
	typedef typename PFP::REAL REAL;

	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);
629
	TraversorF<MAP> t(map) ;
630 631 632 633 634 635 636 637 638 639 640 641
	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++;
642
				vertices.push_back(map.getEmbedding<VERTEX>(it));
643 644 645 646 647 648 649 650 651 652 653
			}
			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;
	}

654
	VertexAttribute<typename PFP::VEC3> frame[3] ;
655
	std::vector<TVEC3> coefs ;
656 657 658 659

	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") ;
660 661 662

	unsigned int i = 0 ;
	do {
663
		std::stringstream name ;
664 665 666 667 668 669 670
		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()) ;
671

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

676 677
	out << "ply" << std::endl ;
	out << "format ascii 1.0" << std::endl ;
kenneth's avatar
kenneth committed
678
	out << "comment ply SLF (K. Vanhoey generic format): SLF_" << (((extension == ".plyPTMext") || extension == ".plyPTMextBin" ) ? "PTMext" : "SHreal") << std::endl ;
679 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
	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 ;
}

735
template <typename PFP>
736
bool exportPlySLFgenericBin(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& position, const char* filename)
737 738 739 740 741
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;
	typedef typename PFP::REAL REAL;

742
	std::ofstream out(filename, std::ios::out) ;
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
	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);
760
	TraversorF<MAP> t(map) ;
761 762 763 764 765 766 767 768 769 770 771 772
	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++;
773
				vertices.push_back(map.getEmbedding<VERTEX>(it));
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
			}
			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) ;

807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
	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 ;
823
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
824
		out << "property float C0_" << coefI << std::endl ;
825
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
826
		out << "property float C1_" << coefI << std::endl ;
827
	for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
828
		out << "property float C2_" << coefI << std::endl ;
829

830 831 832
	out << "element face " << nbf << std::endl ;
	out << "property list uchar int vertex_indices" << std::endl ;
	out << "end_header" << std::endl ;
833 834 835 836 837 838

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
		 // position
		for(unsigned int coord = 0 ; coord < 3 ; ++coord)
839 840 841 842
		{
			const float& floatofdouble = position[vi][coord] ;
			out.write((char*)(&floatofdouble), sizeof(float)) ;
		}
843 844 845
		 // frame
		for(unsigned int axis = 0 ; axis < 3 ; ++axis)
			for (unsigned int coord = 0 ; coord < 3 ; ++coord)
846 847 848 849
			{
				const float& floatofdouble = frame[axis][vi][coord] ;
				out.write((char*)(&floatofdouble), sizeof(float)) ;
			}
850 851 852
		 // coefficients
		for (unsigned int channel = 0 ; channel < 3 ; ++channel)
			for(unsigned int coefI = 0 ; coefI < nbCoefs ; ++coefI)
853 854 855 856
			{
				const float& floatofdouble = coefs[coefI][vi][channel] ;
				out.write((char*)(&floatofdouble), sizeof(float)) ;
			}
857 858 859 860 861 862
	}

	std::vector<unsigned int>::iterator it = faces.begin();
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
863
		out.write((char*)&nbe, sizeof(unsigned int)) ;
864
		for(unsigned int j = 0; j < nbe; ++j)
865 866 867 868
		{
			unsigned int index = *it++ ;
			out.write((char*)(&index), sizeof(unsigned int)) ;
		}
869 870 871 872 873
	}

	out.close() ;
	return true ;
}
874

Pierre Kraemer's avatar
Pierre Kraemer committed
875
template <typename PFP>
876
bool exportPLYPTM(typename PFP::MAP& map, const char* filename, const VertexAttribute<typename PFP::VEC3>& position, const VertexAttribute<typename PFP::VEC3> frame[3], const VertexAttribute<typename PFP::VEC3> colorPTM[6])
Pierre Kraemer's avatar
Pierre Kraemer committed
877 878 879 880 881 882 883
{
	typedef typename PFP::MAP MAP;
	typedef typename PFP::VEC3 VEC3;

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

888
	VertexAutoAttribute<unsigned int> tableVertLab(map);
Pierre Kraemer's avatar
Pierre Kraemer committed
889 890 891 892 893 894 895 896 897

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

898
	CellMarker<VERTEX> markV(map);
899
	TraversorF<MAP> t(map) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
900 901
	unsigned int lab = 0;
	unsigned int nbf = 0;
902
	for(Dart d = t.begin(); d != t.end(); d = t.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
903
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
904 905 906
		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
907
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
908
			if (!markV.isMarked(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
909
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
910 911
				markV.mark(it);
				tableVertLab[it] = lab++;
912
				vertices.push_back(map.template getEmbedding<VERTEX>(it));
913
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
914 915
			face.push_back(tableVertLab[it]);
		}
916

Pierre Kraemer's avatar
Pierre Kraemer committed
917 918 919
		faces.push_back(face.size()) ;
		for (unsigned int i = 0 ; i < face.size() ; ++i)
			faces.push_back(face.at(i)) ;
920

Pierre Kraemer's avatar
Pierre Kraemer committed
921
		++nbf;
Pierre Kraemer's avatar
Pierre Kraemer committed
922 923
	}

924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
	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
961 962 963 964

	for(unsigned int i = 0; i < vertices.size(); ++i)
	{
		unsigned int vi = vertices[i];
965 966 967 968 969 970
		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] <<" " ;
971
		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
972 973
	}

974
	std::vector<unsigned int>::iterator it = faces.begin();
Pierre Kraemer's avatar
Pierre Kraemer committed
975 976 977 978 979 980
	while (it != faces.end())
	{
		unsigned int nbe = *it++;
		out << nbe ;
		for(unsigned int j = 0; j < nbe; ++j)
			out << " " << *it++;
981
		out << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
982 983 984 985
	}

	out.close() ;
	return true ;
986
}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
987
*/
Pierre Kraemer's avatar
Pierre Kraemer committed
988

989
template <typename PFP>
990
bool exportChoupi(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const char* filename)
991 992 993 994 995 996 997 998 999 1000
{
	typedef typename PFP::MAP MAP;

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

1001
	out << Algo::Topo::getNbOrbits<VERTEX>(map) << " " << Algo::Topo::getNbOrbits<EDGE>(map) << std::endl;
1002

Pierre Kraemer's avatar
Pierre Kraemer committed
1003
	TraversorV<MAP> travV(map);
1004 1005
	for(Dart dit = travV.begin() ; dit != travV.end() ; dit = travV.next())
	{
1006
		out << map.template getEmbedding<VERTEX>(dit) << " " << position[dit] << std::endl;
1007 1008
	}

Pierre Kraemer's avatar
Pierre Kraemer committed
1009
	TraversorE<MAP> travE(map);
1010 1011 1012
	unsigned int indexE = 0;
	for(Dart dit = travE.begin() ; dit != travE.end() ; dit = travE.next())
	{
1013
		out << indexE << "  " << map.template getEmbedding<VERTEX>(dit) << " " << map.template getEmbedding<VERTEX>(map.phi2(dit)) << std::endl;
1014 1015 1016 1017 1018 1019
		++indexE;
	}

	out.close() ;
	return true ;
}
Pierre Kraemer's avatar
Pierre Kraemer committed
1020 1021 1022

} // namespace Export

Pierre Kraemer's avatar
Pierre Kraemer committed
1023
} // namespace Surface
1024

Pierre Kraemer's avatar
Pierre Kraemer committed
1025 1026 1027
} // namespace Algo

} // namespace CGoGN