map2MR_PrimalAdapt.hpp 14.8 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
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

25
#include "Algo/Multiresolution/map2MR/map2MR_PrimalAdapt.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
26 27 28 29

namespace CGoGN
{

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
namespace Algo
{

namespace MR
{

namespace Primal
{

namespace Adaptive
{

template <typename PFP>
Map2MR<PFP>::Map2MR(typename PFP::MAP& map) :
	m_map(map),
45 46 47 48
	shareVertexEmbeddings(true),
	vertexVertexFunctor(NULL),
	edgeVertexFunctor(NULL),
	faceVertexFunctor(NULL)
Pierre Kraemer's avatar
Pierre Kraemer committed
49
{
50

Pierre Kraemer's avatar
Pierre Kraemer committed
51 52 53 54 55
}

/***************************************************
 *               CELLS INFORMATION                 *
 ***************************************************/
56 57
template <typename PFP>
unsigned int Map2MR<PFP>::edgeLevel(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
58
{
Pierre Kraemer's avatar
Pierre Kraemer committed
59
	assert(getDartLevel(d) <= getCurrentLevel() || !"edgeLevel : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
60 61 62 63 64 65

	unsigned int ld = getDartLevel(d) ;
	unsigned int ldd = getDartLevel(phi2(d)) ;	// the level of an edge is the maximum of the
	return ld > ldd ? ld : ldd ;				// insertion levels of its two darts
}

66 67
template <typename PFP>
unsigned int Map2MR<PFP>::faceLevel(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
68
{
Pierre Kraemer's avatar
Pierre Kraemer committed
69
	assert(getDartLevel(d) <= getCurrentLevel() || !"faceLevel : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

	if(getCurrentLevel() == 0)
		return 0 ;

	Dart it = d ;
	unsigned int min1 = getDartLevel(it) ;		// the level of a face is the second minimum of the
	it = phi1(it) ;
	unsigned int min2 = getDartLevel(it) ;		// insertion levels of its darts

	if(min2 < min1)
	{
		unsigned int tmp = min1 ;
		min1 = min2 ;
		min2 = tmp ;
	}

	it = phi1(it) ;
	while(it != d)
	{
		unsigned int dl = getDartLevel(it) ;
		if(dl < min2)
		{
			if(dl < min1)
			{
				min2 = min1 ;
				min1 = dl ;
			}
			else
				min2 = dl ;
		}
		it = phi1(it) ;
	}

	return min2 ;
}

106 107
template <typename PFP>
Dart Map2MR<PFP>::faceOrigin(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
108
{
Pierre Kraemer's avatar
Pierre Kraemer committed
109
	assert(getDartLevel(d) <= getCurrentLevel() || !"faceOrigin : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123

	pushLevel() ;
	Dart p = d ;
	unsigned int pLevel = getDartLevel(p) ;
	while(pLevel > 0)
	{
		p = faceOldestDart(p) ;
		pLevel = getDartLevel(p) ;
		setCurrentLevel(pLevel) ;
	}
	popLevel() ;
	return p ;
}

124 125
template <typename PFP>
Dart Map2MR<PFP>::faceOldestDart(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
126
{
Pierre Kraemer's avatar
Pierre Kraemer committed
127
	assert(getDartLevel(d) <= getCurrentLevel() || !"faceOldestDart : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

	Dart it = d ;
	Dart oldest = it ;
	unsigned int l_old = getDartLevel(oldest) ;
	do
	{
		unsigned int l = getDartLevel(it) ;
		if(l == 0)
			return it ;
		if(l < l_old)
		{
			oldest = it ;
			l_old = l ;
		}
		it = phi1(it) ;
	} while(it != d) ;
	return oldest ;
}

147 148
template <typename PFP>
bool Map2MR<PFP>::edgeIsSubdivided(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
149
{
Pierre Kraemer's avatar
Pierre Kraemer committed
150
	assert(getDartLevel(d) <= getCurrentLevel() || !"edgeIsSubdivided : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
151 152 153 154 155

	if(getCurrentLevel() == getMaxLevel())
		return false ;

	Dart d2 = phi2(d) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
156
	incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
157
	Dart d2_l = phi2(d) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
158
	decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
159 160 161 162 163 164
	if(d2 != d2_l)
		return true ;
	else
		return false ;
}

165 166
template <typename PFP>
bool Map2MR<PFP>::edgeCanBeCoarsened(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
167
{
Pierre Kraemer's avatar
Pierre Kraemer committed
168
	assert(getDartLevel(d) <= getCurrentLevel() || !"edgeCanBeCoarsened : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
169 170 171 172 173 174 175

	if(edgeIsSubdivided(d))
	{
		bool subdOnce = true ;
		bool degree2 = false ;

		Dart d2 = phi2(d) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
176
		incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
177 178 179 180 181 182
		if(vertexDegree(phi1(d)) == 2)
		{
			degree2 = true ;
			if(edgeIsSubdivided(d) || edgeIsSubdivided(d2))
				subdOnce = false ;
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
183
		decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
184 185 186 187 188 189 190

		return degree2 && subdOnce ;
	}

	return false ;
}

191 192
template <typename PFP>
bool Map2MR<PFP>::faceIsSubdivided(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
193
{
Pierre Kraemer's avatar
Pierre Kraemer committed
194
	assert(getDartLevel(d) <= getCurrentLevel() || !"faceIsSubdivided : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
195 196 197 198 199 200 201 202 203

	if(getCurrentLevel() == getMaxLevel())
		return false ;

	unsigned int fLevel = faceLevel(d) ;
	if(fLevel < getCurrentLevel())	// a face whose level in the current level map is lower than
		return false ;				// the current level can not be subdivided to higher levels

	bool subd = false ;
Pierre Kraemer's avatar
Pierre Kraemer committed
204
	incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
205 206
	if(getDartLevel(phi1(phi1(d))) == getCurrentLevel())
		subd = true ;
Pierre Kraemer's avatar
Pierre Kraemer committed
207
	decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
208 209 210
	return subd ;
}

211 212
template <typename PFP>
bool Map2MR<PFP>::faceIsSubdividedOnce(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
213
{
Pierre Kraemer's avatar
Pierre Kraemer committed
214
	assert(getDartLevel(d) <= getCurrentLevel() || !"faceIsSubdividedOnce : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
215 216 217 218 219 220 221 222 223 224 225 226

	if(getCurrentLevel() == getMaxLevel())
		return false ;

	unsigned int fLevel = faceLevel(d) ;
	if(fLevel < getCurrentLevel())	// a face whose level in the current level map is lower than
		return false ;				// the current level can not be subdivided to higher levels

	unsigned int degree = 0 ;
	bool subd = false ;
	bool subdOnce = true ;

Pierre Kraemer's avatar
Pierre Kraemer committed
227
	incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
228 229
	if(getDartLevel(phi1(phi1(d))) == getCurrentLevel())
		subd = true ;
Pierre Kraemer's avatar
Pierre Kraemer committed
230
	decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
231 232 233

	if(subd)
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
234
		incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
235 236 237

		if(getCurrentLevel() == getMaxLevel())
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
238
			decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
239 240 241 242 243 244
			return true ;
		}

		Dart fit = d ;
		do
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
245
			incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
246 247
			if(getDartLevel(phi1(phi1(fit))) == getCurrentLevel())
				subdOnce = false ;
Pierre Kraemer's avatar
Pierre Kraemer committed
248
			decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
249 250 251 252 253 254 255
			++degree ;
			fit = phi1(fit) ;
		} while(subdOnce && fit != d) ;

		if(degree == 3 && subdOnce)
		{
			Dart cf = phi2(phi1(d)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
256
			incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
257 258
			if(getDartLevel(phi1(phi1(cf))) == getCurrentLevel())
				subdOnce = false ;
Pierre Kraemer's avatar
Pierre Kraemer committed
259
			decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
260 261
		}

Pierre Kraemer's avatar
Pierre Kraemer committed
262
		decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
263 264 265 266 267 268 269

		return subdOnce ;
	}

	return false ;
}

270
/***************************************************
271
 *               SUBDIVISION                       *
272 273
 ***************************************************/

274 275
template <typename PFP>
void Map2MR<PFP>::addNewLevel(bool embedNewVertices)
276
{
untereiner's avatar
untereiner committed
277
	addLevelBack() ;
278 279
}

280 281
template <typename PFP>
void Map2MR<PFP>::propagateDartRelation(Dart d, AttributeMultiVector<Dart>* rel)
282 283 284 285 286 287 288 289 290 291 292
{
	Dart dd = (*rel)[dartIndex(d)] ;
	pushLevel() ;
	for(unsigned int i = getCurrentLevel() + 1; i <= getMaxLevel(); ++i)
	{
		setCurrentLevel(i) ;
		(*rel)[dartIndex(d)] = dd ;
	}
	popLevel() ;
}

293
template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
294
template <unsigned int ORBIT>
295
void Map2MR<PFP>::propagateDartEmbedding(Dart d)
296
{
Pierre Kraemer's avatar
Pierre Kraemer committed
297
	unsigned int emb = getEmbedding<ORBIT>(d) ;
298 299 300 301
	pushLevel() ;
	for(unsigned int i = getCurrentLevel() + 1; i <= getMaxLevel(); ++i)
	{
		setCurrentLevel(i) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
302
		setDartEmbedding<ORBIT>( d, emb) ;
303 304 305 306
	}
	popLevel() ;
}

307
template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
308
template <unsigned int ORBIT>
309
void Map2MR<PFP>::propagateOrbitEmbedding(Dart d)
310
{
Pierre Kraemer's avatar
Pierre Kraemer committed
311
	unsigned int emb = getEmbedding<ORBIT>(d) ;
312 313 314 315
	pushLevel() ;
	for(unsigned int i = getCurrentLevel() + 1; i <= getMaxLevel(); ++i)
	{
		setCurrentLevel(i) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
316
		embedOrbit<ORBIT>(d, emb) ;
317 318 319 320
	}
	popLevel() ;
}

321
//Dart Map2MR::cutEdge(Dart d)
322
//{
323
//	Dart dd = phi2(d) ;
324
//
325 326
//	Dart d1 = newDart() ;
//	Dart dd1 = newDart() ;
327
//
328 329
//	pushLevel() ;
//	for(unsigned int i = getCurrentLevel(); i <= getMaxLevel(); ++i)
330
//	{
331 332 333 334 335 336 337
//		setCurrentLevel(i) ;
//
//		phi2unsew(d) ;
//
//		phi1sew(d, d1) ;
//		if (isBoundaryMarked(d))
//			boundaryMark(d1) ;
338
//
339 340 341 342 343 344 345 346 347 348 349 350
//		phi1sew(dd, dd1) ;
//		if (isBoundaryMarked(dd))
//			boundaryMark(dd1) ;
//
//		phi2sew(d, dd1) ;
//		phi2sew(dd, d1) ;
//	}
//	popLevel() ;
//
//	return d1 ;
//}

351 352
template <typename PFP>
Dart Map2MR<PFP>::cutEdge(Dart d)
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
{
	Dart dd = phi2(d) ;
	Dart d1 = EmbeddedMap2::cutEdge(d) ;
	Dart dd1 = phi1(dd) ;
	Dart d11 = phi1(d1) ;
	Dart dd11 = phi1(dd1) ;

	propagateDartRelation(d, m_phi1) ;
	propagateDartRelation(d, m_phi2) ;
	propagateDartRelation(dd, m_phi1) ;
	propagateDartRelation(dd, m_phi2) ;
	propagateDartRelation(d1, m_phi1) ;
	propagateDartRelation(d1, m_phi_1) ;
	propagateDartRelation(d1, m_phi2) ;
	propagateDartRelation(dd1, m_phi1) ;
	propagateDartRelation(dd1, m_phi_1) ;
	propagateDartRelation(dd1, m_phi2) ;
	propagateDartRelation(d11, m_phi_1) ;
	propagateDartRelation(dd11, m_phi_1) ;

	return d1 ;
}

376
//void Map2MR::splitFace(Dart d, Dart e)
377
//{
378 379
//	Dart dprev = phi_1(d) ;
//	Dart eprev = phi_1(e) ;
380
//
381 382
//	Dart dd = newDart() ;
//	Dart ee = newDart() ;
383
//
384 385
//	pushLevel() ;
//	for(unsigned int i = getCurrentLevel(); i <= getMaxLevel(); ++i)
386
//	{
387 388 389 390 391 392 393 394 395 396 397 398 399 400
//		setCurrentLevel(i) ;
//
//		phi1sew(dprev, dd) ;
//		if (isBoundaryMarked(dprev))
//			boundaryMark(dd);
//
//		phi1sew(eprev, ee) ;
//		if (isBoundaryMarked(eprev))
//			boundaryMark(ee);
//
//		phi1sew(dprev, eprev) ;
//
//		phi2sew(dd, ee) ;
//
Pierre Kraemer's avatar
Pierre Kraemer committed
401 402
//		copyDartEmbedding<VERTEX>(ee, d) ;
//		copyDartEmbedding<VERTEX>(dd, e) ;
403 404
//	}
//	popLevel() ;
405 406
//}

407 408
template <typename PFP>
void Map2MR<PFP>::splitFace(Dart d, Dart e)
409
{
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
	Dart dprev = phi_1(d) ;
	Dart eprev = phi_1(e) ;
	EmbeddedMap2::splitFace(d, e) ;
	Dart dd = phi1(dprev) ;
	Dart ee = phi1(eprev) ;

	propagateDartRelation(d, m_phi_1) ;
	propagateDartRelation(e, m_phi_1) ;
	propagateDartRelation(dd, m_phi1) ;
	propagateDartRelation(dd, m_phi_1) ;
	propagateDartRelation(dd, m_phi2) ;
	propagateDartRelation(ee, m_phi1) ;
	propagateDartRelation(ee, m_phi_1) ;
	propagateDartRelation(ee, m_phi2) ;
	propagateDartRelation(dprev, m_phi1) ;
	propagateDartRelation(eprev, m_phi1) ;

Pierre Kraemer's avatar
Pierre Kraemer committed
427 428
	propagateDartEmbedding<VERTEX>(dd) ;
	propagateDartEmbedding<VERTEX>(ee) ;
429 430
}

431 432
template <typename PFP>
void Map2MR<PFP>::subdivideEdge(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
433
{
Pierre Kraemer's avatar
Pierre Kraemer committed
434
	assert(getDartLevel(d) <= getCurrentLevel() || !"subdivideEdge : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
435 436
	assert(!edgeIsSubdivided(d) || !"Trying to subdivide an already subdivided edge") ;

437
	assert(getCurrentLevel() == edgeLevel(d) || !"Trying to subdivide an edge on a bad current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
438

439 440
	incCurrentLevel() ;

441 442
	Dart d1 = cutEdge(d) ;
	Dart dd1 = phi2(d) ;
443

444
	(*edgeVertexFunctor)(d1) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
445 446
	propagateDartEmbedding<VERTEX>(d1) ;
	propagateDartEmbedding<VERTEX>(dd1) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
447

448 449 450
	decCurrentLevel() ;
}

451 452
template <typename PFP>
void Map2MR<PFP>::coarsenEdge(Dart d)
453
{
Pierre Kraemer's avatar
Pierre Kraemer committed
454
	assert(getDartLevel(d) <= getCurrentLevel() || !"coarsenEdge : called with a dart inserted after current level") ;
455 456 457 458 459
	assert(edgeCanBeCoarsened(d) || !"Trying to coarsen an edge that can not be coarsened") ;

	incCurrentLevel() ;
	uncutEdge(d) ;
	decCurrentLevel() ;
460

461 462
	unsigned int maxL = getMaxLevel() ;
	if(getCurrentLevel() == maxL - 1 && getNbInsertedDarts(maxL) == 0)
untereiner's avatar
untereiner committed
463
		removeLevelBack() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
464 465
}

466 467
template <typename PFP>
unsigned int Map2MR<PFP>::subdivideFace(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
468
{
Pierre Kraemer's avatar
Pierre Kraemer committed
469
	assert(getDartLevel(d) <= getCurrentLevel() || !"subdivideFace : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
470 471 472 473 474 475 476 477
	assert(!faceIsSubdivided(d) || !"Trying to subdivide an already subdivided face") ;

	unsigned int fLevel = faceLevel(d) ;
	Dart old = faceOldestDart(d) ;

	pushLevel() ;
	setCurrentLevel(fLevel) ;		// go to the level of the face to subdivide its edges

Pierre Kraemer's avatar
Pierre Kraemer committed
478 479 480 481
	if(getCurrentLevel() == getMaxLevel())
		addNewLevel() ;

	unsigned int degree = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
482 483 484
	Dart it = old ;
	do
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
485
		++degree ;						// compute the degree of the face
486 487 488
//		Dart nf = phi2(it) ;
//		if(faceLevel(nf) == fLevel - 1)	// check if neighboring faces have to be subdivided first
//			subdivideFace(nf) ;
489
		if(!edgeIsSubdivided(it))
Pierre Kraemer's avatar
Pierre Kraemer committed
490
			subdivideEdge(it) ;			// and cut the edges (if they are not already)
Pierre Kraemer's avatar
Pierre Kraemer committed
491 492 493 494 495 496 497 498
		it = phi1(it) ;
	} while(it != old) ;

	setCurrentLevel(fLevel + 1) ;	// go to the next level to perform face subdivision

	if(degree == 3)					// if subdividing a triangle
	{
		Dart dd = phi1(old) ;
499 500
		Dart e = phi1(dd) ;
		(*vertexVertexFunctor)(e) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
501
		propagateOrbitEmbedding<VERTEX>(e) ;
502
		e = phi1(e) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
503 504 505
		splitFace(dd, e) ;

		dd = e ;
506 507
		e = phi1(dd) ;
		(*vertexVertexFunctor)(e) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
508
		propagateOrbitEmbedding<VERTEX>(e) ;
509
		e = phi1(e) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
510 511 512
		splitFace(dd, e) ;

		dd = e ;
513 514
		e = phi1(dd) ;
		(*vertexVertexFunctor)(e) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
515
		propagateOrbitEmbedding<VERTEX>(e) ;
516
		e = phi1(e) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
517 518 519 520 521
		splitFace(dd, e) ;
	}
	else							// if subdividing a polygonal face
	{
		Dart dd = phi1(old) ;
522 523
		Dart next = phi1(dd) ;
		(*vertexVertexFunctor)(next) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
524
		propagateOrbitEmbedding<VERTEX>(next) ;
525 526
		next = phi1(next) ;
		splitFace(dd, next) ;			// insert a first edge
Pierre Kraemer's avatar
Pierre Kraemer committed
527 528 529 530
		Dart ne = alpha1(dd) ;

		cutEdge(ne) ;					// cut the new edge to insert the central vertex

531 532
		dd = phi1(next) ;
		(*vertexVertexFunctor)(dd) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
533
		propagateOrbitEmbedding<VERTEX>(dd) ;
534
		dd = phi1(dd) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
535 536
		while(dd != ne)					// turn around the face and insert new edges
		{								// linked to the central vertex
Pierre Kraemer's avatar
Pierre Kraemer committed
537
			splitFace(phi1(ne), dd) ;
538 539
			dd = phi1(dd) ;
			(*vertexVertexFunctor)(dd) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
540
			propagateOrbitEmbedding<VERTEX>(dd) ;
541
			dd = phi1(dd) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
542
		}
543 544

		(*faceVertexFunctor)(phi2(ne)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
545
		propagateOrbitEmbedding<VERTEX>(phi2(ne)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
546 547 548
	}

	popLevel() ;
549 550

	return fLevel ;
Pierre Kraemer's avatar
Pierre Kraemer committed
551 552
}

553 554
template <typename PFP>
void Map2MR<PFP>::coarsenFace(Dart d)
Pierre Kraemer's avatar
Pierre Kraemer committed
555
{
Pierre Kraemer's avatar
Pierre Kraemer committed
556
	assert(getDartLevel(d) <= getCurrentLevel() || !"coarsenFace : called with a dart inserted after current level") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
	assert(faceIsSubdividedOnce(d) || !"Trying to coarsen a non-subdivided face or a more than once subdivided face") ;

	unsigned int degree = 0 ;
	Dart fit = d ;
	do
	{
		++degree ;
		fit = phi1(fit) ;
	} while(fit != d) ;

	if(degree == 3)
	{
		fit = d ;
		do
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
572
			incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
573 574 575
			Dart innerEdge = phi1(fit) ;
			setCurrentLevel(getMaxLevel()) ;
			mergeFaces(innerEdge) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
576
			decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
577 578 579 580 581
			fit = phi1(fit) ;
		} while(fit != d) ;
	}
	else
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
582
		incCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
583 584 585
		Dart centralV = phi1(phi1(d)) ;
		setCurrentLevel(getMaxLevel()) ;
		deleteVertex(centralV) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
586
		decCurrentLevel() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
587 588 589 590 591 592 593 594 595
	}

	fit = d ;
	do
	{
		if(edgeCanBeCoarsened(fit))
			coarsenEdge(fit) ;
		fit = phi1(fit) ;
	} while(fit != d) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
596 597 598

	unsigned int maxL = getMaxLevel() ;
	if(getCurrentLevel() == maxL - 1 && getNbInsertedDarts(maxL) == 0)
untereiner's avatar
untereiner committed
599
		removeLevelBack() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
600 601
}

602 603 604 605 606 607 608 609
} // namespace Adaptive

} // namespace Primal

} // namespace MR

} // namespace Algo

Pierre Kraemer's avatar
Pierre Kraemer committed
610
} // namespace CGoGN