本文由CSDN点云侠原创,原文链接。爬虫网站自重。博客长期更新,本文最新更新时间为:2023年8月10日。
1.Octree
通过菜单栏的'Edit > Octree > Compute'
找到该功能。
设置相关参数:
八叉树空间区段可以通过多种方式设置:
Default
:包含实体的最小立方体cell size at max level
:用户可以在最小的细分级别上定义单元格大小为 N N N,那么八叉树的体素个数则为 2 N 2^N 2N。Custom bounding box
:用户可以使用专用的子对话框定义自定义边界框。
最大八叉树级别(或细分的数量)在32位版本中是
N
N
N=10,在64位版本中是
N
N
N=21。
注意:这个操作通常是不必要的(即八叉树计算是由CloudCompare在必要时自动完成的)。
CloudCompare默认以面片的形式
显示mesh网格模型,因此放大之后也看不到所谓的“网格”
2.可视化八叉树
选中Octree
,可以看到显示的是默认的包含实体的最小包围框
在属性选项中,设置八叉树的显示层级,操作如下:
以线框的形式
显示八叉树,八叉树的层级为:4。
以面片的形式
显示八叉树。
以点的形式显示八叉树,看不出来效果。不做展示。
3.CC源码
bool computeOctree(const ccHObject::Container &selectedEntities, QWidget *parent)
{
ccBBox bbox;
std::unordered_set<ccGenericPointCloud*> clouds;
PointCoordinateType maxBoxSize = -1;
for (ccHObject* ent : selectedEntities)
{
//specific test for locked vertices
bool lockedVertices = false;
ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(ent, &lockedVertices);
if (cloud == nullptr)
{
continue;
}
if (lockedVertices)
{
ccUtils::DisplayLockedVerticesWarning(ent->getName(), selectedEntities.size() == 1);
continue;
}
clouds.insert(cloud);
//we look for the biggest box so as to define the "minimum cell size"
const ccBBox thisBBox = cloud->getOwnBB();
if (thisBBox.isValid())
{
CCVector3 dd = thisBBox.maxCorner() - thisBBox.minCorner();
PointCoordinateType maxd = std::max(dd.x, std::max(dd.y, dd.z));
if (maxBoxSize < 0.0 || maxd > maxBoxSize)
maxBoxSize = maxd;
}
bbox += thisBBox;
}
if (clouds.empty() || maxBoxSize < 0.0)
{
ccLog::Warning("[doActionComputeOctree] No eligible entities in selection!");
return false;
}
//min(cellSize) = max(dim)/2^N with N = max subidivision level
const double minCellSize = static_cast<double>(maxBoxSize) / (1 << ccOctree::MAX_OCTREE_LEVEL);
ccComputeOctreeDlg coDlg(bbox, minCellSize, parent);
if (!coDlg.exec())
return false;
ccProgressDialog pDlg(true, parent);
pDlg.setAutoClose(false);
//if we must use a custom bounding box, we update 'bbox'
if (coDlg.getMode() == ccComputeOctreeDlg::CUSTOM_BBOX)
bbox = coDlg.getCustomBBox();
for (const auto cloud : clouds)
{
//we temporarily detach entity, as it may undergo
//"severe" modifications (octree deletion, etc.) --> see ccPointCloud::computeOctree
ccMainAppInterface* instance = dynamic_cast<ccMainAppInterface*>(parent);
ccMainAppInterface::ccHObjectContext objContext;
if (instance)
objContext = instance->removeObjectTemporarilyFromDBTree(cloud);
//computation
QElapsedTimer eTimer;
eTimer.start();
ccOctree::Shared octree(nullptr);
switch (coDlg.getMode())
{
case ccComputeOctreeDlg::DEFAULT:
octree = cloud->computeOctree(&pDlg);
break;
case ccComputeOctreeDlg::MIN_CELL_SIZE:
case ccComputeOctreeDlg::CUSTOM_BBOX:
{
//for a cell-size based custom box, we must update it for each cloud!
if (coDlg.getMode() == ccComputeOctreeDlg::MIN_CELL_SIZE)
{
double cellSize = coDlg.getMinCellSize();
PointCoordinateType halfBoxWidth = static_cast<PointCoordinateType>(cellSize * (1 << ccOctree::MAX_OCTREE_LEVEL) / 2.0);
CCVector3 C = cloud->getOwnBB().getCenter();
bbox = ccBBox( C - CCVector3(halfBoxWidth, halfBoxWidth, halfBoxWidth),
C + CCVector3(halfBoxWidth, halfBoxWidth, halfBoxWidth));
}
cloud->deleteOctree();
octree = ccOctree::Shared(new ccOctree(cloud));
if (octree->build(bbox.minCorner(), bbox.maxCorner(), nullptr, nullptr, &pDlg) > 0)
{
ccOctreeProxy* proxy = new ccOctreeProxy(octree);
proxy->setDisplay(cloud->getDisplay());
cloud->addChild(proxy);
}
else
{
octree.clear();
}
}
break;
default:
Q_ASSERT(false);
return false;
}
qint64 elapsedTime_ms = eTimer.elapsed();
//put object back in tree
if (instance)
instance->putObjectBackIntoDBTree(cloud, objContext);
if (octree)
{
ccConsole::Print("[doActionComputeOctree] Timing: %2.3f s", static_cast<double>(elapsedTime_ms) / 1000.0);
cloud->setEnabled(true); //for mesh vertices!
ccOctreeProxy* proxy = cloud->getOctreeProxy();
assert(proxy);
proxy->setVisible(true);
proxy->prepareDisplayForRefresh();
}
else
{
ccConsole::Warning(QString("Octree computation on cloud '%1' failed!").arg(cloud->getName()));
}
}
return true;
}
4.相关代码
[1] PCL 可视化八叉树
[2] Open3D 从点云中构建八叉树
[3] Open3D (C++) 八叉树的使用