diff --git a/visualization/include/pcl/visualization/interactor_style.h b/visualization/include/pcl/visualization/interactor_style.h index c89bb2d6107..7cc7210fb90 100644 --- a/visualization/include/pcl/visualization/interactor_style.h +++ b/visualization/include/pcl/visualization/interactor_style.h @@ -114,11 +114,11 @@ namespace pcl /** \brief Empty constructor. */ PCLVisualizerInteractorStyle () : - init_ (), rens_ (), actors_ (), win_height_ (), win_width_ (), win_pos_x_ (), win_pos_y_ (), - max_win_height_ (), max_win_width_ (), grid_enabled_ (), grid_actor_ (), lut_enabled_ (), + init_ (), rens_ (), cloud_actors_ (), shape_actors_ (), win_height_ (), win_width_ (), win_pos_x_ (), win_pos_y_ (), + max_win_height_ (), max_win_width_ (), use_vbos_ (false), grid_enabled_ (), grid_actor_ (), lut_enabled_ (), lut_actor_ (), snapshot_writer_ (), wif_ (), mouse_signal_ (), keyboard_signal_ (), point_picking_signal_ (), area_picking_signal_ (), stereo_anaglyph_mask_default_ (), - mouse_callback_ (), modifier_ (), camera_file_ (), camera_ (), camera_saved_ (), win_ () + mouse_callback_ (), modifier_ (), camera_file_ (), camera_ (), camera_saved_ (), win_ (), lut_actor_id_ ("") {} /** \brief Empty destructor */ @@ -131,15 +131,25 @@ namespace pcl virtual void Initialize (); - /** \brief Pass a pointer to the actor map + /** \brief Pass a pointer to the cloud actor map + * \param[in] actors the actor map that will be used with this style + */ + inline void + setCloudActorMap (const CloudActorMapPtr &actors) { cloud_actors_ = actors; } + + /** \brief Pass a pointer to the shape actor map * \param[in] actors the actor map that will be used with this style */ inline void - setCloudActorMap (const CloudActorMapPtr &actors) { actors_ = actors; } + setShapeActorMap (const ShapeActorMapPtr &actors) { shape_actors_ = actors; } /** \brief Get the cloud actor map pointer. */ inline CloudActorMapPtr - getCloudActorMap () { return (actors_); } + getCloudActorMap () { return (cloud_actors_); } + + /** \brief Get the cloud actor map pointer. */ + inline ShapeActorMapPtr + getShapeActorMap () { return (shape_actors_); } /** \brief Pass a set of renderers to the interactor style. * \param[in] rens the vtkRendererCollection to use @@ -257,8 +267,11 @@ namespace pcl /** \brief Collection of vtkRenderers stored internally. */ vtkSmartPointer rens_; - /** \brief Actor map stored internally. */ - CloudActorMapPtr actors_; + /** \brief Cloud actor map stored internally. */ + CloudActorMapPtr cloud_actors_; + + /** \brief Shape map stored internally. */ + ShapeActorMapPtr shape_actors_; /** \brief The current window width/height. */ int win_height_, win_width_; @@ -374,6 +387,18 @@ namespace pcl friend class PointPickingCallback; friend class PCLVisualizer; + + private: + /** \brief ID used to fetch/display the look up table on the visualizer + * It should be set by PCLVisualizer \ref setLookUpTableID + * @note If empty, a random actor added to the interactor will be used */ + std::string lut_actor_id_; + + /** \brief Add/remove the look up table displayed when 'u' is pressed, can also be used to update the current LUT displayed + * \ref lut_actor_id_ is used (if not empty) to chose which cloud/shape actor LUT will be updated (depending on what is available) + * If \ref lut_actor_id_ is empty the first actor with LUT support found will be used. */ + void + updateLookUpTableDisplay (bool add_lut = false); }; /** \brief PCL histogram visualizer interactory style class. diff --git a/visualization/include/pcl/visualization/pcl_visualizer.h b/visualization/include/pcl/visualization/pcl_visualizer.h index baf70a209b7..ec3e63b2643 100644 --- a/visualization/include/pcl/visualization/pcl_visualizer.h +++ b/visualization/include/pcl/visualization/pcl_visualizer.h @@ -1403,18 +1403,6 @@ namespace pcl const std::string &id = "PolyData", int viewport = 0); - /** \brief Add a vtkPolyDataMapper as a mesh - * \param[in] polydatamapper vtkPolyDataMapper - * \param[in] id the model id/name (default: "PolyDataMapper") - * \param[in] viewport (optional) the id of the new viewport (default: 0) - * \return True if successful, false otherwise - * \note This allows to display a colored mesh, also see \ref PCL_VISUALIZER_LUT. - */ - bool - addModelFromPolyData (vtkSmartPointer polydatamapper, - const std::string & id = "PolyDataMapper", - int viewport = 0); - /** \brief Add a PLYmodel as a mesh * \param[in] filename of the ply file * \param[in] id the model id/name (default: "PLYModel") @@ -1872,6 +1860,12 @@ namespace pcl void setUseVbos (bool use_vbos); + /** \brief Set the ID of a cloud or shape to be used for LUT display + * \param[in] id The id of the cloud/shape look up table to be displayed + * The look up table is displayed by pressing 'u' in the PCLVisualizer */ + void + setLookUpTableID (const std::string id); + /** \brief Create the internal Interactor object. */ void createInteractor (); diff --git a/visualization/src/interactor_style.cpp b/visualization/src/interactor_style.cpp index eb135be3167..fff2855e747 100644 --- a/visualization/src/interactor_style.cpp +++ b/visualization/src/interactor_style.cpp @@ -634,7 +634,7 @@ pcl::visualization::PCLVisualizerInteractorStyle::OnKeyDown () // Geometry ? if (keymod) { - for (it = actors_->begin (); it != actors_->end (); ++it) + for (it = cloud_actors_->begin (); it != cloud_actors_->end (); ++it) { CloudActor *act = &(*it).second; if (index >= static_cast (act->geometry_handlers.size ())) @@ -683,7 +683,7 @@ pcl::visualization::PCLVisualizerInteractorStyle::OnKeyDown () } else { - for (it = actors_->begin (); it != actors_->end (); ++it) + for (it = cloud_actors_->begin (); it != cloud_actors_->end (); ++it) { CloudActor *act = &(*it).second; // Check for out of bounds @@ -786,7 +786,7 @@ pcl::visualization::PCLVisualizerInteractorStyle::OnKeyDown () case 'l': case 'L': { // Iterate over the entire actors list and extract the geomotry/color handlers list - for (CloudActorMap::iterator it = actors_->begin (); it != actors_->end (); ++it) + for (CloudActorMap::iterator it = cloud_actors_->begin (); it != cloud_actors_->end (); ++it) { std::list geometry_handlers_list, color_handlers_list; CloudActor *act = &(*it).second; @@ -1057,27 +1057,7 @@ pcl::visualization::PCLVisualizerInteractorStyle::OnKeyDown () // Display a LUT actor on screen case 'u': case 'U': { - CloudActorMap::iterator it; - for (it = actors_->begin (); it != actors_->end (); ++it) - { - CloudActor *act = &(*it).second; - - vtkScalarsToColors* lut = act->actor->GetMapper ()->GetLookupTable (); - lut_actor_->SetLookupTable (lut); - lut_actor_->Modified (); - } - if (!lut_enabled_) - { - CurrentRenderer->AddActor (lut_actor_); - lut_actor_->SetVisibility (true); - lut_enabled_ = true; - } - else - { - CurrentRenderer->RemoveActor (lut_actor_); - lut_enabled_ = false; - } - CurrentRenderer->Render (); + updateLookUpTableDisplay (true); break; } @@ -1098,13 +1078,13 @@ pcl::visualization::PCLVisualizerInteractorStyle::OnKeyDown () vtkSmartPointer cam = CurrentRenderer->GetActiveCamera (); - static CloudActorMap::iterator it = actors_->begin (); + static CloudActorMap::iterator it = cloud_actors_->begin (); // it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault. bool found_transformation = false; - for (unsigned idx = 0; idx < actors_->size (); ++idx, ++it) + for (unsigned idx = 0; idx < cloud_actors_->size (); ++idx, ++it) { - if (it == actors_->end ()) - it = actors_->begin (); + if (it == cloud_actors_->end ()) + it = cloud_actors_->begin (); const CloudActor& actor = it->second; if (actor.viewpoint_transformation_.GetPointer ()) @@ -1138,10 +1118,10 @@ pcl::visualization::PCLVisualizerInteractorStyle::OnKeyDown () } // go to the next actor for the next key-press event. - if (it != actors_->end ()) + if (it != cloud_actors_->end ()) ++it; else - it = actors_->begin (); + it = cloud_actors_->begin (); CurrentRenderer->SetActiveCamera (cam); CurrentRenderer->ResetCameraClippingRange (); @@ -1187,6 +1167,135 @@ pcl::visualization::PCLVisualizerInteractorStyle::OnKeyDown () Interactor->Render (); } +////////////////////////////////////////////////////////////////////////////////////////////// +// Update the look up table displayed when 'u' is pressed +void +pcl::visualization::PCLVisualizerInteractorStyle::updateLookUpTableDisplay (bool add_lut) +{ + CloudActorMap::iterator am_it; + ShapeActorMap::iterator sm_it; + bool actor_found = false; + + if (lut_actor_id_ != "") // Search if provided actor id is in CloudActorMap or ShapeActorMap + { + am_it = cloud_actors_->find (lut_actor_id_); + if (am_it == cloud_actors_->end ()) + { + sm_it = shape_actors_->find (lut_actor_id_); + if (sm_it == shape_actors_->end ()) + { + PCL_WARN ("[updateLookUpTableDisplay] Could not find any actor with id <%s>!\n", lut_actor_id_.c_str ()); + if (lut_enabled_) + { // Remove LUT and exit + CurrentRenderer->RemoveActor (lut_actor_); + lut_enabled_ = false; + } + return; + } + + // ShapeActor found + vtkSmartPointer *act = & (*sm_it).second; + vtkSmartPointer actor = vtkActor::SafeDownCast (*act); + if (!actor || !actor->GetMapper ()->GetInput ()->GetPointData ()->GetScalars ()) + { + PCL_WARN ("[updateLookUpTableDisplay] id <%s> does not hold any color information!\n", lut_actor_id_.c_str ()); + if (lut_enabled_) + { // Remove LUT and exit + CurrentRenderer->RemoveActor (lut_actor_); + lut_enabled_ = false; + } + return; + } + + lut_actor_->SetLookupTable (actor->GetMapper ()->GetLookupTable ()); + lut_actor_->Modified (); + actor_found = true; + } + else + { + // CloudActor + CloudActor *act = & (*am_it).second; + if (!act->actor->GetMapper ()->GetLookupTable () && !act->actor->GetMapper ()->GetInput ()->GetPointData ()->GetScalars ()) + { + PCL_WARN ("[updateLookUpTableDisplay] id <%s> does not hold any color information!\n", lut_actor_id_.c_str ()); + if (lut_enabled_) + { // Remove LUT and exit + CurrentRenderer->RemoveActor (lut_actor_); + lut_enabled_ = false; + } + return; + } + + vtkScalarsToColors* lut = act->actor->GetMapper ()->GetLookupTable (); + lut_actor_->SetLookupTable (lut); + lut_actor_->Modified (); + actor_found = true; + } + } + else // lut_actor_id_ == "", the user did not specify which cloud/shape LUT should be displayed + // Circling through all clouds/shapes and displaying first LUT found + { + for (am_it = cloud_actors_->begin (); am_it != cloud_actors_->end (); ++am_it) + { + CloudActor *act = & (*am_it).second; + if (!act->actor->GetMapper ()->GetLookupTable ()) + continue; + + if (!act->actor->GetMapper ()->GetInput ()->GetPointData ()->GetScalars ()) + continue; + + vtkScalarsToColors* lut = act->actor->GetMapper ()->GetLookupTable (); + lut_actor_->SetLookupTable (lut); + lut_actor_->Modified (); + actor_found = true; + break; + } + + if (!actor_found) + { + for (sm_it = shape_actors_->begin (); sm_it != shape_actors_->end (); ++sm_it) + { + vtkSmartPointer *act = & (*sm_it).second; + vtkSmartPointer actor = vtkActor::SafeDownCast (*act); + if (!actor) + continue; + + if (!actor->GetMapper ()->GetInput ()->GetPointData ()->GetScalars ()) // Check if actor has scalars + continue; + lut_actor_->SetLookupTable (actor->GetMapper ()->GetLookupTable ()); + lut_actor_->Modified (); + actor_found = true; + break; + } + } + } + + if (!actor_found) + PCL_WARN ("[updateLookUpTableDisplay] No actor was found with LUT information!\n"); + + if (!actor_found || (lut_enabled_ && add_lut)) // Remove actor + { + CurrentRenderer->RemoveActor (lut_actor_); + lut_enabled_ = false; + } + else if (!lut_enabled_ && add_lut) // Add actor + { + CurrentRenderer->AddActor (lut_actor_); + lut_actor_->SetVisibility (true); + lut_enabled_ = true; + } + else if (lut_enabled_) // Update actor (if displayed) + { + CurrentRenderer->RemoveActor (lut_actor_); + CurrentRenderer->AddActor (lut_actor_); + } + else + return; + + CurrentRenderer->Render (); + return; +} + ////////////////////////////////////////////////////////////////////////////////////////////// void pcl::visualization::PCLVisualizerInteractorStyle::OnKeyUp () diff --git a/visualization/src/pcl_visualizer.cpp b/visualization/src/pcl_visualizer.cpp index e9edcffcafb..d2bf2a1ab64 100644 --- a/visualization/src/pcl_visualizer.cpp +++ b/visualization/src/pcl_visualizer.cpp @@ -165,6 +165,7 @@ pcl::visualization::PCLVisualizer::PCLVisualizer (const std::string &name, const style_->Initialize (); style_->setRendererCollection (rens_); style_->setCloudActorMap (cloud_actor_map_); + style_->setShapeActorMap (shape_actor_map_); style_->UseTimersOn (); style_->setUseVbos(use_vbos_); @@ -227,6 +228,7 @@ pcl::visualization::PCLVisualizer::PCLVisualizer (int &argc, char **argv, const style_->Initialize (); style_->setRendererCollection (rens_); style_->setCloudActorMap (cloud_actor_map_); + style_->setShapeActorMap (shape_actor_map_); style_->UseTimersOn (); // Get screen size @@ -802,6 +804,7 @@ pcl::visualization::PCLVisualizer::removeShape (const std::string &id, int viewp if (removeActorFromRenderer (am_it->second, viewport)) { shape_actor_map_->erase (am_it); + style_->updateLookUpTableDisplay (false); return (true); } } @@ -810,6 +813,7 @@ pcl::visualization::PCLVisualizer::removeShape (const std::string &id, int viewp if (removeActorFromRenderer (ca_it->second.actor, viewport)) { cloud_actor_map_->erase (ca_it); + style_->updateLookUpTableDisplay (false); return (true); } } @@ -1634,6 +1638,7 @@ pcl::visualization::PCLVisualizer::setShapeRenderingProperties ( } table->Build (); actor->GetMapper ()->SetLookupTable (table); + style_->updateLookUpTableDisplay (false); break; } default: @@ -2261,38 +2266,6 @@ pcl::visualization::PCLVisualizer::addModelFromPolyData ( return (true); } -//////////////////////////////////////////////////////////////////////////////////////////// -bool -pcl::visualization::PCLVisualizer::addModelFromPolyData (vtkSmartPointer polydatamapper, - const std::string & id, - int viewport) -{ - if (contains (id)) - { - pcl::console::print_warn (stderr, - "[addModelFromPolyData] A shape with id <%s> already exists! Please choose a different id and retry.\n", - id.c_str ()); - return (false); - } - - // Check if mesh has color information - if (polydatamapper->GetInput ()->GetPointData ()->GetScalars ()) - { - double range[2]; - polydatamapper->GetInput ()->GetPointData ()->GetScalars ()->GetRange (range); - polydatamapper->ScalarVisibilityOn (); - polydatamapper->SetScalarRange (range[0], range[1]); - } - - vtkSmartPointer actor = vtkSmartPointer::New (); - actor->SetMapper (polydatamapper); - addActorToRenderer (actor, viewport); - - // Save the pointer/ID pair to the global actor map - (*shape_actor_map_)[id] = actor; - return (true); -} - //////////////////////////////////////////////////////////////////////////////////////////// bool pcl::visualization::PCLVisualizer::addModelFromPLYFile (const std::string &filename, @@ -4312,6 +4285,14 @@ pcl::visualization::PCLVisualizer::setUseVbos (bool use_vbos) style_->setUseVbos (use_vbos_); } +////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::visualization::PCLVisualizer::setLookUpTableID (const std::string id) +{ + style_->lut_actor_id_ = id; + style_->updateLookUpTableDisplay (false); +} + ////////////////////////////////////////////////////////////////////////////////////////////// void pcl::visualization::PCLVisualizer::ExitMainLoopTimerCallback::Execute (