选择点云,实现移位功能。
分享给有需要的人,代码质量勿喷。
1、xjShift.h
#ifndef XJ_SHIFT_HEADER
#define XJ_SHIFT_HEADER
#include "ccStdPluginInterface.h"
#include "ShiftDlg.h"
//Qt
#include <QtGui>
#include <QApplication>
#include <QtConcurrentRun>
#include <QApplication>
#include <QProgressDialog>
#include <QMainWindow>
//qCC_db
#include <ccPointCloud.h>
//CCLib
#include <ccScalarField.h>
//System
#include <algorithm>
#if defined(CC_WINDOWS)
#include "windows.h"
#else
#include <time.h>
#endif
class xjShift : public QObject, public ccStdPluginInterface
{
Q_OBJECT
Q_INTERFACES(ccStdPluginInterface)
Q_PLUGIN_METADATA(IID "cccorp.cloudcompare.plugin.xjShift" FILE "info.json")
public:
//! Default constructor
explicit xjShift(QObject* parent = nullptr);
//inherited from ccStdPluginInterface
virtual void onNewSelection(const ccHObject::Container& selectedEntities);
virtual QList<QAction *> getActions() override;
protected slots:
//! Slot called when associated ation is triggered
void doAction();
protected:
//! Associated action
QAction* m_action;
};
#endif
2、xjShift.cpp
xjShift::xjShift(QObject* parent/*=nullptr*/)
: QObject(parent)
, ccStdPluginInterface(":/CC/plugin/xjShift/info.json")
, m_action(nullptr)
{
}
void xjShift::onNewSelection(const ccHObject::Container& selectedEntities)
{
if (m_action)
m_action->setEnabled(selectedEntities.size() >= 1);
//m_action->setEnabled(selectedEntities.size()==1 && selectedEntities[0]->isA(CC_TYPES::POINT_CLOUD));
}
void xjShift::doAction()
{
assert(m_app);
if (!m_app)
return;
//1 judge
const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
size_t selNum = selectedEntities.size();
if (selNum!=1)
{
m_app->dispToConsole(tr("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(tr("Select a real point cloud!"),ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
}
//2 input cloud
ccPointCloud* pc = static_cast<ccPointCloud*>(ent);
unsigned count = pc->size();
bool hasNorms = pc->hasNormals();
CCVector3 bbMin, bbMax;
pc->getBoundingBox(bbMin,bbMax);
const CCVector3d& globalShift = pc->getGlobalShift();
double globalScale = pc->getGlobalScale();
//3 result point cloud
QString pcname = ent->getName();
if (pcname.contains(" - Cloud"))
pcname.replace(" - Cloud", "_Shift");
else
pcname += "_Shift";
ccPointCloud *resultPC = new ccPointCloud(pcname);
if (!resultPC->reserveThePointsTable(count))
{
m_app->dispToConsole(tr("Not enough memory"), ccMainAppInterface::ERR_CONSOLE_MESSAGE);
delete resultPC;
return;
}
//4 simulation parameters
ShiftDlg xjShiftDlg(m_app->getMainWindow());
if (!xjShiftDlg.exec())
return;
double Xdis = xjShiftDlg.spinX->value();
double Ydis = xjShiftDlg.spinY->value();
double Zdis = xjShiftDlg.spinZ->value();
//5 progress
QProgressDialog *pDlg = new QProgressDialog(tr("running..."), QString(), 0, 100, m_app->getMainWindow());
pDlg->setWindowTitle(tr("point cloud shift"));
pDlg->show();
QApplication::processEvents();
#pragma region update coordinate
pDlg->setLabelText(tr("update coordinates..."));
float x = 0, y = 0, z = 0;
for (unsigned i = 0; i < count; ++i)
{
x = (pc->getPoint(i)->x) + Xdis;
y = (pc->getPoint(i)->y) + Ydis;
z = (pc->getPoint(i)->z) + Zdis;
存点方式1
//const CCVector3 &P1 = CCVector3(x,y,z);
//resultPC->addPoint(P1);
存点方式2
//CCVector3 P(x,y,z);
//resultPC->addPoint(P);
存点方式3
const CCVector3* X = new CCVector3(x, y, z);
resultPC->addPoint(*X);
//progress:coordinate
pDlg->setValue(100.0*i / count);
}
resultPC->invalidateBoundingBox();
#pragma endregion
#pragma region update normal
if (pc->hasNormals())
{
pDlg->setLabelText("update normals...");
if (resultPC->reserveTheNormsTable())
{
for (unsigned i = 0; i < count; i++)
{
const CompressedNormType& nor = pc->getPointNormalIndex(i);
resultPC->addNormIndex(nor);
//progress:normal
pDlg->setValue(100.0*i / count);
}
resultPC->showNormals(true);
}
else
{
m_app->dispToConsole(tr("Not enough memory: normal"), ccMainAppInterface::ERR_CONSOLE_MESSAGE);
delete resultPC;
return;
}
}
#pragma endregion
#pragma region update scalar field
unsigned sfCount = pc->getNumberOfScalarFields();
if (sfCount != 0)
{
for (unsigned k = 0; k < sfCount; ++k)
{
const ccScalarField* sf = static_cast<ccScalarField*>(pc->getScalarField(k));
assert(sf);
if (sf)
{
QString sfName = QString(QLatin1String(sf->getName()));//QString::fromUtf8(sf->getName());
pDlg->setLabelText("update scalar field:" + sfName + "...");
//we create a new scalar field with same name
int sfIdx = resultPC->addScalarField(sf->getName());
if (sfIdx >= 0)
{
const ccScalarField* oldsf = static_cast<ccScalarField*>(pc->getScalarField(sfIdx));
ccScalarField* currentScalarField = static_cast<ccScalarField*>(resultPC->getScalarField(sfIdx));
assert(currentScalarField);
if (currentScalarField->resizeSafe(count))
{
currentScalarField->setGlobalShift(sf->getGlobalShift());
//we copy data to new SF
for (unsigned i = 0; i < count; i++)
{
//const ScalarType val= oldsf->getValue(i);
//currentScalarField->setValue(i,val);
currentScalarField->setValue(i, oldsf->getValue(i));
//progress:scalar field
pDlg->setValue(100.0*i / count);
}
currentScalarField->computeMinAndMax();
currentScalarField->importParametersFrom(sf);//copy display parameters
}
else
{
//if we don't have enough memory, we cancel SF creation
resultPC->deleteScalarField(sfIdx);
QString infor = tr("Not enough memory: SF ") + sfName;
m_app->dispToConsole(infor, ccMainAppInterface::ERR_CONSOLE_MESSAGE);
delete resultPC;
return;
}
}
}
}
unsigned copiedSFCount = pc->getNumberOfScalarFields();
if (copiedSFCount)
{
//we display the same scalar field as the source (if we managed to copy it!)
if (pc->getCurrentDisplayedScalarField())
{
int sfIdx = resultPC->getScalarFieldIndexByName(pc->getCurrentDisplayedScalarField()->getName());
if (sfIdx >= 0)
resultPC->setCurrentDisplayedScalarField(sfIdx);
else
resultPC->setCurrentDisplayedScalarField(static_cast<int>(copiedSFCount) - 1);
}
resultPC->showNormals(false);
resultPC->showSF(true);
}
}
#pragma endregion
#pragma region update colors
if (pc->hasColors())
{
pDlg->setLabelText("update colors...");
if (resultPC->reserveTheRGBTable())
{
for (unsigned i = 0; i < count; i++)
{
const ccColor::Rgb& rgb = pc->getPointColor(i);
resultPC->addRGBColor(rgb);
//progress:colors
pDlg->setValue(100.0*i / count);
}
resultPC->showNormals(false);
resultPC->showSF(false);
resultPC->showColors(true);
}
else
{
m_app->dispToConsole(tr("Not enough memory: colors"), ccMainAppInterface::ERR_CONSOLE_MESSAGE);
delete resultPC;
return;
}
}
#pragma endregion
//6 progress
delete pDlg;
pDlg = nullptr;
//7 result refresh
if (resultPC)
{
ent->setEnabled(false);
m_app->dispToConsole(tr("[Point Cloud Shift] The previously selected entity has been hidden!"), ccMainAppInterface::STD_CONSOLE_MESSAGE);
resultPC->setGlobalShift(pc->getGlobalShift());
resultPC->setGlobalScale(pc->getGlobalScale());
resultPC->setDisplay(ent->getDisplay());
resultPC->prepareDisplayForRefresh();
resultPC->refreshDisplay();
m_app->addToDB(resultPC);
m_app->setSelectedInDB(resultPC, true);
m_app->refreshAll();
m_app->zoomOnSelectedEntities();
}
}
3、界面ShiftDlg.h
#ifndef SHIFT_DLG_H
#define SHIFT_DLG_H
#include <QWidget>
#include <QDialog>
#include "ui_ShiftDlg.h"
class ShiftDlg : public QDialog, public Ui::ShiftDlg
{
Q_OBJECT
public:
explicit ShiftDlg(QWidget * parent = 0);
};
#endif // SHIFT_DLG_H
4、界面ShiftDlg.cpp
#include "ShiftDlg.h"
ShiftDlg::ShiftDlg(QWidget *parent)
: QDialog(parent,Qt::Tool)
,Ui::ShiftDlg()
{
setupUi(this);
//OK-Cancel
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
}