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 }