bool ccMinimumSpanningTreeForNormsDirection::Process(	ccPointCloud* cloud,
														CCLib::GenericProgressCallback* progressCb/*=0*/,
														CCLib::DgmOctree* _octree/*=0*/)
{
	assert(cloud);
	if (!cloud->hasNormals())
	{
		ccLog::Warning(QString("Cloud '%1' has no normals!").arg(cloud->getName()));
		return false;
	}

	//ask for parameter
	bool ok;
#ifdef MST_USE_KNN
	unsigned kNN = static_cast<unsigned>(QInputDialog::getInt(0,"Neighborhood size", "Neighbors", 6, 1, 1000, 1, &ok));
	if (!ok)
		return false;
#else
	PointCoordinateType radius = static_cast<PointCoordinateType>(QInputDialog::getDouble(0,"Neighborhood radius", "radius", cloud->getOwnBB().getDiagNorm() * 0.01, 0, 1.0e9, 6, &ok));
	if (!ok)
		return false;
#endif

	//build octree if necessary
	CCLib::DgmOctree* octree = _octree;
	if (!octree)
	{
		octree = new CCLib::DgmOctree(cloud);
		if (octree->build(progressCb) <= 0)
		{
			ccLog::Warning(QString("Failed to compute octree on cloud '%1'").arg(cloud->getName()));
			delete octree;
			return false;
		}
	}
		
#ifdef MST_USE_KNN
	uchar level = octree->findBestLevelForAGivenPopulationPerCell(kNN*2);
#else
	uchar level = octree->findBestLevelForAGivenNeighbourhoodSizeExtraction(radius);
#endif

	bool result = true;
	try
	{
		Graph graph;
		if (!graph.reserve(cloud->size()))
		{
			//not enough memory!
			result = false;
		}

		//parameters
		void* additionalParameters[3] = {	reinterpret_cast<void*>(&graph),
											reinterpret_cast<void*>(cloud),
#ifdef MST_USE_KNN
											reinterpret_cast<void*>(&kNN)
#else
											reinterpret_cast<void*>(&radius)
#endif
										};

		if (octree->executeFunctionForAllCellsAtLevel(	level,
														&ComputeMSTGraphAtLevel,
														additionalParameters,
														false, //not compatible with parallel strategies!
														progressCb,
														"Build Spanning Tree") == 0)
		{
			//something went wrong
			ccLog::Warning(QString("Failed to compute Spanning Tree on cloud '%1'").arg(cloud->getName()));
			result = false;
		}
		else
		{
			if (!ResolveNormalsWithMST(cloud,graph,progressCb))
			{
				//something went wrong
				ccLog::Warning(QString("Failed to compute Minimum Spanning Tree on cloud '%1'").arg(cloud->getName()));
				result = false;
			}
		}
	}
	catch(...)
	{
		ccLog::Error(QString("Process failed on cloud '%1'").arg(cloud->getName()));
		result = false;
	}

	if (octree && !_octree)
	{
		delete octree;
		octree = 0;
	}

	return result;
}
bool ccMinimumSpanningTreeForNormsDirection::OrientNormals(	ccPointCloud* cloud,
        unsigned kNN/*=6*/,
        ccProgressDialog* progressDlg/*=0*/)
{
    assert(cloud);
    if (!cloud->hasNormals())
    {
        ccLog::Warning(QString("Cloud '%1' has no normals!").arg(cloud->getName()));
        return false;
    }

    //we need the octree
    if (!cloud->getOctree())
    {
        if (!cloud->computeOctree(progressDlg))
        {
            ccLog::Warning(QString("[orientNormalsWithMST] Could not compute octree on cloud '%1'").arg(cloud->getName()));
            return false;
        }
    }
    ccOctree::Shared octree = cloud->getOctree();
    assert(octree);

    unsigned char level = octree->findBestLevelForAGivenPopulationPerCell(kNN*2);

    bool result = true;
    try
    {
        Graph graph;
        if (!graph.reserve(cloud->size()))
        {
            //not enough memory!
            result = false;
        }

        //parameters
        void* additionalParameters[3] = {	reinterpret_cast<void*>(&graph),
                                            reinterpret_cast<void*>(cloud),
                                            reinterpret_cast<void*>(&kNN)
                                        };

        if (octree->executeFunctionForAllCellsAtLevel(	level,
                &ComputeMSTGraphAtLevel,
                additionalParameters,
                false, //not compatible with parallel strategies!
                progressDlg,
                "Build Spanning Tree") == 0)
        {
            //something went wrong
            ccLog::Warning(QString("Failed to compute Spanning Tree on cloud '%1'").arg(cloud->getName()));
            result = false;
        }
        else
        {
            if (!ResolveNormalsWithMST(cloud, graph, progressDlg))
            {
                //something went wrong
                ccLog::Warning(QString("Failed to compute Minimum Spanning Tree on cloud '%1'").arg(cloud->getName()));
                result = false;
            }
        }
    }
    catch (...)
    {
        ccLog::Error(QString("Process failed on cloud '%1'").arg(cloud->getName()));
        result = false;
    }

    return result;
}