[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点与最近邻点之间距离的平方。
[CC]点云密度计算的更多相关文章
- 阿里云流计算专场-GitHub上相关文档
阿里云流计算专场-GitHub路径:https://github.com/Alibaba-Technology/hangzhouYunQi2017ppt
- 荣获“5G MEC优秀商用案例奖”,阿里云边缘计算发力新零售
4月24日,在中国联通合作伙伴大会的 “5G MEC(Mobile Edge Computing,移动边缘计算)边缘云赋能行业数字化转型”分论坛上,阿里云“基于5G边缘计算的新零售应用案例”荣获201 ...
- 阿里云函数计算 .NET Core 初体验
体验了一波阿里云函数计算, 已支持 .NET Core 2.1, 那么按照惯例, 来写个 "Hello World" 吧. 作者注: 开发环境 Windows 10 & V ...
- 阿里云函数计算上部署.NET Core 3.1
使用阿里云ECS或者其他常见的VPS服务部署应用的时候,需要手动配置环境,并且监测ECS的行为,做补丁之类的,搞得有点复杂.好在很多云厂商(阿里云.Azure等)提供了Serverless服务,借助于 ...
- 阿里云函数计算 VSCode 使用,及部署 Docusaurus
代码: https://github.com/ikuokuo/start-serverless 使用简介 产品页开通服务.使用流程,如下: 新手示例,如下: 创建函数 阿里云提供了如下几种方式创建函数 ...
- 对端边缘云网络计算模式:透明计算、移动边缘计算、雾计算和Cloudlet
对端边缘云网络计算模式:透明计算.移动边缘计算.雾计算和Cloudlet 概要 将数据发送到云端进行分析是过去几十年的一个突出趋势,推动了云计算成为主流计算范式.然而,物联网时代设备数量和数据流量的急 ...
- 独家对话阿里云函数计算负责人不瞋:你所不知道的 Serverless
作者 | 杨丽 出品 | 雷锋网产业组 "Serverless 其实离我们并没有那么遥远". 如果你是一名互联网研发人员,那么极有可能了解并应用过 Serverless 这套技术体 ...
- 阿里云函数计算发布新功能,支持容器镜像,加速应用 Serverless 进程
我们先通过一段视频来看看函数计算和容器相结合后,在视频转码场景下的优秀表现.点击观看视频 >> FaaS 的门槛 Serverless 形态的云服务帮助开发者承担了大量复杂的扩缩容.运维. ...
- 基于MATLAB实现的云模型计算隶属度
”云”或者’云滴‘是云模型的基本单元,所谓云是指在其论域上的一个分布,可以用联合概率的形式(x, u)来表示 云模型用三个数据来表示其特征 期望:云滴在论域空间分布的期望,一般用符号Εx表示. 熵:不 ...
随机推荐
- PullToRefresh
PullToRefreshListView的使用,实现下拉刷新,上拉加载更多.首先是布局文件: <com.handmark.pulltorefresh.library.PullToRefresh ...
- Java基础知识梳理《一》
一.Java数据类型(简单称之为“四类八种”) java 基本的数据类型长度都是固定的,好处是在实现跨平台时就统一了. 1.整型 byte short int long (分别是1,2,4,8个字节) ...
- Android 自动化测试—robotium(九) Junit_report测试报告重定向输出到终端SDCard
借鉴网上相关资料主要用于无root权限的终端.主要分为以下三步: 一.重写InstrumentationTestRunner类: package com.exmaple.test; import ja ...
- Fouandation(NSString ,NSArray,NSDictionary,NSSet) 中常见的理解错误区
Fouandation 中常见的理解错误区 1.NSString //快速创建(实例和类方法) 存放的地址是 常量区 NSString * string1 = [NSString alloc]init ...
- 实现携程X分钟前有人预定功能
实现携程X分钟前有人预定功能 原理:利用cookie与计时器两部分: 首先,进入页面,x会被随机数赋值,赋值后x会一分钟加1,直到加到60,再从1开始累加. 页面是否相同是根据页面的url后的id值判 ...
- C# 线程调用主线程中的控件
由于项目的需要,最近几天一直在做串口和数据库.由于C#使用的时间不长,所以在编写代码和调试的过程中总是遇到意想不到的问题,比如在使用串口接收数据的时候,在接收数据事件中想把接收的数据放入一个textb ...
- Daikon Forge GUI Library(dfgui)之Event Binding
点击按钮并弹出对话框,就用下面的大问题按钮吧 1,选中按钮,Component/Daikon Forge/Data Binding/Event Binding 2,UI上创建DfPanel,并将其Be ...
- IOS ReactiveCocoa
一 前提: 在iOS开发过程中,当某些事件响应时,需处理的某些业务逻辑 Eg. 按钮点击:action ScrollView滚动:delegate 属性值改变:KVO ReactiveCocoa为事件 ...
- 【5集iCore3_ADP演示视频】5-5 iCore3应用开发平台示波器和信号源校准
iCore3双核心应用开发平台基于iCore3双核心板,包含ARM.FPGA.7寸液晶屏.双通道数字示波器.任意波发生器.电压表等模块,是一款专为电子爱好者设计的综合性电子学习系统. [视频简介]本视 ...
- windows中查看开机时间
windows中查看开机时间 在windows下可以使用systeminfo命令来查看. 下面是网站摘录的关于windows启动了多长时间的内容 1. windows系统可以查看从开机到现在共 ...