void CloudViewer::doOpen(const QStringList& filePathList) {
// Open point cloud file one by one
for (int i = 0; i != filePathList.size(); i++) {
timeStart(); // time start
mycloud.cloud.reset(new PointCloudT); // Reset cloud
QFileInfo fileInfo(filePathList[i]);
std::string filePath = fromQString(fileInfo.filePath());
std::string fileName = fromQString(fileInfo.fileName());
// begin loading
ui.statusBar->showMessage(
fileInfo.fileName() + ": " + QString::number(i) + "/" + QString::number(filePathList.size())
+ " point cloud loading..."
);
mycloud = fileIO.load(fileInfo);
if (!mycloud.isValid) {
// TODO: deal with the error, print error info in console?
debug("invalid cloud.");
continue;
}
mycloud.viewer = viewer;
mycloud_vec.push_back(mycloud);
timeCostSecond = timeOff(); // time off
consoleLog(
"Open",
toQString(mycloud.fileName),
toQString(mycloud.filePath),
"Time cost: " + timeCostSecond + " s, Points: " + QString::number(mycloud.cloud->points.size())
);
// update tree widget
QTreeWidgetItem *cloudName = new QTreeWidgetItem(QStringList()
<< toQString(mycloud.fileName));
cloudName->setIcon(0, QIcon(":/Resources/images/icon.png"));
ui.dataTree->addTopLevelItem(cloudName);
total_points += mycloud.cloud->points.size();
}
ui.statusBar->showMessage("");
showPointcloudAdd();
setPropertyTable();
}
// Open point cloud
void CloudViewer::open() {
QStringList filePathList = QFileDialog::getOpenFileNames(
this,
tr("Open point cloud file"),
toQString(mycloud.fileDir),
toQString(fileIO.getInputFormatsStr())
);
if (filePathList.isEmpty()) return;
// Clear cache
// TODO: abstract a function
mycloud_vec.clear();
total_points = 0;
ui.dataTree->clear();
viewer->removeAllPointClouds();
doOpen(filePathList);
}
// Add Point Cloud
void CloudViewer::add() {
QStringList filePathList = QFileDialog::getOpenFileNames(
this,
tr("Add point cloud file"),
toQString(mycloud.fileDir),
toQString(fileIO.getInputFormatsStr())
);
if (filePathList.isEmpty()) return;
doOpen(filePathList);
}
// Clear all point clouds
void CloudViewer::clear() {
mycloud_vec.clear(); // 从点云容器中移除所有点云
viewer->removeAllPointClouds(); // 从viewer中移除所有点云
viewer->removeAllShapes(); // 这个remove更彻底
ui.dataTree->clear(); // 将dataTree清空
ui.propertyTable->clear(); // 清空属性窗口propertyTable
QStringList header;
header << "Property" << "Value";
ui.propertyTable->setHorizontalHeaderLabels(header);
// 输出窗口
consoleLog("Clear", "All point clouds", "", "");
setWindowTitle("CloudViewer"); // 更新窗口标题
showPointcloud(); // 更新显示
}
// Save point cloud
void CloudViewer::save() {
if (!mycloud.isValid) {
QMessageBox::critical(this, tr("Saving file error"),
tr("There is no point cloud to save"));
return;
}
// get binary flag from sender()
QAction *action = qobject_cast<QAction *>(sender());
QVariant v = action->data();
bool isSaveBinary = (bool)v.value<bool>();
QString selectedFilter = toQString(fileIO.outputFiltersMap.at(mycloud.fileSuffix));
QString saveFilePath = QFileDialog::getSaveFileName(
this, // parent
toQString("Save point cloud" + string(isSaveBinary ? " (binary)": "")), // caption
toQString(mycloud.filePath), // dir
toQString(fileIO.getOutputFormatsStr()), // filter
&selectedFilter // selected filter
);
if (saveFilePath.isEmpty()) return;
QFileInfo fileInfo(saveFilePath);
QString saveFileName = fileInfo.fileName();
string saveFilePathStd = fromQString(saveFilePath);
string saveFileNameStd = fromQString(saveFileName);
if (mycloud_vec.size() > 1) {
savemulti(fileInfo, isSaveBinary);
return;
}
bool saveStatus = fileIO.save(mycloud, fileInfo, isSaveBinary);
if (!saveStatus) {
QMessageBox::critical(this, tr("Saving file error"),
tr("We can not save the file"));
return;
}
consoleLog("Save", saveFileName, saveFilePath, "Single save");
setWindowTitle(saveFilePath + " - CloudViewer");
QMessageBox::information(this, tr("save point cloud file"),
toQString("Save " + saveFileNameStd + " successfully!"));
}
// Save multi point cloud
void CloudViewer::savemulti(const QFileInfo& fileInfo, bool isSaveBinary) {
string subname = fromQString(fileInfo.fileName());
QString saveFilePath = fileInfo.filePath();
PointCloudT::Ptr multi_cloud;
multi_cloud.reset(new PointCloudT);
multi_cloud->height = 1;
int sum = 0;
for (auto c : mycloud_vec) {
sum += c.cloud->points.size();
}
multi_cloud->width = sum;
multi_cloud->resize(multi_cloud->height * multi_cloud->width);
int k = 0;
for (int i = 0; i != mycloud_vec.size(); ++i) {
// 注意cloudvec[i]->points.size()和cloudvec[i]->size()的区别
for (int j = 0; j != mycloud_vec[i].cloud->points.size(); ++j) {
multi_cloud->points[k].x = mycloud_vec[i].cloud->points[j].x;
multi_cloud->points[k].y = mycloud_vec[i].cloud->points[j].y;
multi_cloud->points[k].z = mycloud_vec[i].cloud->points[j].z;
multi_cloud->points[k].r = mycloud_vec[i].cloud->points[j].r;
multi_cloud->points[k].g = mycloud_vec[i].cloud->points[j].g;
multi_cloud->points[k].b = mycloud_vec[i].cloud->points[j].b;
k++;
}
}
MyCloud multiMyCloud;
multiMyCloud.cloud = multi_cloud;
multiMyCloud.isValid = true;
// save multi_cloud
bool saveStatus = fileIO.save(multiMyCloud, fileInfo, isSaveBinary);
if (!saveStatus) {
QMessageBox::critical(this, tr("Saving file error"),
tr("We can not save the file"));
return;
}
if (isSaveBinary) {
consoleLog("Save as binary", QString::fromLocal8Bit(subname.c_str()), saveFilePath, "Multi save (binary)");
} else {
consoleLog("Save", QString::fromLocal8Bit(subname.c_str()), saveFilePath, "Multi save");
}
// 将保存后的 multi_cloud 设置为当前 mycloud,以便保存之后直接进行操作
mycloud.cloud = multi_cloud;
mycloud.filePath = fromQString(saveFilePath);
mycloud.fileName = subname;
setWindowTitle(saveFilePath + " - CloudViewer");
QMessageBox::information(this, tr("save point cloud file"), toQString("Save " + subname + " successfully!"));
}