scene_tree.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2012, Willow Garage, Inc.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of Willow Garage, Inc. nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
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   // put the cloud mesh items in a new render window
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 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:32:48