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) { progressCb->reset(); progressCb->setMethodTitle("Gaussian filter"); char infos[256]; sprintf(infos,"Level: %i\n",level); progressCb->setInfo(infos); } 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; }
SimpleCloud* CloudSamplingTools::resampleCloudWithOctreeAtLevel(GenericIndexedCloudPersist* theCloud, uchar octreeLevel, RESAMPLING_CELL_METHOD resamplingMethod, GenericProgressCallback* progressCb, DgmOctree* _theOctree) { assert(theCloud); DgmOctree* theOctree = _theOctree; if (!theOctree) { theOctree = new DgmOctree(theCloud); if (theOctree->build(progressCb) < 1) { delete theOctree; return 0; } } SimpleCloud* cloud = new SimpleCloud(); unsigned nCells = theOctree->getCellNumber(octreeLevel); if (!cloud->reserve(nCells)) { if (!_theOctree) delete theOctree; delete cloud; return 0; } //structure contenant les parametres additionnels void* additionalParameters[2]; additionalParameters[0] = (void*)cloud; additionalParameters[1] = (void*)&resamplingMethod; //The process is so simple that MT is slower! //#ifdef ENABLE_MT_OCTREE //theOctree->executeFunctionForAllCellsAtLevel_MT(octreeLevel, //#else if (theOctree->executeFunctionForAllCellsAtLevel(octreeLevel, &resampleCellAtLevel, additionalParameters, progressCb, "Cloud Resampling") == 0) { //something went wrong delete cloud; cloud=0; } if (!_theOctree) delete theOctree; return cloud; }
SimpleCloud* CloudSamplingTools::resampleCloudWithOctreeAtLevel(GenericIndexedCloudPersist* inputCloud, unsigned char octreeLevel, RESAMPLING_CELL_METHOD resamplingMethod, GenericProgressCallback* progressCb/*=0*/, DgmOctree* inputOctree/*=0*/) { assert(inputCloud); DgmOctree* octree = inputOctree; if (!octree) { octree = new DgmOctree(inputCloud); if (octree->build(progressCb) < 1) { delete octree; return 0; } } SimpleCloud* cloud = new SimpleCloud(); unsigned nCells = octree->getCellNumber(octreeLevel); if (!cloud->reserve(nCells)) { if (!inputOctree) delete octree; delete cloud; return 0; } //structure contenant les parametres additionnels void* additionalParameters[2] = { reinterpret_cast<void*>(cloud), reinterpret_cast<void*>(&resamplingMethod) }; if (octree->executeFunctionForAllCellsAtLevel( octreeLevel, &resampleCellAtLevel, additionalParameters, false, //the process is so simple that MT is slower! progressCb, "Cloud Resampling") == 0) { //something went wrong delete cloud; cloud=0; } if (!inputOctree) delete octree; return cloud; }
int GeometricalAnalysisTools::computeCurvature( GenericIndexedCloudPersist* theCloud, Neighbourhood::CC_CURVATURE_TYPE cType, PointCoordinateType kernelRadius, GenericProgressCallback* progressCb/*=0*/, DgmOctree* inputOctree/*=0*/) { if (!theCloud) return -1; unsigned numberOfPoints = theCloud->size(); if (numberOfPoints < 5) return -2; DgmOctree* theOctree = inputOctree; if (!theOctree) { theOctree = new DgmOctree(theCloud); if (theOctree->build(progressCb) < 1) { delete theOctree; return -3; } } theCloud->enableScalarField(); unsigned char level = theOctree->findBestLevelForAGivenNeighbourhoodSizeExtraction(kernelRadius); //parameters void* additionalParameters[2] = { static_cast<void*>(&cType), static_cast<void*>(&kernelRadius) }; int result = 0; if (theOctree->executeFunctionForAllCellsAtLevel(level, &computeCellCurvatureAtLevel, additionalParameters, true, progressCb, "Curvature Computation") == 0) { //something went wrong result = -4; } if (!inputOctree) delete theOctree; return result; }
int GeometricalAnalysisTools::flagDuplicatePoints( GenericIndexedCloudPersist* theCloud, double minDistanceBetweenPoints/*=1.0e-12*/, GenericProgressCallback* progressCb/*=0*/, DgmOctree* inputOctree/*=0*/) { if (!theCloud) return -1; unsigned numberOfPoints = theCloud->size(); if (numberOfPoints <= 1) return -2; DgmOctree* theOctree = inputOctree; if (!theOctree) { theOctree = new DgmOctree(theCloud); if (theOctree->build(progressCb) < 1) { delete theOctree; return -3; } } theCloud->enableScalarField(); //set all flags to 0 by default theCloud->forEach(CCLib::ScalarFieldTools::SetScalarValueToZero); unsigned char level = theOctree->findBestLevelForAGivenNeighbourhoodSizeExtraction(static_cast<PointCoordinateType>(minDistanceBetweenPoints)); //parameters void* additionalParameters[1] = { static_cast<void*>(&minDistanceBetweenPoints) }; int result = 0; if (theOctree->executeFunctionForAllCellsAtLevel( level, &flagDuplicatePointsInACellAtLevel, additionalParameters, false, //doesn't work in parallel! progressCb, "Flag duplicate points") == 0) { //something went wrong result = -4; } if (!inputOctree) delete theOctree; return result; }
int GeometricalAnalysisTools::computeLocalDensityApprox(GenericIndexedCloudPersist* theCloud, Density densityType, GenericProgressCallback* progressCb/*=0*/, DgmOctree* inputOctree/*=0*/) { if (!theCloud) return -1; unsigned numberOfPoints = theCloud->size(); if (numberOfPoints < 3) return -2; 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->findBestLevelForAGivenPopulationPerCell(3); //parameters void* additionalParameters[] = { static_cast<void*>(&densityType) }; int result = 0; if (theOctree->executeFunctionForAllCellsAtLevel( level, &computeApproxPointsDensityInACellAtLevel, additionalParameters, true, progressCb, "Approximate Local Density Computation") == 0) { //something went wrong result = -4; } if (!inputOctree) delete theOctree; return result; }
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; }
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; }