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. CQRS FAQ (翻译)

    我从接触ddd到学习cqrs有6年多了, 其中也遇到了不少疑问, 也向很多的前辈牛人请教得到了很多宝贵的意见和建议. 偶尔的机会看到国外有个站点专门罗列了ddd, cqrs和事件溯源的常见问题. 其中 ...

  2. android中设置控件获得焦点 (转)

    android中,要使控件获得焦点,需要先setFocus,再requestFocus. 以Button为例:                 btn.setFocusable(true);      ...

  3. Android版:验证手机号码的正则表达式 (转)

    /**  * 验证手机格式  */  public static boolean isMobileNO(String mobiles) {      /*     移动:134.135.136.137 ...

  4. 使用urllib2打开网页的三种方法

    #coding:utf-8 import urllib2 import cookielib url="http://www.baidu.com" print '方法 1' resp ...

  5. Java知识点归总一之堆栈

    Java栈与堆 (一天一个知识点2014-07-28) ----对这两个概念的不明好久,终于找到一篇好文,拿来共享 1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C ...

  6. Pig基础学习【持续更新中】

    *本文参考了Pig官方文档以及已有的一些博客,并加上了自己的一些知识性的理解.目前正在持续更新中.* Pig作为一种处理大规模数据的高级查询语言,底层是转换成MapReduce实现的,可以作为MapR ...

  7. bzoj3212 pku3468 A Simple Problem with Integers

    一个有初值的数列.区间加.区间查 用线段树直接水过 然而并没有1A,主要是做题太快没看规模结果没注意线段树要用longlong建 卧槽怎么可以这么坑爹,害得我看见wa心慌了,还以为连线段树都要跪 一开 ...

  8. jquery ui dialog autofocus 去掉默认第一个元素获取焦点

    经常在dialog窗口中第一个元素为日期控件时,打开窗口则会自动显示日期下拉框. 解决办法:在dialog的open事件中,设置父对象获得焦点. p1_dialog_seniorSearch.dial ...

  9. 最简单的html轮播图制作适合新手

    html代码 --------------------------------------------------------------------------------------------- ...

  10. 一些用过的我常忘记的小知识(web前端)

    背景图片固定:background-attachment:fixed 将图片的尺寸从中心点开始改变:backgroun-position:center   background-size: ** 旋转 ...