/*////////////////////////////////////////////////////////////////////////////// // CMT Cosmic Muon Tomography project ////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova All rights reserved Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > ------------------------------------------------------------------ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. //////////////////////////////////////////////////////////////////////////////*/ #ifndef ULIBVTKINTERFACE_H #define ULIBVTKINTERFACE_H #include "Core/Monitor.h" #include "Core/Object.h" #include "Core/Property.h" #include #include #include #include #include #include #include #include // vtk classes forward declaration // class vtkProp; class vtkProp3D; class vtkPolyData; class vtkPropCollection; class vtkRenderer; class vtkRendererCollection; class vtkRenderWindowInteractor; namespace uLib { namespace Archive { class display_properties_archive; } namespace Vtk { class Prop3D; class Viewer; } // namespace Vtk } // namespace uLib namespace uLib { namespace Vtk { class Prop3D : public uLib::Object { uLibTypeMacro(Prop3D, uLib::Object) public: Prop3D(); virtual ~Prop3D(); virtual vtkProp *GetProp(); virtual vtkProp3D *GetProxyProp(); virtual vtkPropCollection *GetParts(); virtual vtkPropCollection *GetProps(); virtual uLib::Object *GetContent() const { return nullptr; } void ConnectRenderer(vtkRenderer *renderer); void DisconnectRenderer(vtkRenderer *renderer); void ConnectViewer(Viewer *viewer); void DisonnectViewer(Viewer *viewer); void SetColor(double r, double g, double b); void GetColor(double &r, double &g, double &b) const; void SetOpacity(double alpha); double GetOpacity() const; void SetSelectable(bool selectable = true); bool IsSelectable() const; void SetSelected(bool selected = true); bool IsSelected() const; /** * @brief Synchronizes the VTK representation with the internal state and properties. * * This method should be called whenever the underlying model or display properties * are modified to ensure the visual representation in VTK is consistent. */ virtual void Update(); /** * @brief Synchronizes the internal state and properties from the VTK representation. * * This method should be called when the VTK representation has been modified * (e.g., via a gizmo) and the changes need to be pushed back to the model. */ virtual void SyncFromVtk(); enum Representation { Points = 0, Wireframe = 1, Surface = 2, SurfaceWithEdges = 3, Volume = 4, Outline = 5, Slice = 6 }; void SetRepresentation(Representation mode); void SetRepresentation(const char *mode); enum HighlightMode { HighlightPlain = 0, HighlightCorners = 1 }; void SetHighlightMode(HighlightMode mode); virtual void PrintSelf(std::ostream &o) const; void ShowBoundingBox(bool show); void ShowScaleMeasures(bool show); vtkRendererCollection *GetRenderers() const; const std::vector &GetDisplayProperties() const override { return m_DisplayProperties; } void RegisterDisplayProperty(uLib::PropertyBase *prop) override { m_DisplayProperties.push_back(prop); } virtual void serialize_display(uLib::Archive::display_properties_archive &ar, const unsigned int version = 0); virtual void ConnectInteractor(class vtkRenderWindowInteractor *interactor); void AddToViewer(class Viewport &viewer); void RemoveFromViewer(class Viewport &viewer); protected: void SetProp(vtkProp *prop); void RemoveProp(vtkProp *prop); virtual void ApplyAppearance(vtkProp *prop); virtual void ApplyTransform(vtkProp3D *p3d); virtual void ApplyProp3DTransform(vtkProp3D *p3d); std::vector m_DisplayProperties; mutable uLib::RecursiveMutex m_UpdateMutex; private: Prop3D(const Prop3D &) = delete; Prop3D &operator=(const Prop3D &) = delete; friend class Prop3DData; class Prop3DData *pd; }; } // namespace Vtk } // namespace uLib // -------------------------------------------------------------------------- // // DISPLAY PROPERTIES SERIALIZE // -------------------------------------------------------------------------- // namespace uLib { namespace Archive { /** * @brief Specialized archive for registering display-only properties in * Prop3Ds. */ class display_properties_archive : public boost::archive::detail::common_oarchive< display_properties_archive> { public: friend class boost::archive::detail::interface_oarchive; friend class boost::archive::save_access; using boost::archive::detail::common_oarchive::save_override; display_properties_archive(Vtk::Prop3D *p) : boost::archive::detail::common_oarchive( boost::archive::no_header), m_Prop3D(p) { if (p) m_Visited.insert(dynamic_cast(p)); } std::string GetCurrentGroup() const { std::string group; for (const auto &g : m_GroupStack) { if (!group.empty()) group += "."; group += g; } return group; } template void save_override(const boost::serialization::hrp &t) { if (m_Prop3D) { uLib::Property *p = new uLib::Property( m_Prop3D, t.name(), &const_cast &>(t).value(), t.units() ? t.units() : "", GetCurrentGroup()); if (t.has_range()) p->SetRange(t.min_val(), t.max_val()); if (t.has_default()) p->SetDefault(t.default_val()); m_Prop3D->RegisterDisplayProperty(p); Vtk::Prop3D *prop3d = m_Prop3D; uLib::Object::connect(p, &uLib::Object::Updated, [prop3d]() { prop3d->Update(); }); } } template void save_override(const boost::serialization::hrp_enum &t) { if (m_Prop3D) { uLib::EnumProperty *p = new uLib::EnumProperty( m_Prop3D, t.name(), (int *)&const_cast &>(t).value(), t.labels(), t.units() ? t.units() : "", GetCurrentGroup()); m_Prop3D->RegisterDisplayProperty(p); Vtk::Prop3D *prop3d = m_Prop3D; uLib::Object::connect(p, &uLib::Object::Updated, [prop3d]() { prop3d->Update(); }); } } template void save_override(const boost::serialization::nvp &t) { if (t.name()) m_GroupStack.push_back(t.name()); this->save_helper(t.const_value(), typename boost::is_class::type()); if (t.name()) m_GroupStack.pop_back(); } // Follow pointers to discover properties in child objects template void save_override(T * const & t) { if (!t) return; this->save_pointer_helper(t, typename boost::is_base_of::type()); } template void save_pointer_helper(T* t, boost::mpl::true_) { const void* ptr = dynamic_cast(t); if (m_Visited.find(ptr) != m_Visited.end()) return; m_Visited.insert(ptr); this->save_override(*t); } template void save_pointer_helper(T* t, boost::mpl::false_) {} // Recursion for nested classes, ignore primitives template void save_override(const T &t) { this->save_helper(t, typename boost::is_class::type()); } template void save_helper(const T &t, boost::mpl::true_) { boost::serialization::serialize_adl(*this, const_cast(t), 0); } void save_helper(const std::string &t, boost::mpl::true_) {} template void save_helper(const T &t, boost::mpl::false_) {} void save_override(const boost::archive::object_id_type &t) {} void save_override(const boost::archive::object_reference_type &t) {} void save_override(const boost::archive::version_type &t) {} void save_override(const boost::archive::class_id_type &t) {} void save_override(const boost::archive::class_id_optional_type &t) {} void save_override(const boost::archive::class_id_reference_type &t) {} void save_override(const boost::archive::class_name_type &t) {} void save_override(const boost::archive::tracking_type &t) {} // Called by Property::serialize() and EnumProperty::serialize() to // directly register an existing property object as a display property. void register_property(uLib::PropertyBase &p) { if (m_Prop3D) { m_Prop3D->RegisterDisplayProperty(&p); Vtk::Prop3D *prop3d = m_Prop3D; uLib::Object::connect(&p, &uLib::Object::Updated, [prop3d]() { prop3d->Update(); }); } } void register_enum_property(uLib::EnumProperty &p) { register_property(p); } private: Vtk::Prop3D *m_Prop3D; std::vector m_GroupStack; std::set m_Visited; }; } // namespace Archive // This macro MUST be defined after both Prop3D and display_properties_archive // are fully defined. #define ULIB_ACTIVATE_DISPLAY_PROPERTIES \ { \ uLib::Archive::display_properties_archive dar(this); \ this->serialize_display(dar, 0); \ } } // namespace uLib #endif // ULIBVTKINTERFACE_H