예제 #1
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)
	{
		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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
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;
}