[CC]点云密度计算

时间:2023-03-09 04:43:50
[CC]点云密度计算

[CC]点云密度计算

包括两种计算方法:精确计算和近似计算(思考:local density=单位面积的点数 vs  local density =1/单个点所占的面积)

每种方法可以实现三种模式的点云密度计算,CC里面的点云计算依赖于 给定的近邻半径所对应的最佳八叉树层级 (通过findBestLevelForAGivenNeighbourhoodSizeExtraction()方法实现)

在GeometricalAnalysisTools类文件中实现。

//volume of a unit sphere
static double s_UnitSphereVolume = 4.0 * M_PI / 3.0;

1.精确计算

 int GeometricalAnalysisTools::computeLocalDensity(    GenericIndexedCloudPersist* theCloud,
Density densityType,
PointCoordinateType kernelRadius,
GenericProgressCallback* progressCb/*=0*/,
DgmOctree* inputOctree/*=0*/)
{
if (!theCloud)
return -; unsigned numberOfPoints = theCloud->size();
if (numberOfPoints < )
return -; //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 -;
} DgmOctree* theOctree = inputOctree;
if (!theOctree)
{
theOctree = new DgmOctree(theCloud);
if (theOctree->build(progressCb) < )
{
delete theOctree;
return -;
}
} 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 = ; if (theOctree->executeFunctionForAllCellsAtLevel( level,
&computePointsDensityInACellAtLevel,
additionalParameters,
true,
progressCb,
"Local Density Computation") == )
{
//something went wrong
result = -;
} if (!inputOctree)
delete theOctree; return result;
}

GeometricalAnalysisTools::computeLocalDensity

 //"PER-CELL" METHOD: LOCAL DENSITY
//ADDITIONNAL PARAMETERS (2):
// [0] -> (PointCoordinateType*) kernelRadius : spherical neighborhood radius
// [1] -> (ScalarType*) sphereVolume : spherical neighborhood volume
bool GeometricalAnalysisTools::computePointsDensityInACellAtLevel( const DgmOctree::octreeCell& cell,
void** additionalParameters,
NormalizedProgress* nProgress/*=0*/)
{
//parameter(s)
PointCoordinateType radius = *static_cast<PointCoordinateType*>(additionalParameters[]);
double dimensionalCoef = *static_cast<double*>(additionalParameters[]); assert(dimensionalCoef > ); //structure for nearest neighbors search
DgmOctree::NearestNeighboursSphericalSearchStruct nNSS;
nNSS.level = cell.level;
nNSS.prepare(radius,cell.parentOctree->getCellSize(nNSS.level));
cell.parentOctree->getCellPos(cell.truncatedCode,cell.level,nNSS.cellPos,true);
cell.parentOctree->computeCellCenter(nNSS.cellPos,cell.level,nNSS.cellCenter); unsigned n = cell.points->size(); //number of points in the current cell //for each point in the cell
for (unsigned i=; i<n; ++i)
{
cell.points->getPoint(i,nNSS.queryPoint); //look for neighbors inside a sphere
//warning: there may be more points at the end of nNSS.pointsInNeighbourhood than the actual nearest neighbors (neighborCount)!
unsigned neighborCount = cell.parentOctree->findNeighborsInASphereStartingFromCell(nNSS,radius,false);
//数目/体积
ScalarType density = static_cast<ScalarType>(neighborCount/dimensionalCoef);
cell.points->setPointScalarValue(i,density); if (nProgress && !nProgress->oneStep())
{
return false;
}
} return true;
}

computePointsDensityInACellAtLevel

2. 近似计算

 int GeometricalAnalysisTools::computeLocalDensityApprox(GenericIndexedCloudPersist* theCloud,
Density densityType,
GenericProgressCallback* progressCb/*=0*/,
DgmOctree* inputOctree/*=0*/)
{
if (!theCloud)
return -; unsigned numberOfPoints = theCloud->size();
if (numberOfPoints < )
return -; DgmOctree* theOctree = inputOctree;
if (!theOctree)
{
theOctree = new DgmOctree(theCloud);
if (theOctree->build(progressCb) < )
{
delete theOctree;
return -;
}
} theCloud->enableScalarField(); //determine best octree level to perform the computation
unsigned char level = theOctree->findBestLevelForAGivenPopulationPerCell(); //parameters
void* additionalParameters[] = { static_cast<void*>(&densityType) }; int result = ; if (theOctree->executeFunctionForAllCellsAtLevel( level,
&computeApproxPointsDensityInACellAtLevel,
additionalParameters,
true,
progressCb,
"Approximate Local Density Computation") == )
{
//something went wrong
result = -;
} if (!inputOctree)
delete theOctree; return result;
}
 //"PER-CELL" METHOD: APPROXIMATE LOCAL DENSITY
//ADDITIONAL PARAMETERS (0): NONE
bool GeometricalAnalysisTools::computeApproxPointsDensityInACellAtLevel(const DgmOctree::octreeCell& cell,
void** additionalParameters,
NormalizedProgress* nProgress/*=0*/)
{
//extract additional parameter(s)
Density densityType = *static_cast<Density*>(additionalParameters[]); DgmOctree::NearestNeighboursSearchStruct nNSS;
nNSS.level = cell.level;
nNSS.alreadyVisitedNeighbourhoodSize = ;
nNSS.minNumberOfNeighbors = ;
cell.parentOctree->getCellPos(cell.truncatedCode,cell.level,nNSS.cellPos,true);
cell.parentOctree->computeCellCenter(nNSS.cellPos,cell.level,nNSS.cellCenter); unsigned n = cell.points->size();
for (unsigned i=; i<n; ++i)
{
cell.points->getPoint(i,nNSS.queryPoint); //the first point is always the point itself!
if (cell.parentOctree->findNearestNeighborsStartingFromCell(nNSS) > )
{
double R2 = nNSS.pointsInNeighbourhood[].squareDistd; ScalarType density = NAN_VALUE;
if (R2 > ZERO_TOLERANCE)
{
switch (densityType)
{
case DENSITY_KNN:
{
//we return in fact the (inverse) distance to the nearest neighbor
density = static_cast<ScalarType>(1.0 / sqrt(R2));
}
break;
case DENSITY_2D:
{
//circle area (2D approximation)
double circleArea = M_PI * R2;
density = static_cast<ScalarType>(1.0 / circleArea);
}
break;
case DENSITY_3D:
{
//sphere area
double sphereArea = s_UnitSphereVolume * R2 * sqrt(R2);
density = static_cast<ScalarType>(1.0 / sphereArea);
}
break;
default:
assert(false);
break;
}
}
cell.points->setPointScalarValue(i,density);
}
else
{
//shouldn't happen! Apart if the cloud has only one point...
cell.points->setPointScalarValue(i,NAN_VALUE);
} if (nProgress && !nProgress->oneStep())
{
return false;
}
} return true;
}

computeApproxPointsDensityInACellAtLevel

double R2 = nNSS.pointsInNeighbourhood[1].squareDistd;  //索引为1的点,表示最近邻点。pi点与最近邻点之间距离的平方。