0.引言
CloudCompaer是一款优秀的开源软件,在点云处理时可以根据实际要求开发合适的插件,本文需求是将点云文件打开、处理并显示,网上资源可以找到点云简单处理和显示的代码,但对于文件打开的源代码几乎没有,本文通过查阅大量资料和研究源代码实现了点云文件打开,从而达到本文将点云文件打开、处理并显示的目标。本文是CloudCompare插件开发的拓展篇,关于插件开发基础可以参考:CloudCompare如何进行二次开发之插件开发?
1.将点云文件打开、处理并显示的效果
(1)CloudCompare自带打开功能打开点云初始文件
(2)插件打开点云初始文件、处理并显示
2.代码实现
(1)引用的命名空间
#include <QtGui>
#include "MySecondPlugin.h"
#include "qinputdialog.h"
#include "ccProgressDialog.h"
#include "ccPointCloud.h"
(2)设置插件按钮不用选择点云即可使用
void MySecondPlugin::onNewSelection(const ccHObject::Container &selectedEntities)
{
if (m_action == nullptr)
{
return;
}
// If you need to check for a specific type of object, you can use the methods
// in ccHObjectCaster.h or loop and check the objects' classIDs like this:
//
// for ( ccHObject *object : selectedEntities )
// {
// if ( object->getClassID() == CC_TYPES::VIEWPORT_2D_OBJECT )
// {
// // ... do something with the viewports
// }
// }
// For example - only enable our action if something is selected.
//m_action->setEnabled(!selectedEntities.empty());
m_action->setEnabled(true);//设置插件按钮不用选择点云即可使用
}
(3)点云文件打开、处理并显示代码文章来源:https://www.toymoban.com/news/detail-676479.html
void MySecondPlugin::doAction()
{
if (m_app == nullptr)
{
// m_app should have already been initialized by CC when plugin is loaded
Q_ASSERT(false);
return;
}
/*** HERE STARTS THE ACTION ***/
// Put your code here
// --> you may want to start by asking for parameters (with a custom dialog, etc.)
/*
* 点云格式为:x,y,z
*
*/
//【打开文件】将数据预处理到点云文件
//打开文件选择对话框
char szFileName[MAX_PATH] = { 0 };
OPENFILENAME openFileName = { 0 };
openFileName.lStructSize = sizeof(OPENFILENAME);
openFileName.nMaxFile = MAX_PATH;
openFileName.lpstrFilter = "csv文件(*.csv)\0*.csv\0所有文件(*.*)\0*.*\0\0";
openFileName.lpstrFile = szFileName;
openFileName.nFilterIndex = 1;
openFileName.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (!::GetOpenFileName(&openFileName))return;
//打开点云文件
const QString fileName = openFileName.lpstrFile;
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly))return;
QTextStream stream(&file);
QStringList qsl;
std::vector<QVector3D>* vq = new std::vector<QVector3D>();
int countOne = 0;
stream.seek(0);
QStringList strs = (stream.readAll()).split('\n');
for (size_t i = 0; i < strs.size(); i++)
{
qsl = strs.takeAt(i).split(',');
if (qsl.size() != 3) continue;
QVector3D* qv3d = new QVector3D(qsl.at(0).toFloat(), qsl.at(1).toFloat(), qsl.at(2).toFloat());
vq->push_back(*qv3d);
}
file.close();
//将点云文件保存到CloudCompare(cc)标准数据集
ccPointCloud* myPc = new ccPointCloud(QString("myPc"));
myPc->reserve(vq->size());
for (size_t i = 0; i < vq->size(); i++)
{
const CCVector3* vcc = new CCVector3(vq->at(i).x(), vq->at(i).y(), vq->at(i).z());
myPc->addPoint(*vcc);
}
//【点云处理】指定参数切割部分点云
得到点云
//const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();//此处为选择已有点云的操作
//size_t selNum = selectedEntities.size();//此处为选择已有点云的操作
size_t selNum = 1;
//传入参数
bool isOK;
QString s_percentage = QInputDialog::getText(NULL, QString::fromLocal8Bit("参数"), QString::fromLocal8Bit("输入留下点的百分比0-1"), QLineEdit::Normal, "", &isOK);
if (!isOK) {
ccLog::Print("error");
return;
}
//留下点的个数
double percentage = s_percentage.toDouble();
if (percentage < 0 || percentage>1) {
ccLog::Print("error percentage allow 0-1");
return;
}
//加个进度条
ccProgressDialog pDlg(true, 0);
CCLib::GenericProgressCallback* progressCb = &pDlg;
if (progressCb) {
if (progressCb->textCanBeEdited()) {
progressCb->setMethodTitle("compute");
progressCb->setInfo(qPrintable(QString("waiting...")));
}
progressCb->update(0);
progressCb->start();
}
std::vector<ccHObject*> allCloud;
//随机数
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
for (size_t i = 0; i < selNum; i++)
{
//ccHObject* ent = selectedEntities[i];//此处为选择已有点云的操作
ccHObject* ent = myPc;
if (!ent->isA(CC_TYPES::POINT_CLOUD)) {
continue;
}
//ccPointCloud* cloud = ccHObjectCaster::ToPointCloud(selectedEntities[i]);//此处为选择已有点云的操作
ccPointCloud* cloud = myPc;
//计算点云中心
CCVector3 weight;
CCVector3 bmin, bmax;
cloud->getBoundingBox(bmin, bmax);
weight = (bmin + bmax) / 2;
//遍历索引
std::vector<size_t> m_index(cloud->size());
//以递增的方式填充
std::iota(m_index.begin(), m_index.end(), 0);
//随机一个方向
double theta = M_PI*(double)qrand() / (double)(RAND_MAX + 1);
double phi = 2 * M_PI*(double)qrand() / (double)(RAND_MAX + 1);
CCVector3 dir(sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta));
std::vector<double> m_value;
for (size_t i = 0; i < m_index.size(); i++)
{
CCVector3 P;
cloud->getPoint(m_index[i], P);
double temp = (P - weight).dot(dir);
m_value.push_back(temp);
}
//对m_index进行排序
std::sort(m_index.begin(), m_index.end(), [&m_value](auto i1, auto i2) {return m_value[i1] < m_value[i2];});
m_index.erase(m_index.begin(), m_index.begin() + (1 - percentage)*cloud->size());
//新点云
//ccPointCloud* pcc = new ccPointCloud(QString("cq") + cloud->getName());
ccPointCloud* pcc = new ccPointCloud(cloud->getName() + QString("-Clone"));
pcc->reserve(m_index.size());
//pcc->reserveTheNormsTable();//分配法向量内存,本环境报错
for (size_t i = 0; i < m_index.size(); i++)
{
pcc->addPoint(*cloud->getPoint(m_index[i]));
//pcc->addNorm(cloud->getPointNormal(m_index[i]));//分配法向量内存,本环境报错
}
allCloud.push_back(pcc);
progressCb->update((float)100.0*i / selNum);
}
if (progressCb) {
progressCb->stop();
}
//【显示点云】
//新建一个文件夹来放点云
ccHObject* CloudGroup = new ccHObject(QString("CloudGroup"));
for (size_t i = 0; i < allCloud.size(); i++)
{
CloudGroup->addChild(allCloud[i]);
}
m_app->addToDB(CloudGroup);
//刷新
m_app->refreshAll();
m_app->updateUI();
// This is how you can output messages
Display a standard message in the console
//QString show = QString::number(selNum) + "," + s_percentage + "," + QString::number(percentage);
//m_app->dispToConsole(show, ccMainAppInterface::STD_CONSOLE_MESSAGE);
Display a warning message in the console
//m_app->dispToConsole("[MySecondPlugin] Warning: example plugin shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);
Display an error message in the console AND pop-up an error box
//m_app->dispToConsole("Example plugin shouldn't be used - it doesn't do anything!", ccMainAppInterface::ERR_CONSOLE_MESSAGE);
/*** HERE ENDS THE ACTION ***/
}
参考资料:
[1] cacrle. CloudCompare如何进行二次开发之插件开发?; 2023-03-11 [ accessed 2023-03-26 ].
[2] 点云PCL. CloudCompare插件开发教程; 2020-06-20 [ accessed 2023-03-26 ].文章来源地址https://www.toymoban.com/news/detail-676479.html
到了这里,关于CloudCompare插件开发之如何将点云文件打开、处理并显示?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!