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