int ccFastMarchingForNormsDirection::init(ccGenericPointCloud* aList,
                                            NormsIndexesTableType* theNorms,
                                            CCLib::DgmOctree* _theOctree,
                                            uchar level)
{
	//on commence par créer une grille 3D
	theOctree = _theOctree;
	gridLevel = level;

	int result = initGrid();

	if (result<0) return result;

	//printf("cellSize=%f\n",cellSize);

	//on remplit la grille
	CCLib::DgmOctree::cellCodesContainer cellCodes;
	theOctree->getCellCodes(gridLevel,cellCodes,true);

	int cellPos[3];

	while (!cellCodes.empty())
	{
		//on transforme le code de cellule en position
		theOctree->getCellPos(cellCodes.back(),gridLevel,cellPos,true);

		//on renseigne la grille
		unsigned gridPos = FM_pos2index(cellPos);

		DirectionCell* aCell = new DirectionCell;
		aCell->state = CCLib::FastMarching::Cell::FAR_CELL;
		aCell->T = FM_INF;
		aCell->treated = false;
		aCell->v = 0.0;
		aCell->cellCode = cellCodes.back();

		CCLib::ReferenceCloud* Yk = theOctree->getPointsInCell(cellCodes.back(),gridLevel,true);
		if (Yk)
		{
			ccOctree::ComputeRobustAverageNorm(Yk,aList,aCell->N);
			//Yk->clear(); //inutile

			//printf("code %i -> cell(%i,%i,%i) --> %i\n",cellCodes.back(),cellPos[0],cellPos[1],cellPos[2],gridPos);
			theGrid[gridPos] = (CCLib::FastMarching::Cell*)aCell;
		}

		cellCodes.pop_back();
	}

	initialized = true;

	return 0;
}
int ccFastMarchingForNormsDirection::init(	ccGenericPointCloud* cloud,
											NormsIndexesTableType* theNorms,
											ccOctree* theOctree,
											unsigned char level)
{
	int result = initGridWithOctree(theOctree, level);
	if (result < 0)
		return result;

	//fill the grid with the octree
	CCLib::DgmOctree::cellCodesContainer cellCodes;
	theOctree->getCellCodes(level,cellCodes,true);

	CCLib::ReferenceCloud Yk(theOctree->associatedCloud());

	while (!cellCodes.empty())
	{
		if (!theOctree->getPointsInCell(cellCodes.back(),level,&Yk,true))
		{
			//not enough memory
			return -1;
		}
		
		//convert the octree cell code to grid position
		Tuple3i cellPos;
		theOctree->getCellPos(cellCodes.back(),level,cellPos,true);

		//convert it to FM cell pos index
		unsigned gridPos = pos2index(cellPos);

		//create corresponding cell
		DirectionCell* aCell = new DirectionCell;
		{
			//aCell->signConfidence = 1;
			aCell->cellCode = cellCodes.back();
			aCell->N = ComputeRobustAverageNorm(&Yk,cloud);
			aCell->C = *CCLib::Neighbourhood(&Yk).getGravityCenter();
		}

		m_theGrid[gridPos] = aCell;

		cellCodes.pop_back();
	}

	m_initialized = true;

	return 0;
}
int FastMarchingForFacetExtraction::init(	ccGenericPointCloud* cloud,
											CCLib::DgmOctree* theOctree,
											unsigned char level,
											ScalarType maxError,
											CCLib::DistanceComputationTools::ERROR_MEASURES errorMeasure,
											bool useRetroProjectionError,
											CCLib::GenericProgressCallback* progressCb/*=0*/)
{
	m_maxError = maxError;
	m_errorMeasure = errorMeasure;
	m_useRetroProjectionError = useRetroProjectionError;

	if (progressCb)
	{
		if (progressCb->textCanBeEdited())
		{
			progressCb->setMethodTitle("Fast Marching grid initialization");
			progressCb->setInfo(qPrintable(QString("Level: %1").arg(level)));
		}
		progressCb->update(0);
		progressCb->start();
	}

	int result = initGridWithOctree(theOctree, level);
	if (result < 0)
		return result;

	//fill the grid with the octree
	CCLib::DgmOctree::cellCodesContainer cellCodes;
	theOctree->getCellCodes(level,cellCodes,true);
	size_t cellCount = cellCodes.size();

	CCLib::NormalizedProgress nProgress(progressCb, static_cast<unsigned>(cellCount));
	if (progressCb)
	{
		progressCb->setInfo(qPrintable(QString("Level: %1\nCells: %2").arg(level).arg(cellCount)));
	}

	CCLib::ReferenceCloud Yk(theOctree->associatedCloud());
	while (!cellCodes.empty())
	{
		if (theOctree->getPointsInCell(cellCodes.back(),level,&Yk,true))
		{
			//convert the octree cell code to grid position
			Tuple3i cellPos;
			theOctree->getCellPos(cellCodes.back(),level,cellPos,true);

			CCVector3 N,C;
			ScalarType error;
			if (ComputeCellStats(&Yk,N,C,error,m_errorMeasure))
			{
				//convert octree cell pos to FM cell pos index
				unsigned gridPos = pos2index(cellPos);

				//create corresponding cell
				PlanarCell* aCell = new PlanarCell;
				aCell->cellCode = cellCodes.back();
				aCell->N = N;
				aCell->C = C;
				aCell->planarError = error;
				m_theGrid[gridPos] = aCell;
			}
			else
			{
				//an error occurred?!
				return -10;
			}
		}

		cellCodes.pop_back();

		if (progressCb && !nProgress.oneStep())
		{
			//process cancelled by user
			progressCb->stop();
			return -1;
		}
	}

	if (progressCb)
	{
		progressCb->stop();
	}
		
	m_initialized = true;

	return 0;
}