00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <pcl/apps/modeler/scene_tree.h>
00038
00039 #include <set>
00040 #include <pcl/apps/modeler/main_window.h>
00041 #include <pcl/apps/modeler/render_window.h>
00042 #include <pcl/apps/modeler/render_window_item.h>
00043 #include <pcl/apps/modeler/cloud_mesh_item.h>
00044 #include <pcl/apps/modeler/cloud_mesh_item_updater.h>
00045 #include <pcl/apps/modeler/thread_controller.h>
00046 #include <pcl/apps/modeler/voxel_grid_downsample_worker.h>
00047 #include <pcl/apps/modeler/statistical_outlier_removal_worker.h>
00048 #include <pcl/apps/modeler/normal_estimation_worker.h>
00049 #include <pcl/apps/modeler/icp_registration_worker.h>
00050 #include <pcl/apps/modeler/poisson_worker.h>
00051 #include <pcl/io/pcd_io.h>
00052
00053
00055 pcl::modeler::SceneTree::SceneTree(QWidget * parent)
00056 : QTreeWidget(parent)
00057 {
00058 setDragEnabled(true);
00059 setAcceptDrops(true);
00060 setDropIndicatorShown(true);
00061 setDragDropMode(QAbstractItemView::DragDrop);
00062
00063 setSelectionMode(QAbstractItemView::ExtendedSelection);
00064
00065 connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
00066 this, SLOT(slotUpdateOnSelectionChange(QItemSelection, const QItemSelection)));
00067
00068 connect(this, SIGNAL(itemInsertedOrRemoved()),this, SLOT(slotUpdateOnInsertOrRemove()));
00069
00070 connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),this, SLOT(slotOnItemDoubleClicked(QTreeWidgetItem*)));
00071 }
00072
00074 pcl::modeler::SceneTree::~SceneTree()
00075 {
00076 }
00077
00079 QSize
00080 pcl::modeler::SceneTree::sizeHint() const
00081 {
00082 return QSize(256, 512);
00083 }
00084
00086 QList<pcl::modeler::RenderWindowItem*>
00087 pcl::modeler::SceneTree::selectedRenderWindowItems() const
00088 {
00089 QList<RenderWindowItem*> selected_render_window_items;
00090 if (topLevelItemCount() == 1)
00091 selected_render_window_items.push_back(dynamic_cast<RenderWindowItem*>(topLevelItem(0)));
00092 else
00093 selected_render_window_items = selectedTypeItems<RenderWindowItem>();
00094
00095 return (selected_render_window_items);
00096 }
00097
00099 void
00100 pcl::modeler::SceneTree::contextMenuEvent(QContextMenuEvent *event)
00101 {
00102 AbstractItem* item = dynamic_cast<AbstractItem*>(currentItem());
00103 item->showContextMenu(&(event->globalPos()));
00104
00105 return;
00106 }
00107
00109 void
00110 pcl::modeler::SceneTree::slotOnItemDoubleClicked(QTreeWidgetItem * item)
00111 {
00112 AbstractItem* abstract_item = dynamic_cast<AbstractItem*>(item);
00113 abstract_item->showPropertyEditor();
00114 }
00115
00117 bool
00118 pcl::modeler::SceneTree::openPointCloud(const QString& filename)
00119 {
00120 QList<RenderWindowItem*> selected_render_window_items = selectedRenderWindowItems();
00121
00122 for (QList<RenderWindowItem*>::iterator selected_render_window_items_it = selected_render_window_items.begin();
00123 selected_render_window_items_it != selected_render_window_items.end();
00124 ++ selected_render_window_items_it)
00125 {
00126 if(!(*selected_render_window_items_it)->openPointCloud(filename))
00127 return (false);
00128 expandItem(*selected_render_window_items_it);
00129 }
00130
00131 emit fileOpened(filename);
00132
00133 return (true);
00134 }
00135
00137 bool
00138 pcl::modeler::SceneTree::savePointCloud(const QString& filename)
00139 {
00140 QList<CloudMeshItem*> selected_cloud_mesh_items = selectedTypeItems<CloudMeshItem>();
00141
00142 return (CloudMeshItem::savePointCloud(selected_cloud_mesh_items, filename));
00143 }
00144
00146 void
00147 pcl::modeler::SceneTree::slotOpenPointCloud()
00148 {
00149 MainWindow* main_window = &MainWindow::getInstance();
00150 QList<RenderWindowItem*> selected_render_window_items = selectedRenderWindowItems();
00151
00152 if (selected_render_window_items.empty())
00153 {
00154 QMessageBox::warning(main_window,
00155 tr("Failed to Open Point Cloud"),
00156 tr("Please specify in which render window(s) you want to open the point cloud(s)"));
00157 return;
00158 }
00159
00160 QStringList filenames = QFileDialog::getOpenFileNames(main_window,
00161 tr("Open Point Cloud"),
00162 main_window->getRecentFolder(),
00163 tr("Point Cloud(*.pcd)\n")
00164 );
00165
00166 if (filenames.isEmpty())
00167 return;
00168
00169 for (QList<RenderWindowItem*>::iterator selected_render_window_items_it = selected_render_window_items.begin();
00170 selected_render_window_items_it != selected_render_window_items.end();
00171 ++ selected_render_window_items_it)
00172 {
00173 RenderWindowItem* render_window_item = *selected_render_window_items_it;
00174
00175 QList<CloudMeshItem*> cloud_mesh_items;
00176 for (int i = 0, i_end = render_window_item->childCount(); i < i_end; ++ i)
00177 cloud_mesh_items.push_back(dynamic_cast<CloudMeshItem*>(render_window_item->child(i)));
00178
00179 closePointCloud(cloud_mesh_items);
00180 }
00181
00182 for (QStringList::const_iterator filenames_it = filenames.begin();
00183 filenames_it != filenames.end();
00184 ++ filenames_it)
00185 {
00186 if (!openPointCloud(*filenames_it))
00187 QMessageBox::warning(main_window,
00188 tr("Failed to Open Point Cloud"),
00189 tr("Can not open point cloud file %1, please check if it's in valid .pcd format!").arg(*filenames_it));
00190 }
00191
00192 return;
00193 }
00194
00196 void
00197 pcl::modeler::SceneTree::slotImportPointCloud()
00198 {
00199 MainWindow* main_window = &MainWindow::getInstance();
00200
00201 if (selectedRenderWindowItems().empty())
00202 {
00203 QMessageBox::warning(main_window,
00204 tr("Failed to Import Point Cloud"),
00205 tr("Please specify in which render window(s) you want to import the point cloud(s)"));
00206 return;
00207 }
00208
00209 QStringList filenames = QFileDialog::getOpenFileNames(main_window,
00210 tr("Import Point Cloud"),
00211 main_window->getRecentFolder(),
00212 tr("Point Cloud(*.pcd)\n")
00213 );
00214 if (filenames.isEmpty())
00215 return;
00216
00217 for (QStringList::const_iterator filenames_it = filenames.begin();
00218 filenames_it != filenames.end();
00219 ++ filenames_it)
00220 {
00221 if (!openPointCloud(*filenames_it))
00222 QMessageBox::warning(main_window,
00223 tr("Failed to Import Point Cloud"),
00224 tr("Can not import point cloud file %1, please check if it's in valid .pcd format!").arg(*filenames_it));
00225 }
00226
00227 return;
00228 }
00229
00231 void
00232 pcl::modeler::SceneTree::slotSavePointCloud()
00233 {
00234 MainWindow* main_window = &MainWindow::getInstance();
00235
00236 if (selectedTypeItems<CloudMeshItem>().empty())
00237 {
00238 QMessageBox::warning(main_window,
00239 tr("Failed to Save Point Cloud"),
00240 tr("Please specify the point cloud(s) you want to save"));
00241 return;
00242 }
00243
00244 QString filename = QFileDialog::getSaveFileName(main_window,
00245 tr("Save Point Cloud"),
00246 main_window->getRecentFolder(),
00247 tr("Save Cloud(*.pcd)\n"));
00248
00249 if (filename.isEmpty())
00250 return;
00251
00252 savePointCloud(filename);
00253
00254 return;
00255 }
00256
00258 void
00259 pcl::modeler::SceneTree::closePointCloud(const QList<CloudMeshItem*>& items)
00260 {
00261 QList<RenderWindowItem*> render_window_items;
00262
00263 for (QList<CloudMeshItem*>::const_iterator items_it = items.begin();
00264 items_it != items.end();
00265 ++ items_it)
00266 {
00267 CloudMeshItem* item = *items_it;
00268
00269 RenderWindowItem* render_window_item = dynamic_cast<RenderWindowItem*>(item->parent());
00270 if (render_window_item != NULL)
00271 render_window_items.push_back(render_window_item);
00272
00273 item->parent()->removeChild(item);
00274 delete item;
00275 }
00276
00277 for (QList<RenderWindowItem*>::const_iterator render_window_items_it = render_window_items.begin();
00278 render_window_items_it != render_window_items.end();
00279 ++ render_window_items_it)
00280 {
00281 (*render_window_items_it)->getRenderWindow()->render();
00282 }
00283
00284 return;
00285 }
00286
00288 void
00289 pcl::modeler::SceneTree::slotClosePointCloud()
00290 {
00291 MainWindow* main_window = &MainWindow::getInstance();
00292 QList<CloudMeshItem*> selected_cloud_mesh_items = selectedTypeItems<CloudMeshItem>();
00293
00294 if (selected_cloud_mesh_items.empty())
00295 {
00296 QMessageBox::warning(main_window,
00297 tr("Failed to Close Point Cloud"),
00298 tr("Please specify the point cloud(s) you want to close"));
00299 return;
00300 }
00301
00302 closePointCloud(selected_cloud_mesh_items);
00303
00304 return;
00305 }
00306
00308 void
00309 pcl::modeler::SceneTree::slotICPRegistration()
00310 {
00311 QList<CloudMeshItem*> selected_cloud_mesh_items = selectedTypeItems<CloudMeshItem>();
00312 CloudMesh::PointCloudPtr result(new CloudMesh::PointCloud());
00313
00314 AbstractWorker* worker = new ICPRegistrationWorker(result, selected_cloud_mesh_items,&MainWindow::getInstance());
00315 ThreadController* thread_controller = new ThreadController();
00316
00317 QList<RenderWindowItem*> selected_render_window_items = selectedRenderWindowItems();
00318 for (QList<RenderWindowItem*>::iterator selected_render_window_items_it = selected_render_window_items.begin();
00319 selected_render_window_items_it != selected_render_window_items.end();
00320 ++ selected_render_window_items_it)
00321 {
00322 CloudMeshItem* cloud_mesh_item = (*selected_render_window_items_it)->addPointCloud(result);
00323 expandItem(*selected_render_window_items_it);
00324 connect(worker, SIGNAL(finished()), new CloudMeshItemUpdater(cloud_mesh_item), SLOT(updateCloudMeshItem()));
00325 }
00326
00327 thread_controller->runWorker(worker);
00328
00329 return;
00330 }
00331
00333 void
00334 pcl::modeler::SceneTree::slotVoxelGridDownsampleFilter()
00335 {
00336 QList<CloudMeshItem*> selected_cloud_mesh_items = selectedTypeItems<CloudMeshItem>();
00337 AbstractWorker* worker = new VoxelGridDownampleWorker(selected_cloud_mesh_items,&MainWindow::getInstance());
00338 ThreadController* thread_controller = new ThreadController();
00339 connect(worker, SIGNAL(dataUpdated(CloudMeshItem*)), thread_controller, SLOT(slotOnCloudMeshItemUpdate(CloudMeshItem*)));
00340 thread_controller->runWorker(worker);
00341
00342 return;
00343 }
00344
00346 void
00347 pcl::modeler::SceneTree::slotStatisticalOutlierRemovalFilter()
00348 {
00349 QList<CloudMeshItem*> selected_cloud_mesh_items = selectedTypeItems<CloudMeshItem>();
00350 AbstractWorker* worker = new StatisticalOutlierRemovalWorker(selected_cloud_mesh_items,&MainWindow::getInstance());
00351 ThreadController* thread_controller = new ThreadController();
00352 connect(worker, SIGNAL(dataUpdated(CloudMeshItem*)), thread_controller, SLOT(slotOnCloudMeshItemUpdate(CloudMeshItem*)));
00353 thread_controller->runWorker(worker);
00354
00355 return;
00356 }
00357
00359 void
00360 pcl::modeler::SceneTree::slotEstimateNormal()
00361 {
00362 QList<CloudMeshItem*> selected_cloud_mesh_items = selectedTypeItems<CloudMeshItem>();
00363 AbstractWorker* worker = new NormalEstimationWorker(selected_cloud_mesh_items,&MainWindow::getInstance());
00364 ThreadController* thread_controller = new ThreadController();
00365 connect(worker, SIGNAL(dataUpdated(CloudMeshItem*)), thread_controller, SLOT(slotOnCloudMeshItemUpdate(CloudMeshItem*)));
00366 thread_controller->runWorker(worker);
00367
00368 return;
00369 }
00370
00372 void
00373 pcl::modeler::SceneTree::slotPoissonReconstruction()
00374 {
00375 QList<CloudMeshItem*> selected_cloud_mesh_items = selectedTypeItems<CloudMeshItem>();
00376 AbstractWorker* worker = new PoissonReconstructionWorker(selected_cloud_mesh_items,&MainWindow::getInstance());
00377 ThreadController* thread_controller = new ThreadController();
00378 connect(worker, SIGNAL(dataUpdated(CloudMeshItem*)), thread_controller, SLOT(slotOnCloudMeshItemUpdate(CloudMeshItem*)));
00379 thread_controller->runWorker(worker);
00380
00381 return;
00382 }
00383
00384
00386 void
00387 pcl::modeler::SceneTree::selectRenderWindowItem(RenderWindowItem* render_window_item)
00388 {
00389 selectionModel()->clearSelection();
00390 selectionModel()->select(indexFromItem(render_window_item), QItemSelectionModel::SelectCurrent);
00391 }
00392
00394 void
00395 pcl::modeler::SceneTree::slotUpdateOnSelectionChange(const QItemSelection & selected, const QItemSelection & deselected)
00396 {
00397 QModelIndexList selected_indices = selected.indexes();
00398 for (QModelIndexList::const_iterator selected_indices_it = selected_indices.begin();
00399 selected_indices_it != selected_indices.end();
00400 ++ selected_indices_it)
00401 {
00402 QTreeWidgetItem* item = itemFromIndex(*selected_indices_it);
00403 RenderWindowItem* render_window_item = dynamic_cast<RenderWindowItem*>(item);
00404 if (render_window_item != NULL)
00405 {
00406 render_window_item->getRenderWindow()->setActive(true);
00407 }
00408 }
00409
00410 QModelIndexList deselected_indices = deselected.indexes();
00411 for (QModelIndexList::const_iterator deselected_indices_it = deselected_indices.begin();
00412 deselected_indices_it != deselected_indices.end();
00413 ++ deselected_indices_it)
00414 {
00415 QTreeWidgetItem* item = itemFromIndex(*deselected_indices_it);
00416 RenderWindowItem* render_window_item = dynamic_cast<RenderWindowItem*>(item);
00417 if (render_window_item != NULL)
00418 {
00419 render_window_item->getRenderWindow()->setActive(false);
00420 }
00421 }
00422
00423 return;
00424 }
00425
00427 void
00428 pcl::modeler::SceneTree::slotUpdateOnInsertOrRemove()
00429 {
00430 for (int i = 0, i_end = topLevelItemCount(); i < i_end; ++ i)
00431 {
00432 RenderWindowItem* render_window_item = dynamic_cast<RenderWindowItem*>(topLevelItem(i));
00433 if (render_window_item == NULL)
00434 continue;
00435
00436 QString title = (i == 0)?("Central Render Window"):(QString("Render Window #%1").arg(i));
00437 render_window_item->setText(0, title);
00438
00439 render_window_item->getRenderWindow()->setTitle(title);
00440 }
00441 }
00442
00444 void
00445 pcl::modeler::SceneTree::addTopLevelItem(RenderWindowItem* render_window_item)
00446 {
00447 QTreeWidget::addTopLevelItem(render_window_item);
00448
00449 selectionModel()->clearSelection();
00450 selectionModel()->select(indexFromItem(render_window_item), QItemSelectionModel::SelectCurrent);
00451
00452 emit itemInsertedOrRemoved();
00453 }
00454
00456 void
00457 pcl::modeler::SceneTree::slotCloseRenderWindow()
00458 {
00459 QList<RenderWindowItem*> selected_render_window_items = selectedTypeItems<RenderWindowItem>();
00460
00461 for (QList<RenderWindowItem*>::iterator selected_render_window_items_it = selected_render_window_items.begin();
00462 selected_render_window_items_it != selected_render_window_items.end();
00463 ++ selected_render_window_items_it)
00464 {
00465 removeItemWidget((*selected_render_window_items_it), 0);
00466 delete (*selected_render_window_items_it);
00467 }
00468
00469 emit itemInsertedOrRemoved();
00470
00471 return;
00472 }
00473
00475 void
00476 pcl::modeler::SceneTree::dropEvent(QDropEvent * event)
00477 {
00478 QList<CloudMeshItem*> selected_cloud_meshes = selectedTypeItems<CloudMeshItem>();
00479
00480 std::set<RenderWindowItem*> previous_parents;
00481 for (QList<CloudMeshItem*>::iterator selected_cloud_meshes_it = selected_cloud_meshes.begin();
00482 selected_cloud_meshes_it != selected_cloud_meshes.end();
00483 selected_cloud_meshes_it ++)
00484 {
00485 CloudMeshItem* cloud_mesh_item = *selected_cloud_meshes_it;
00486 RenderWindowItem* render_window_item = dynamic_cast<RenderWindowItem*>(cloud_mesh_item->parent());
00487 if (render_window_item != NULL)
00488 previous_parents.insert(render_window_item);
00489 }
00490
00491 QTreeWidget::dropEvent(event);
00492
00493 std::vector<CloudMeshItem*> cloud_mesh_items;
00494 for (QList<CloudMeshItem*>::iterator selected_cloud_meshes_it = selected_cloud_meshes.begin();
00495 selected_cloud_meshes_it != selected_cloud_meshes.end();
00496 selected_cloud_meshes_it ++)
00497 {
00498 CloudMeshItem* cloud_mesh_item = *selected_cloud_meshes_it;
00499 if (dynamic_cast<RenderWindowItem*>(cloud_mesh_item->parent()) == NULL)
00500 cloud_mesh_items.push_back(cloud_mesh_item);
00501 else
00502 cloud_mesh_item->updateRenderWindow();
00503 }
00504
00505
00506 if (!cloud_mesh_items.empty())
00507 {
00508 for (size_t i = 0, i_end = cloud_mesh_items.size(); i < i_end; ++ i)
00509 takeTopLevelItem(indexFromItem(cloud_mesh_items[i]).row());
00510 RenderWindowItem* render_window_item = MainWindow::getInstance().createRenderWindow();
00511 for (size_t i = 0, i_end = cloud_mesh_items.size(); i < i_end; ++ i)
00512 render_window_item->addChild(cloud_mesh_items[i]);
00513 render_window_item->setExpanded(true);
00514 }
00515
00516 for (std::set<RenderWindowItem*>::iterator previous_parents_it = previous_parents.begin();
00517 previous_parents_it != previous_parents.end();
00518 previous_parents_it ++)
00519 {
00520 (*previous_parents_it)->getRenderWindow()->updateAxes();
00521 (*previous_parents_it)->getRenderWindow()->render();
00522 }
00523
00524 return;
00525 }
00526
00528 bool
00529 pcl::modeler::SceneTree::dropMimeData(QTreeWidgetItem * parent, int, const QMimeData *, Qt::DropAction)
00530 {
00531 QList<CloudMeshItem*> selected_cloud_meshes = selectedTypeItems<CloudMeshItem>();
00532
00533 RenderWindowItem* render_window_item =
00534 (parent == NULL)?(MainWindow::getInstance().createRenderWindow()):(dynamic_cast<RenderWindowItem*>(parent));
00535
00536 for (QList<CloudMeshItem*>::iterator selected_cloud_meshes_it = selected_cloud_meshes.begin();
00537 selected_cloud_meshes_it != selected_cloud_meshes.end();
00538 selected_cloud_meshes_it ++)
00539 {
00540 CloudMeshItem* cloud_mesh_item_copy = new CloudMeshItem(render_window_item, *(*selected_cloud_meshes_it));
00541 render_window_item->addChild(cloud_mesh_item_copy);
00542 setCurrentItem(cloud_mesh_item_copy);
00543 }
00544 render_window_item->setExpanded(true);
00545
00546 return true;
00547 }