/** * @file DialogPCLPoissonMesh.cpp * @brief None * @author 陈增辉 (3045316072@qq.com) * @version 2.5.0 * @date 2024/4/5 * @copyright Copyright (c) Since 2024 中科卫星应用研究院 All rights reserved. */ // You may need to build the project (run Qt uic code generator) to get "ui_DialogPCLPoissonMesh.h" // resolved #include "DialogPCLPoissonMesh.h" #include "ui_DialogPCLPoissonMesh.h" #include "ModuleBase/ThreadTask.h" #include "PythonModule/PyAgent.h" #include "MeshData/meshSingleton.h" #include "MeshData/meshSet.h" #include #include #include #include #include #include #include "MeshData/meshKernal.h" #include "PointCloudOperator/PointCloudCommon.h" #include "PointCloudOperator/PointCloudMesh.h" #include "Settings/BusAPI.h" #include "BaseTool.h" #include "IO/IOConfig.h" #include "ModuleBase/ThreadControl.h" #include "ConfigOptions/ConfigOptions.h" #include "ConfigOptions/MeshConfig.h" #include "MeshData/meshSingleton.h" #include "MeshData/meshKernal.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Common/DebugLogger.h" #include // auto meshData = MeshData::MeshData::getInstance(); namespace MainWidget { DialogPCLPoissonMesh::DialogPCLPoissonMesh(GUI::MainWindow *parent) : QFDialog(parent), _ui(new Ui::DialogPCLPoissonMesh), _mw(parent), _selectdlg(new DialogSelectComponents(parent)) { _ui->setupUi(this); _ui->geoSelectPoint->setToolTip(tr("Clicked Button Selected Components")); setWindowTitle(tr("GP Meshing")); _ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(_ui->geoSelectPoint, &QPushButton::clicked, [=]() { _selectdlg->clearSelectItems(); _selectdlg->exec(); }); connect(_selectdlg, SIGNAL(selectedComponentsSig(QList)), this, SLOT(selectedComponentsSlot(QList))); connect(_ui->listWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(customContextMenuRequestedSlot(const QPoint&))); } DialogPCLPoissonMesh::~DialogPCLPoissonMesh() { delete _ui; _ui = NULL; delete _selectdlg; _selectdlg = NULL; } void DialogPCLPoissonMesh::accept() { if (_components.size() == 0) return; QString componentIds; for (auto component: _components) componentIds.append(QString(",%1").arg(component->getID())); componentIds.remove(0, 1); bool Confidence = _ui->Confidence->isChecked(); size_t Degree = _ui->Degree->value(); size_t Depth = _ui->Depth->value(); size_t IsoDivide = _ui->IsoDivide->value(); bool Manifold = _ui->Manifold->isChecked(); bool OutputPolygons = _ui->OutputPolygons->isChecked(); double SamplesPerNode = _ui->SamplesPerNode->value(); double Scale = _ui->Scale->value(); size_t SolverDivide = _ui->SolverDivide->value(); QString outfilename = "filter"; for (auto component: _components) outfilename.append(QString("_%1").arg(component->getName())); // 确定是否保存结果文件 QMessageBox::StandardButton result = QMessageBox::critical(this, "info", "save as result ?"); QString filepath = JoinPath(Setting::BusAPI::instance()->getWorkingDir(), outfilename + "_tmep.pcd"); QString AbFileName = filepath; if (result == QMessageBox::StandardButton::Ok || result == QMessageBox::StandardButton::Yes) { DebugInfo("outfilename ok ok \n"); QStringList suffixlist = IO::IOConfigure::getMeshExporters(); if (suffixlist.isEmpty()) { QMessageBox::warning(this, tr("Warning"), tr("The MeshPlugin is not installed !")); return; } QStringList meshsuffix = ConfigOption::ConfigOption::getInstance() ->getMeshConfig() ->getExportSuffix(ConfigOption::MeshDataType::vtkMesh) .split(";"); QStringList list; for (QString s: meshsuffix) { for (int i = 0; i < suffixlist.size(); i++) { QString suffix = suffixlist.at(i); if (suffix.contains(s)) list.append(suffix); } } std::sort(list.begin(), list.end()); QString suffixes = list.join(";;"); QString workDir = Setting::BusAPI::instance()->getWorkingDir(); QFileDialog dlg(this, tr("Export mesh"), workDir, suffixes); dlg.setAcceptMode(QFileDialog::AcceptSave); if (dlg.exec() != QFileDialog::FileName) return; QString aSuffix = dlg.selectedNameFilter(); QString aFileName = dlg.selectedFiles().join(","); if (!(aFileName.isEmpty())) { filepath = aFileName; } else { } AbFileName = filepath; } else { // 不保存成点云数据 } DebugInfo("outfilename %s \n", AbFileName.toStdString().c_str()); // 启动线程 auto pclremesh = new WBFZ::PCLPoissonMesh( AbFileName, WBFZ::PointCloudOperation::POINTCLOUD_MESH, _mainWindow, componentIds, Confidence, Degree, Depth, IsoDivide, Manifold, OutputPolygons, SamplesPerNode, Scale, SolverDivide); ModuleBase::ThreadControl *tc = new ModuleBase::ThreadControl(pclremesh); emit tc->threadStart(); // emit MSHwriter->start(); DebugInfo("tc overing %s \n", AbFileName.toStdString().c_str()); QFDialog::accept(); DebugInfo("QFDialog::accept() \n"); } void DialogPCLPoissonMesh::selectedComponentsSlot(QList components) { for (MeshData::MeshSet *set: components) { if (_components.contains(set)) continue; _components.append(set); _ui->listWidget->addItem(set->getName()); } } void DialogPCLPoissonMesh::customContextMenuRequestedSlot(const QPoint &point) { QListWidgetItem *curItem = _ui->listWidget->itemAt(point); if (!curItem) return; QMenu *menu = new QMenu(this); QAction *deleteItem = new QAction(tr("delete this item")); menu->addAction(deleteItem); connect(menu, &QMenu::triggered, [=]() { removeCurrentItem(curItem); }); menu->exec(QCursor::pos()); } void DialogPCLPoissonMesh::removeCurrentItem(QListWidgetItem *curItem) { auto meshData = MeshData::MeshData::getInstance(); auto meshSet = meshData->getMeshSetByName(curItem->text()); if (!meshSet) return; _components.removeOne(meshSet); _ui->listWidget->removeItemWidget(curItem); delete curItem; } } // namespace MainWidget namespace WBFZ { PCLPoissonMesh::PCLPoissonMesh(const QString &fileName, WBFZ::PointCloudOperation operation, GUI::MainWindow *mw, QString componentIds, bool Confidence, size_t Degree, size_t Depth, size_t IsoDivide, bool Manifold, bool OutputPolygons, double SamplesPerNode, double Scale, size_t SolverDivide ) : ModuleBase::ThreadTask(mw), _operation(operation), _fileName(fileName), _componentIds(componentIds) ,_Confidence(Confidence ) ,_Degree(Degree ) ,_Depth (Depth) ,_IsoDivide (IsoDivide) ,_Manifold(Manifold ) ,_OutputPolygons(OutputPolygons ) ,_SamplesPerNode(SamplesPerNode ) ,_Scale (Scale) ,_SolverDivide(SolverDivide ) { } PCLPoissonMesh::~PCLPoissonMesh() {} void PCLPoissonMesh::defaultMeshFinished() { ModuleBase::ThreadTask::threadTaskFinished(); Py::PythonAgent::getInstance()->unLock(); if (_threadRuning) { QString information{}; ModuleBase::Message msg; if (_operation == POINTCLOUD_FILTER || _operation == POINTCLOUD_MESH) { if (_success) { information = QString("Successful resurface Mesh From \"%1\"").arg(_fileName); msg.type = Common::Message::Normal; msg.message = information; qDebug() << "Successful Import Mesh From " << _fileName; QFileInfo info(_fileName); QString name = info.fileName(); QString path = info.filePath(); QString suffix = info.suffix().toLower(); if(info.exists()){ if(suffix.toLower().contains("stl")){ suffix="STL(*.stl)"; emit _mainwindow->importMeshSIGN(_fileName,suffix,-1); }else if(suffix.toLower().contains("vtk")){ suffix="VTK(*.vtk)"; emit _mainwindow->importMeshSIGN(_fileName,suffix,-1); }else if(suffix.toLower().contains("neu")){ suffix="Gambit(*.neu)"; emit _mainwindow->importMeshSIGN(_fileName,suffix,-1); }else{ information = QString("Failed Filter From \"%1\"").arg(_fileName); msg.type = Common::Message::Error; msg.message = information; qDebug() << "Failed Import Mesh From " << _fileName; } } } else { information = QString("Failed resurface From \"%1\"").arg(_fileName); msg.type = Common::Message::Error; msg.message = information; qDebug() << "Failed resurface Mesh From " << _fileName; } } else { } emit showInformation(information); emit _mainwindow->printMessageToMessageWindow(msg); } qDebug()<<"PCLPoissonMesh::defaultMeshFinished ModuleBase::ThreadTask::threadTaskFinished"; // Py::PythonAgent::getInstance()->unLock(); } void PCLPoissonMesh::setThreadRunState(bool flag) { _success = flag; } void PCLPoissonMesh::run() { ModuleBase::ThreadTask::run(); bool result = false; switch (_operation) { case POINTCLOUD_MESH: emit showInformation(tr("POINTCLOUD_MESH From \"%1\"").arg(_fileName)); result = remeshtaskProcess(); setThreadRunState(result); break; default: break; } DebugInfo("run ok _success %d _threadRuning %d \n", _success, _threadRuning); defaultMeshFinished(); } bool PCLPoissonMesh::remeshtaskProcess() { QString componentIds = _componentIds; emit _mainwindow->printMessage(Common::Message::Normal, "PCLPoissonMeshAlg"); // 获取vtdataset QStringList qCompontIds = QString(componentIds).split(','); MeshData::MeshSet* meshSet = NULL; MeshData::MeshKernal* meshKernal = NULL; MeshData::MeshData* meshData = MeshData::MeshData::getInstance(); QString kernalName, transformedName, setType, ids; // 创建 vtkCellDataToPointData 过滤器 vtkSmartPointer cellToPointFilter = vtkSmartPointer::New(); vtkSmartPointer inpolyData=vtkSmartPointer::New(); vtkSmartPointer polydata = vtkSmartPointer::New(); for (QString compontId: qCompontIds) { meshSet = meshData->getMeshSetByID(compontId.toInt()); DebugInfo("point count %d : %d \n", compontId.toInt(), meshSet == nullptr); if (!meshSet) continue; QString outfilename = meshSet->getName(); cellToPointFilter->SetInputData(PointCloudOperator::PointCloudCommon::meshSetToVtkDataset(meshSet)); DebugInfo("point count %d \n", compontId.toInt()); } // 执行过滤操作 cellToPointFilter->Update(); DebugInfo("cellToPointFilter \n"); // 获取过滤后的 vtkPolyData inpolyData = cellToPointFilter->GetOutput(); qDebug()<GetNumberOfCells(); qDebug()<GetNumberOfPoints(); if(PointCloudOperator::PointCloudMeshOperator::PoissonMesh(inpolyData,polydata, _Confidence, _Degree, _Depth, _IsoDivide, _Manifold, _OutputPolygons, _SamplesPerNode, _Scale, _SolverDivide)) { }else{ return false; } DebugInfo("PCLPoissonMeshAlg successfully!! wait for writing file dataset : %d \n",nullptr==polydata); if(nullptr!=polydata){ DebugInfo("PCLPoissonMeshAlg successfully!! wait for writing file dataset : %d %d\n",polydata->GetNumberOfPoints(),polydata->GetNumberOfCells()); } QString filepath = _fileName; QFile outfile_presave(_fileName); if (outfile_presave.exists()) { // 如果存在文件,就删除 outfile_presave.remove(); } // 手动释放所有的变量 //return false; { // 写出到文件中 // 加载文件 QFileInfo info(filepath); QString name = info.fileName(); QString path = info.filePath(); QString suffix = info.suffix().toLower(); QTextCodec* codec = QTextCodec::codecForName("GB18030"); QByteArray ba = codec->fromUnicode(filepath); std::string outFileName = ba.data(); DebugInfo("writing %s suffix %s !! \n", ba.data(), suffix.toStdString().c_str()); if(suffix == "vtk") { vtkSmartPointer writer = vtkSmartPointer::New(); writer->SetInputData(polydata); writer->SetFileTypeToBinary(); writer->SetFileName(ba); writer->Write(); DebugInfo("writing vtk !! \n"); } else if(suffix == "stl") { QTextCodec* codec = QTextCodec::codecForName("GB18030"); QByteArray ba = codec->fromUnicode(_fileName); vtkSmartPointer writer = vtkSmartPointer::New(); writer->SetInputData(polydata); writer->SetFileTypeToBinary(); writer->SetFileName(ba); writer->Write(); DebugInfo("writing stl !! \n"); } else { } } DebugInfo("dataset %d _fileName %s \n", nullptr==polydata, _fileName.toStdString().c_str()); if (nullptr == polydata) { } else { DebugInfo("GP variable start release !! \n"); //dataset->Delete(); //dataset=nullptr; DebugInfo("GP variable finish release!! \n"); } QFile outfile(_fileName); if (outfile.exists()) { DebugInfo("GP main process sucessfully !! \n"); return true; } else { DebugInfo("GP main process fail !! \n"); return false; } DebugInfo("GP main process fail !! \n"); return false; } } // namespace WBFZ