GenericIndexedCloud* CloudSamplingTools::resampleCloudWithOctree(GenericIndexedCloudPersist* theCloud, int newNumberOfPoints, RESAMPLING_CELL_METHOD resamplingMethod, GenericProgressCallback* progressCb, DgmOctree* _theOctree)
{
	assert(theCloud);

	DgmOctree* theOctree = _theOctree;
	if (!theOctree)
	{
		theOctree = new DgmOctree(theCloud);
		if (theOctree->build(progressCb) < 1)
			return 0;
	}

	//on cherche le niveau qui donne le nombre de points le plus proche de la consigne
	uchar bestLevel=theOctree->findBestLevelForAGivenCellNumber(newNumberOfPoints);

	GenericIndexedCloud* sampledCloud = resampleCloudWithOctreeAtLevel(theCloud,bestLevel,resamplingMethod,progressCb,theOctree);

	if (!_theOctree)
		delete theOctree;

	return sampledCloud;
}
int AutoSegmentationTools::labelConnectedComponents(GenericIndexedCloudPersist* theCloud,
													unsigned char level,
													bool sixConnexity/*=false*/,
													GenericProgressCallback* progressCb/*=0*/,
													DgmOctree* inputOctree/*=0*/)
{
	if (!theCloud)
	{
		return -1;
	}

	//compute octree if none was provided
	DgmOctree* theOctree = inputOctree;
	if (!theOctree)
	{
		theOctree = new DgmOctree(theCloud);
		if (theOctree->build(progressCb) < 1)
		{
			delete theOctree;
			return -1;
		}
	}

	//we use the default scalar field to store components labels
	theCloud->enableScalarField();

	int result = theOctree->extractCCs(level, sixConnexity, progressCb);

	//remove octree if it was not provided as input
	if (theOctree && !inputOctree)
	{
		delete theOctree;
	}

	return result;
}
bool AutoSegmentationTools::frontPropagationBasedSegmentation(GenericIndexedCloudPersist* theCloud,
        ScalarType minSeedDist,
        uchar octreeLevel,
        ReferenceCloudContainer& theSegmentedLists,
        GenericProgressCallback* progressCb,
        DgmOctree* inputOctree,
        bool applyGaussianFilter,
        float alpha)
{
    unsigned numberOfPoints = (theCloud ? theCloud->size() : 0);
    if (numberOfPoints == 0)
        return false;

    //compute octree if none was provided
    DgmOctree* theOctree = inputOctree;
    if (!theOctree)
    {
        theOctree = new DgmOctree(theCloud);
        if (theOctree->build(progressCb)<1)
        {
            delete theOctree;
            return false;
        }
    }

    //on calcule le gradient (va ecraser le champ des distances)
    if (ScalarFieldTools::computeScalarFieldGradient(theCloud,true,true,progressCb,theOctree) < 0)
    {
        if (!inputOctree)
            delete theOctree;
        return false;
    }

    //et on lisse le resultat
    if (applyGaussianFilter)
    {
        uchar level = theOctree->findBestLevelForAGivenPopulationPerCell(NUMBER_OF_POINTS_FOR_GRADIENT_COMPUTATION);
        PointCoordinateType cellSize = theOctree->getCellSize(level);
        ScalarFieldTools::applyScalarFieldGaussianFilter(static_cast<float>(cellSize/3),theCloud,-1,progressCb,theOctree);
    }

    unsigned seedPoints = 0;
    unsigned numberOfSegmentedLists = 0;

    //on va faire la propagation avec le FastMarching();
    FastMarchingForPropagation* fm = new FastMarchingForPropagation();

    fm->setJumpCoef(50.0);
    fm->setDetectionThreshold(alpha);

    int result = fm->init(theCloud,theOctree,octreeLevel);
    int octreeLength = OCTREE_LENGTH(octreeLevel)-1;

    if (result<0)
    {
        if (!inputOctree)
            delete theOctree;
        delete fm;
        return false;
    }

    if (progressCb)
    {
        progressCb->reset();
        progressCb->setMethodTitle("FM Propagation");
        char buffer[256];
        sprintf(buffer,"Octree level: %i\nNumber of points: %u",octreeLevel,numberOfPoints);
        progressCb->setInfo(buffer);
        progressCb->start();
    }

    ScalarField* theDists = new ScalarField("distances");
    {
        ScalarType d = theCloud->getPointScalarValue(0);
        if (!theDists->resize(numberOfPoints,true,d))
        {
            if (!inputOctree)
                delete theOctree;
            return false;

        }
    }

    unsigned maxDistIndex = 0, begin = 0;
    CCVector3 startPoint;

    while (true)
    {
        ScalarType maxDist = NAN_VALUE;

        //on cherche la premiere distance superieure ou egale a "minSeedDist"
        while (begin<numberOfPoints)
        {
            const CCVector3 *thePoint = theCloud->getPoint(begin);
            const ScalarType& theDistance = theDists->getValue(begin);
            ++begin;

            //FIXME DGM: what happens if SF is negative?!
            if (theCloud->getPointScalarValue(begin) >= 0 && theDistance >= minSeedDist)
            {
                maxDist = theDistance;
                startPoint = *thePoint;
                maxDistIndex = begin;
                break;
            }
        }

        //il n'y a plus de point avec des distances suffisamment grandes !
        if (maxDist<minSeedDist)
            break;

        //on finit la recherche du max
        for (unsigned i=begin; i<numberOfPoints; ++i)
        {
            const CCVector3 *thePoint = theCloud->getPoint(i);
            const ScalarType& theDistance = theDists->getValue(i);

            if ((theCloud->getPointScalarValue(i)>=0.0)&&(theDistance > maxDist))
            {
                maxDist = theDistance;
                startPoint = *thePoint;
                maxDistIndex = i;
            }
        }

        int pos[3];
        theOctree->getTheCellPosWhichIncludesThePoint(&startPoint,pos,octreeLevel);
        //clipping (important!)
        pos[0] = std::min(octreeLength,pos[0]);
        pos[1] = std::min(octreeLength,pos[1]);
        pos[2] = std::min(octreeLength,pos[2]);
        fm->setSeedCell(pos);
        ++seedPoints;

        int result = fm->propagate();

        //if the propagation was successful
        if (result >= 0)
        {
            //we extract the corresponding points
            ReferenceCloud* newCloud = new ReferenceCloud(theCloud);

            if (fm->extractPropagatedPoints(newCloud) && newCloud->size() != 0)
            {
                theSegmentedLists.push_back(newCloud);
                ++numberOfSegmentedLists;
            }
            else
            {
                //not enough memory?!
                delete newCloud;
                newCloud = 0;
            }

            if (progressCb)
                progressCb->update(float(numberOfSegmentedLists % 100));

            fm->cleanLastPropagation();

            //break;
        }

        if (maxDistIndex == begin)
            ++begin;
    }

    if (progressCb)
        progressCb->stop();

    for (unsigned i=0; i<numberOfPoints; ++i)
        theCloud->setPointScalarValue(i,theDists->getValue(i));

    delete fm;
    fm = 0;

    theDists->release();
    theDists = 0;

    if (!inputOctree)
        delete theOctree;

    return true;
}
double StatisticalTestingTools::testCloudWithStatisticalModel(const GenericDistribution* distrib,
                                                              GenericIndexedCloudPersist* theCloud,
                                                              unsigned numberOfNeighbours,
                                                              double pTrust,
                                                              GenericProgressCallback* progressCb/*=0*/,
                                                              DgmOctree* inputOctree/*=0*/)
{
	assert(theCloud);

	if (!distrib->isValid())
		return -1.0;

	DgmOctree* theOctree = inputOctree;
	if (!theOctree)
	{
		theOctree = new DgmOctree(theCloud);
		if (theOctree->build(progressCb) < 1)
		{
			delete theOctree;
			return -2.0;
		}
	}

	//on active le champ scalaire (IN) pour recevoir les distances du Chi2
	theCloud->enableScalarField();

	unsigned char level = theOctree->findBestLevelForAGivenPopulationPerCell(numberOfNeighbours);

	unsigned numberOfChi2Classes = (unsigned)ceil(sqrt((double)numberOfNeighbours));

	//Chi2 hisogram values
	unsigned* histoValues = new unsigned[numberOfChi2Classes];
	if (!histoValues)
	{
		if (!inputOctree)
			delete theOctree;
		return -3.0;
	}

	ScalarType* histoMin = 0, customHistoMin = 0;
	ScalarType* histoMax = 0, customHistoMax = 0;
	if (strcmp(distrib->getName(),"Gauss")==0)
	{
		const NormalDistribution* nDist = static_cast<const NormalDistribution*>(distrib);
		ScalarType mu=0, sigma2=0;
		nDist->getParameters(mu, sigma2);
		customHistoMin = mu - (ScalarType)3.0 * sqrt(sigma2);
		histoMin = &customHistoMin;
		customHistoMax = mu + (ScalarType)3.0 * sqrt(sigma2);
		histoMax = &customHistoMax;
	}
	else if (strcmp(distrib->getName(),"Weibull")==0)
	{
		customHistoMin = 0;
		histoMin = &customHistoMin;
	}

	//additionnal parameters for local process
	void* additionalParameters[] = {	reinterpret_cast<void*>(const_cast<GenericDistribution*>(distrib)),
										reinterpret_cast<void*>(&numberOfNeighbours),
										reinterpret_cast<void*>(&numberOfChi2Classes),
										reinterpret_cast<void*>(histoValues),
										reinterpret_cast<void*>(histoMin),
										reinterpret_cast<void*>(histoMax) };

	double maxChi2 = -1.0;

	//let's compute Chi2 distances
	if (theOctree->executeFunctionForAllCellsStartingAtLevel(	level,
																&computeLocalChi2DistAtLevel,
																additionalParameters,
																numberOfNeighbours/2,
																numberOfNeighbours*3,
																true,
																progressCb,
																"Statistical Test") != 0) //sucess
	{
		if (!progressCb || !progressCb->isCancelRequested())
		{
			//theoretical Chi2 fractile
			maxChi2 = computeChi2Fractile(pTrust, numberOfChi2Classes-1);
			maxChi2 = sqrt(maxChi2); //on travaille avec les racines carrees des distances du Chi2
		}
	}

	delete[] histoValues;
	histoValues=0;

	if (!inputOctree)
        delete theOctree;

	return maxChi2;
}
Beispiel #5
0
bool AutoSegmentationTools::frontPropagationBasedSegmentation(GenericIndexedCloudPersist* theCloud,
                                                                bool signedSF,
                                                                DistanceType minSeedDist,
                                                                uchar octreeLevel,
                                                                ReferenceCloudContainer& theSegmentedLists,
                                                                GenericProgressCallback* progressCb,
                                                                DgmOctree* _theOctree,
                                                                bool applyGaussianFilter,
                                                                float alpha)
{
	if (!theCloud)
        return false;
	unsigned numberOfPoints = theCloud->size();
	if (numberOfPoints<1)
        return false;

	//on calcule l'octree
	DgmOctree* theOctree = _theOctree;
	if (!theOctree)
	{
		theOctree = new DgmOctree(theCloud);
		if (theOctree->build(progressCb)<1)
		{
			delete theOctree;
			return false;
		}
	}

	ScalarField* theDists = new ScalarField("distances",true);
	if (!theDists->reserve(numberOfPoints))
	{
		if (!_theOctree)
			delete theOctree;
		return false;
	}
	theCloud->placeIteratorAtBegining();
	unsigned k=0;
	DistanceType d = theCloud->getPointScalarValue(k);
	for (;k<numberOfPoints;++k)
        theDists->addElement(d);

	//on calcule le gradient (va écraser le champ des distances)
	if (ScalarFieldTools::computeScalarFieldGradient(theCloud,signedSF,true,true,progressCb,theOctree)<0)
	{
		if (!_theOctree)
			delete theOctree;
		return false;
	}

	//et on lisse le résultat
	if (applyGaussianFilter)
	{
		uchar level = theOctree->findBestLevelForAGivenPopulationPerCell(NUMBER_OF_POINTS_FOR_GRADIENT_COMPUTATION);
		float cellSize = theOctree->getCellSize(level);
        ScalarFieldTools::applyScalarFieldGaussianFilter(cellSize*0.33f,theCloud,signedSF,-1,progressCb,theOctree);
	}

	DistanceType maxDist;
	unsigned seedPoints = 0;
	unsigned numberOfSegmentedLists = 0;

	//on va faire la propagation avec le FastMarching();
	FastMarchingForPropagation* fm = new FastMarchingForPropagation();

	fm->setJumpCoef(50.0);
	fm->setDetectionThreshold(alpha);

	int result = fm->init(theCloud,theOctree,octreeLevel);
	int octreeLength = OCTREE_LENGTH(octreeLevel)-1;

	if (result<0)
	{
		if (!_theOctree)
            delete theOctree;
		delete fm;
		return false;
	}

	if (progressCb)
	{
		progressCb->reset();
		progressCb->setMethodTitle("FM Propagation");
		char buffer[256];
		sprintf(buffer,"Octree level: %i\nNumber of points: %i",octreeLevel,numberOfPoints);
		progressCb->setInfo(buffer);
		progressCb->start();
	}

	unsigned maxDistIndex=0,begin = 0;
	CCVector3 startPoint;

	while (true)
	{
		maxDist = HIDDEN_VALUE;

		//on cherche la première distance supérieure ou égale à "minSeedDist"
		while (begin<numberOfPoints)
		{
			const CCVector3 *thePoint = theCloud->getPoint(begin);
			const DistanceType& theDistance = theDists->getValue(begin);
			++begin;

			if ((theCloud->getPointScalarValue(begin)>=0.0)&&(theDistance >= minSeedDist))
			{
				maxDist = theDistance;
				startPoint = *thePoint;
				maxDistIndex = begin;
				break;
			}
		}

		//il n'y a plus de point avec des distances suffisamment grandes !
		if (maxDist<minSeedDist)
            break;

		//on finit la recherche du max
		for (unsigned i=begin;i<numberOfPoints;++i)
		{
			const CCVector3 *thePoint = theCloud->getPoint(i);
			const DistanceType& theDistance = theDists->getValue(i);

			if ((theCloud->getPointScalarValue(i)>=0.0)&&(theDistance > maxDist))
			{
				maxDist = theDistance;
				startPoint = *thePoint;
				maxDistIndex = i;
			}
		}

		//on lance la propagation à partir du point de distance maximale
		//propagateFromPoint(aList,_GradientNorms,maxDistIndex,octreeLevel,_gui);

		int pos[3];
		theOctree->getTheCellPosWhichIncludesThePoint(&startPoint,pos,octreeLevel);
		//clipping (important !)
		pos[0] = std::min(octreeLength,pos[0]);
		pos[1] = std::min(octreeLength,pos[1]);
		pos[2] = std::min(octreeLength,pos[2]);
		fm->setSeedCell(pos);
		++seedPoints;

		int result = fm->propagate();

		//si la propagation s'est bien passée
		if (result>=0)
		{
			//on la termine (i.e. on extrait les points correspondant)
			ReferenceCloud* newCloud = fm->extractPropagatedPoints();

			//si la liste convient
			//on la rajoute au groupe des listes segmentées
			theSegmentedLists.push_back(newCloud);
			++numberOfSegmentedLists;

			if (progressCb)
                progressCb->update(float(numberOfSegmentedLists % 100));

			fm->endPropagation();

			//break;
		}

		if (maxDistIndex == begin)
            ++begin;
	}

	if (progressCb)
		progressCb->stop();

	for (unsigned i=0;i<numberOfPoints;++i)
		theCloud->setPointScalarValue(i,theDists->getValue(i));

	delete fm;
	theDists->release();
	theDists=0;

	if (!_theOctree)
		delete theOctree;

	return true;
}
ReferenceCloud* CloudSamplingTools::noiseFilter(GenericIndexedCloudPersist* inputCloud,
												PointCoordinateType kernelRadius,
												double nSigma,
												bool removeIsolatedPoints/*=false*/,
												bool useKnn/*=false*/,
												int knn/*=6*/,
												bool useAbsoluteError/*=true*/,
												double absoluteError/*=0.0*/,
												DgmOctree* inputOctree/*=0*/,
												GenericProgressCallback* progressCb/*=0*/)
{
	if (!inputCloud || inputCloud->size() < 2 || (useKnn && knn <= 0) || (!useKnn && kernelRadius <= 0))
	{
		//invalid input
		assert(false);
		return 0;
	}

	DgmOctree* octree = inputOctree;
	if (!octree)
	{
		octree = new DgmOctree(inputCloud);
		if (octree->build(progressCb) < 1)
		{
			delete octree;
			return 0;
		}
	}

	ReferenceCloud* filteredCloud = new ReferenceCloud(inputCloud);

	unsigned pointCount = inputCloud->size();
	if (!filteredCloud->reserve(pointCount))
	{
		//not enough memory
		if (!inputOctree)
			delete octree;
		delete filteredCloud;
		return 0;
	}

	//additional parameters
	void* additionalParameters[] = {reinterpret_cast<void*>(filteredCloud),
									reinterpret_cast<void*>(&kernelRadius),
									reinterpret_cast<void*>(&nSigma),
									reinterpret_cast<void*>(&removeIsolatedPoints),
									reinterpret_cast<void*>(&useKnn),
									reinterpret_cast<void*>(&knn),
									reinterpret_cast<void*>(&useAbsoluteError),
									reinterpret_cast<void*>(&absoluteError)
	};

	unsigned char octreeLevel = 0;
	if (useKnn)
		octreeLevel = octree->findBestLevelForAGivenNeighbourhoodSizeExtraction(kernelRadius);
	else
		octreeLevel = octree->findBestLevelForAGivenPopulationPerCell(knn);

	if (octree->executeFunctionForAllCellsAtLevel(	octreeLevel,
													&applyNoiseFilterAtLevel,
													additionalParameters,
													true,
													progressCb,
													"Noise filter" ) == 0)
	{
		//something went wrong
		delete filteredCloud;
		filteredCloud = 0;
	}

	if (!inputOctree)
	{
		delete octree;
		octree = 0;
	}

	if (filteredCloud)
	{
		filteredCloud->resize(filteredCloud->size());
	}

	return filteredCloud;
}
ReferenceCloud* CloudSamplingTools::sorFilter(	GenericIndexedCloudPersist* inputCloud,
												int knn/*=6*/,
												double nSigma/*=1.0*/,
												DgmOctree* inputOctree/*=0*/,
												GenericProgressCallback* progressCb/*=0*/)
{
	if (!inputCloud || knn <= 0 || inputCloud->size() <= static_cast<unsigned>(knn))
	{
		//invalid input
		assert(false);
		return 0;
	}

	DgmOctree* octree = inputOctree;
	if (!octree)
	{
		//compute the octree if necessary
		octree = new DgmOctree(inputCloud);
		if (octree->build(progressCb) < 1)
		{
			delete octree;
			return 0;
		}
	}

	//output
	ReferenceCloud* filteredCloud = 0;

	for (unsigned step=0; step<1; ++step) //fake loop for easy break
	{
		unsigned pointCount = inputCloud->size();

		std::vector<PointCoordinateType> meanDistances;
		try
		{
			meanDistances.resize(pointCount,0);
		}
		catch (const std::bad_alloc&)
		{
			//not enough memory
			break;
		}
		double avgDist = 0, stdDev = 0;

		//1st step: compute the average distance to the neighbors
		{
			//additional parameters
			void* additionalParameters[] = {reinterpret_cast<void*>(&knn),
											reinterpret_cast<void*>(&meanDistances)
			};

			unsigned char octreeLevel = octree->findBestLevelForAGivenPopulationPerCell(knn);

			if (octree->executeFunctionForAllCellsAtLevel(	octreeLevel,
															&applySORFilterAtLevel,
															additionalParameters,
															true,
															progressCb,
															"SOR filter") == 0)
			{
				//something went wrong
				break;
			}

			//deduce the average distance and std. dev.
			double sumDist = 0;
			double sumSquareDist = 0;
			for (unsigned i=0; i<pointCount; ++i)
			{
				sumDist += meanDistances[i];
				sumSquareDist += meanDistances[i]*meanDistances[i];
			}
			avgDist = sumDist / pointCount;
			stdDev = sqrt(fabs(sumSquareDist / pointCount - avgDist*avgDist));
		}

		//2nd step: remove the farthest points 
		{
			//deduce the max distance
			double maxDist = avgDist + nSigma * stdDev;

			filteredCloud = new ReferenceCloud(inputCloud);
			if (!filteredCloud->reserve(pointCount))
			{
				//not enough memory
				delete filteredCloud;
				filteredCloud = 0;
				break;
			}

			for (unsigned i=0; i<pointCount; ++i)
			{
				if (meanDistances[i] <= maxDist)
				{
					filteredCloud->addPointIndex(i);
				}
			}

			filteredCloud->resize(filteredCloud->size());
		}
	}

	if (!inputOctree)
	{
		delete octree;
		octree = 0;
	}

	return filteredCloud;
}
ReferenceCloud* CloudSamplingTools::resampleCloudSpatially(GenericIndexedCloudPersist* inputCloud,
															PointCoordinateType minDistance,
															const SFModulationParams& modParams,
															DgmOctree* inputOctree/*=0*/,
															GenericProgressCallback* progressCb/*=0*/)
{
	assert(inputCloud);
    unsigned cloudSize = inputCloud->size();

    DgmOctree* octree = inputOctree;
	if (!octree)
	{
		octree = new DgmOctree(inputCloud);
		if (octree->build() < static_cast<int>(cloudSize))
		{
			delete octree;
			return 0;
		}
	}
	assert(octree && octree->associatedCloud() == inputCloud);

	//output cloud
	ReferenceCloud* sampledCloud = new ReferenceCloud(inputCloud);
	const unsigned c_reserveStep = 65536;
	if (!sampledCloud->reserve(std::min(cloudSize,c_reserveStep)))
	{
		if (!inputOctree)
			delete octree;
		return 0;
	}

	GenericChunkedArray<1,char>* markers = new GenericChunkedArray<1,char>(); //DGM: upgraded from vector, as this can be quite huge!
	if (!markers->resize(cloudSize,true,1)) //true by default
	{
		markers->release();
		if (!inputOctree)
			delete octree;
		delete sampledCloud;
		return 0;
	}

	//best octree level (there may be several of them if we use parameter modulation)
	std::vector<unsigned char> bestOctreeLevel;
	bool modParamsEnabled = modParams.enabled;
	ScalarType sfMin = 0, sfMax = 0;
	try
	{
		if (modParams.enabled)
		{
			//compute min and max sf values
			ScalarFieldTools::computeScalarFieldExtremas(inputCloud,sfMin,sfMax);

			if (!ScalarField::ValidValue(sfMin))
			{
				//all SF values are NAN?!
				modParamsEnabled = false;
			}
			else
			{
				//compute min and max 'best' levels
				PointCoordinateType dist0 = static_cast<PointCoordinateType>(sfMin * modParams.a + modParams.b);
				PointCoordinateType dist1 = static_cast<PointCoordinateType>(sfMax * modParams.a + modParams.b);
				unsigned char level0 = octree->findBestLevelForAGivenNeighbourhoodSizeExtraction(dist0);
				unsigned char level1 = octree->findBestLevelForAGivenNeighbourhoodSizeExtraction(dist1);

				bestOctreeLevel.push_back(level0);
				if (level1 != level0)
				{
					//add intermediate levels if necessary
					size_t levelCount = (level1 < level0 ? level0-level1 : level1-level0) + 1;
					assert(levelCount != 0);
					
					for (size_t i=1; i<levelCount-1; ++i) //we already know level0 and level1!
					{
						ScalarType sfVal = sfMin + i*((sfMax-sfMin)/levelCount);
						PointCoordinateType dist = static_cast<PointCoordinateType>(sfVal * modParams.a + modParams.b);
						unsigned char level = octree->findBestLevelForAGivenNeighbourhoodSizeExtraction(dist);
						bestOctreeLevel.push_back(level);
					}
				}
				bestOctreeLevel.push_back(level1);
			}
		}
		else
		{
			unsigned char defaultLevel = octree->findBestLevelForAGivenNeighbourhoodSizeExtraction(minDistance);
			bestOctreeLevel.push_back(defaultLevel);
		}
	}
	catch (const std::bad_alloc&)
	{
		//not enough memory
		markers->release();
		if (!inputOctree)
		{
			delete octree;
		}
		delete sampledCloud;
		return 0;
	}

	//progress notification
	NormalizedProgress normProgress(progressCb, cloudSize);
	if (progressCb)
	{
		if (progressCb->textCanBeEdited())
		{
			progressCb->setMethodTitle("Spatial resampling");
			char buffer[256];
			sprintf(buffer, "Points: %u\nMin dist.: %f", cloudSize, minDistance);
			progressCb->setInfo(buffer);
		}
		progressCb->update(0);
		progressCb->start();
	}

	//for each point in the cloud that is still 'marked', we look
	//for its neighbors and remove their own marks
	markers->placeIteratorAtBegining();
	bool error = false;
	//default octree level
	assert(!bestOctreeLevel.empty());
	unsigned char octreeLevel = bestOctreeLevel.front();
	//default distance between points
	PointCoordinateType minDistBetweenPoints = minDistance;
	for (unsigned i=0; i<cloudSize; i++, markers->forwardIterator())
	{
		//no mark? we skip this point
		if (markers->getCurrentValue() != 0)
		{
			//init neighbor search structure
			const CCVector3* P = inputCloud->getPoint(i);

			//parameters modulation
			if (modParamsEnabled)
			{
				ScalarType sfVal = inputCloud->getPointScalarValue(i);
				if (ScalarField::ValidValue(sfVal))
				{
					//modulate minDistance
					minDistBetweenPoints = static_cast<PointCoordinateType>(sfVal * modParams.a + modParams.b);
					//get (approximate) best level
					size_t levelIndex = static_cast<size_t>(bestOctreeLevel.size() * (sfVal / (sfMax-sfMin)));
					if (levelIndex == bestOctreeLevel.size())
						--levelIndex;
					octreeLevel = bestOctreeLevel[levelIndex];
				}
				else
				{
					minDistBetweenPoints = minDistance;
					octreeLevel = bestOctreeLevel.front();
				}
			}

			//look for neighbors and 'de-mark' them
			{
				DgmOctree::NeighboursSet neighbours;
				octree->getPointsInSphericalNeighbourhood(*P,minDistBetweenPoints,neighbours,octreeLevel);
				for (DgmOctree::NeighboursSet::iterator it = neighbours.begin(); it != neighbours.end(); ++it)
					if (it->pointIndex != i)
						markers->setValue(it->pointIndex,0);
			}

			//At this stage, the ith point is the only one marked in a radius of <minDistance>.
			//Therefore it will necessarily be in the final cloud!
			if (sampledCloud->size() == sampledCloud->capacity() && !sampledCloud->reserve(sampledCloud->capacity() + c_reserveStep))
			{
				//not enough memory
				error = true;
				break;
			}
			if (!sampledCloud->addPointIndex(i))
			{
				//not enough memory
				error = true;
				break;
			}
		}
			
		//progress indicator
		if (progressCb && !normProgress.oneStep())
		{
			//cancel process
			error = true;
			break;
		}
	}

	//remove unnecessarily allocated memory
	if (!error)
	{
		if (sampledCloud->capacity() > sampledCloud->size())
			sampledCloud->resize(sampledCloud->size());
	}
	else
	{
		delete sampledCloud;
		sampledCloud = 0;
	}

	if (progressCb)
	{
		progressCb->stop();
	}

	if (!inputOctree)
	{
		//locally computed octree
		delete octree;
		octree = 0;
	}

	markers->release();
	markers = 0;

	return sampledCloud;
}
int GeometricalAnalysisTools::computeLocalDensity(	GenericIndexedCloudPersist* theCloud,
													Density densityType,
													PointCoordinateType kernelRadius,
													GenericProgressCallback* progressCb/*=0*/,
													DgmOctree* inputOctree/*=0*/)
{
	if (!theCloud)
		return -1;

	unsigned numberOfPoints = theCloud->size();
	if (numberOfPoints < 3)
		return -2;

	//compute the right dimensional coef based on the expected output
	double dimensionalCoef = 1.0;
	switch (densityType)
	{
	case DENSITY_KNN:
		dimensionalCoef = 1.0;
		break;
	case DENSITY_2D:
		dimensionalCoef = M_PI * (static_cast<double>(kernelRadius) * kernelRadius);
		break;
	case DENSITY_3D:
		dimensionalCoef = s_UnitSphereVolume * ((static_cast<double>(kernelRadius) * kernelRadius) * kernelRadius);
		break;
	default:
		assert(false);
		return -5;
	}

	DgmOctree* theOctree = inputOctree;
	if (!theOctree)
	{
		theOctree = new DgmOctree(theCloud);
		if (theOctree->build(progressCb) < 1)
		{
			delete theOctree;
			return -3;
		}
	}

	theCloud->enableScalarField();

	//determine best octree level to perform the computation
	unsigned char level = theOctree->findBestLevelForAGivenNeighbourhoodSizeExtraction(kernelRadius);

	//parameters
	void* additionalParameters[] = {	static_cast<void*>(&kernelRadius),
										static_cast<void*>(&dimensionalCoef) };

	int result = 0;

	if (theOctree->executeFunctionForAllCellsAtLevel(	level,
														&computePointsDensityInACellAtLevel,
														additionalParameters,
														true,
														progressCb,
														"Local Density Computation") == 0)
	{
		//something went wrong
		result = -4;
	}

	if (!inputOctree)
        delete theOctree;

	return result;
}
Beispiel #10
0
int ScalarFieldTools::computeScalarFieldGradient(	GenericIndexedCloudPersist* theCloud,
													PointCoordinateType radius,
													bool euclideanDistances,
													bool sameInAndOutScalarField/*=false*/,
													GenericProgressCallback* progressCb/*=0*/,
													DgmOctree* theCloudOctree/*=0*/)
{
	if (!theCloud)
        return -1;

	DgmOctree* theOctree = theCloudOctree;
	if (!theOctree)
	{
		theOctree = new DgmOctree(theCloud);
		if (theOctree->build(progressCb)<1)
		{
			delete theOctree;
			return -2;
		}
	}

	unsigned char octreeLevel = 0;
	if (radius <= 0)
	{
		octreeLevel = theOctree->findBestLevelForAGivenPopulationPerCell(AVERAGE_NUMBER_OF_POINTS_FOR_GRADIENT_COMPUTATION);
		radius = theOctree->getCellSize(octreeLevel);
	}
	else
	{
		octreeLevel = theOctree->findBestLevelForAGivenNeighbourhoodSizeExtraction(radius);
	}

	ScalarField* theGradientNorms = new ScalarField("gradient norms");
	ScalarField* _theGradientNorms = 0;

	//mode champ scalaire "IN" et "OUT" identique
	if (sameInAndOutScalarField)
	{
		if (!theGradientNorms->reserve(theCloud->size())) //not enough memory
		{
			if (!theCloudOctree)
				delete theOctree;
			theGradientNorms->release();
			return -3;
		}
		_theGradientNorms = theGradientNorms;
	}
	else
	//mode champs scalaires "IN" et "OUT" dfferents (par defaut)
	{
		//on initialise les distances (IN - en ecriture) pour recevoir les normes du gradient
		if (!theCloud->enableScalarField())
		{
			if (!theCloudOctree)
				delete theOctree;
			theGradientNorms->release();
			return -4;
		}
	}

	//structure contenant les parametres additionnels
	void* additionalParameters[3] = {	static_cast<void*>(&euclideanDistances),
										static_cast<void*>(&radius),
										static_cast<void*>(_theGradientNorms)
	};

	int result = 0;

	if (theOctree->executeFunctionForAllCellsAtLevel(	octreeLevel,
														computeMeanGradientOnPatch,
														additionalParameters,
														true,
														progressCb,
														"Gradient Computation") == 0)
	{
		//something went wrong
		result = -5;
	}

	if (!theCloudOctree)
        delete theOctree;

	theGradientNorms->release();
	theGradientNorms=0;

    return result;
}
Beispiel #11
0
bool ScalarFieldTools::applyScalarFieldGaussianFilter(PointCoordinateType sigma,
													  GenericIndexedCloudPersist* theCloud,
													  PointCoordinateType sigmaSF,
													  GenericProgressCallback* progressCb,
													  DgmOctree* theCloudOctree)
{
	if (!theCloud)
        return false;

	unsigned n = theCloud->size();
	if (n==0)
        return false;

	DgmOctree* theOctree = 0;
	if (theCloudOctree)
        theOctree = theCloudOctree;
	else
	{
		theOctree = new DgmOctree(theCloud);
		if (theOctree->build(progressCb)<1)
		{
			delete theOctree;
			return false;
		}
	}

    //best octree level
	unsigned char level = theOctree->findBestLevelForAGivenNeighbourhoodSizeExtraction(3.0f*sigma);

	//output scalar field should be different than input one
	theCloud->enableScalarField();

	if (progressCb)
	{
		if (progressCb->textCanBeEdited())
		{
			progressCb->setMethodTitle("Gaussian filter");
			char infos[256];
			sprintf(infos, "Level: %i\n", level);
			progressCb->setInfo(infos);
		}
		progressCb->update(0);
	}

    void* additionalParameters[2] = {	reinterpret_cast<void*>(&sigma),
										reinterpret_cast<void*>(&sigmaSF)
	};

	bool success = true;

	if (theOctree->executeFunctionForAllCellsAtLevel(	level,
														computeCellGaussianFilter,
														additionalParameters,
														true,
														progressCb,
														"Gaussian Filter computation") == 0)
	{
		//something went wrong
		success = false;
	}

	return success;
}