diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index c7976a9999..0a82a9ebb7 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -58,13 +58,17 @@ namespace cv { namespace viz - { + { + typedef std::map VizMap; + typedef std::pair VizPair; + //! takes coordiante frame data and builds transfrom to global coordinate frame CV_EXPORTS Affine3f makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin = Vec3f::all(0)); //! constructs camera pose from position, focal_point and up_vector (see gluLookAt() for more infromation CV_EXPORTS Affine3f makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir); + CV_EXPORTS Viz3d get(const String &window_name); //! checks float value for Nan inline bool isNan(float x) @@ -87,6 +91,27 @@ namespace cv //! checks point for Nans template inline bool isNan(const Point3_<_Tp>& p) { return isNan(p.x) || isNan(p.y) || isNan(p.z); } + + class CV_EXPORTS VizAccessor + { + public: + static VizAccessor & getInstance(); + static void release(); + + Viz3d get(const String &window_name); + void add(Viz3d window); + void remove(const String &window_name); + + static void generateWindowName(const String &window_name, String &output); + + private: + VizAccessor(); // Singleton + ~VizAccessor(); + + static VizAccessor * instance_; + static bool is_instantiated_; + static VizMap viz_map_; + }; } } diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 33b2743254..f4adcd8355 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -21,6 +21,8 @@ namespace cv typedef void (*MouseCallback)(const MouseEvent&, void*); Viz3d(const String& window_name = String()); + Viz3d(const Viz3d&); + Viz3d& operator=(const Viz3d&); ~Viz3d(); void setBackgroundColor(const Color& color = Color::black()); @@ -50,6 +52,8 @@ namespace cv Size getWindowSize() const; void setWindowSize(const Size &window_size); + + String getWindowName() const; void spin(); void spinOnce(int time = 1, bool force_redraw = false); @@ -58,11 +62,12 @@ namespace cv void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); void registerMouseCallback(MouseCallback callback, void* cookie = 0); private: - Viz3d(const Viz3d&); - Viz3d& operator=(const Viz3d&); struct VizImpl; VizImpl* impl_; + + void create(const String &window_name); + void release(); }; } /* namespace viz */ diff --git a/modules/viz/src/viz.cpp b/modules/viz/src/viz.cpp index 2d563f6c1f..c8e09ba9ee 100644 --- a/modules/viz/src/viz.cpp +++ b/modules/viz/src/viz.cpp @@ -85,3 +85,84 @@ namespace cv } } } + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Viz accessor implementation + +cv::viz::VizAccessor * cv::viz::VizAccessor::instance_ = 0; +bool cv::viz::VizAccessor::is_instantiated_ = false; +cv::viz::VizMap cv::viz::VizAccessor::viz_map_; + +cv::viz::VizAccessor::VizAccessor() {} + +cv::viz::VizAccessor::~VizAccessor() {} + +cv::viz::VizAccessor & cv::viz::VizAccessor::getInstance() +{ + if (!is_instantiated_) + { + instance_ = new VizAccessor(); + is_instantiated_ = true; + } + return *instance_; +} + +void cv::viz::VizAccessor::release() +{ + if (is_instantiated_) + { + delete instance_; + instance_ = 0; + is_instantiated_ = false; + } +} + +cv::viz::Viz3d cv::viz::VizAccessor::get(const String & window_name) +{ + // Add the prefix Viz + String name; + generateWindowName(window_name, name); + + VizMap::iterator vm_itr = viz_map_.find(name); + bool exists = vm_itr != viz_map_.end(); + if (exists) return vm_itr->second; + else return viz_map_.insert(VizPair(window_name, Viz3d(window_name))).first->second; +} + +void cv::viz::VizAccessor::add(Viz3d window) +{ + String window_name = window.getWindowName(); + VizMap::iterator vm_itr = viz_map_.find(window_name); + bool exists = vm_itr != viz_map_.end(); + if (exists) return ; + viz_map_.insert(std::pair(window_name, window)); +} + +void cv::viz::VizAccessor::remove(const String &window_name) +{ + // Add the prefix Viz + String name; + generateWindowName(window_name, name); + + VizMap::iterator vm_itr = viz_map_.find(name); + bool exists = vm_itr != viz_map_.end(); + if (!exists) return ; + viz_map_.erase(vm_itr); +} + +void cv::viz::VizAccessor::generateWindowName(const String &window_name, String &output) +{ + output = "Viz"; + // Already is Viz + if (window_name == output) return; + + String prefixed = output + " - "; + if (window_name.substr(0, prefixed.length()) == prefixed) output = window_name; // Already has "Viz - " + else if (window_name.substr(0, output.length()) == output) output = prefixed + window_name; // Doesn't have prefix + else output = (window_name == "" ? output : prefixed + window_name); +} + +cv::viz::Viz3d cv::viz::get(const String &window_name) +{ + return cv::viz::VizAccessor::getInstance().get(window_name); +} \ No newline at end of file diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index ced6e73e18..583ece096b 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -2,8 +2,45 @@ #include "viz3d_impl.hpp" -cv::viz::Viz3d::Viz3d(const String& window_name) : impl_(new VizImpl(window_name)) {} -cv::viz::Viz3d::~Viz3d() { delete impl_; } +cv::viz::Viz3d::Viz3d(const String& window_name) : impl_(0) { create(window_name); } + +cv::viz::Viz3d::Viz3d(const Viz3d& other) : impl_(other.impl_) +{ + if (impl_) CV_XADD(&impl_->ref_counter, 1); +} + +cv::viz::Viz3d& cv::viz::Viz3d::operator=(const Viz3d& other) +{ + if (this != &other) + { + release(); + impl_ = other.impl_; + if (impl_) CV_XADD(&impl_->ref_counter, 1); + } + return *this; +} + +cv::viz::Viz3d::~Viz3d() { release(); } + +void cv::viz::Viz3d::create(const String &window_name) +{ + if (impl_) release(); + impl_ = new VizImpl(window_name); + impl_->ref_counter = 1; + // Register the window + cv::viz::VizAccessor::getInstance().add(*this); +} + +void cv::viz::Viz3d::release() +{ + if (impl_ && CV_XADD(&impl_->ref_counter, -1) == 1) + { + // Erase the window + cv::viz::VizAccessor::getInstance().remove(getWindowName()); + delete impl_; + impl_ = 0; + } +} void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } @@ -55,4 +92,5 @@ void cv::viz::Viz3d::convertToWindowCoordinates(const Point3d &pt, Point3d &wind void cv::viz::Viz3d::converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction) { impl_->converTo3DRay(window_coord, origin, direction); } cv::Size cv::viz::Viz3d::getWindowSize() const { return impl_->getWindowSize(); } -void cv::viz::Viz3d::setWindowSize(const Size &window_size) { impl_->setWindowSize(window_size.width, window_size.height); } \ No newline at end of file +void cv::viz::Viz3d::setWindowSize(const Size &window_size) { impl_->setWindowSize(window_size.width, window_size.height); } +cv::String cv::viz::Viz3d::getWindowName() const { return impl_->getWindowName(); } \ No newline at end of file diff --git a/modules/viz/src/viz3d_impl.cpp b/modules/viz/src/viz3d_impl.cpp index a2aa31bedc..95f93b1154 100644 --- a/modules/viz/src/viz3d_impl.cpp +++ b/modules/viz/src/viz3d_impl.cpp @@ -74,19 +74,17 @@ cv::viz::Viz3d::VizImpl::VizImpl (const std::string &name) ////////////////////////////// - - String window_name("Viz"); - window_name = name.empty() ? window_name : window_name + " - " + name; + String window_name; + VizAccessor::generateWindowName(name, window_name); window_->SetWindowName (window_name.c_str ()); } ///////////////////////////////////////////////////////////////////////////////////////////// cv::viz::Viz3d::VizImpl::~VizImpl () { - if (interactor_ != NULL) - interactor_->DestroyTimer (timer_id_); - - renderer_->Clear(); + if (interactor_) + interactor_->DestroyTimer(timer_id_); + if (renderer_) renderer_->Clear(); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -968,6 +966,11 @@ void cv::viz::Viz3d::VizImpl::setWindowName (const std::string &name) window_->SetWindowName (name.c_str ()); } +cv::String cv::viz::Viz3d::VizImpl::getWindowName() const +{ + return (window_ ? window_->GetWindowName() : ""); +} + void cv::viz::Viz3d::VizImpl::setWindowPosition (int x, int y) { window_->SetPosition (x, y); } void cv::viz::Viz3d::VizImpl::setWindowSize (int xw, int yw) { window_->SetSize (xw, yw); } cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); } diff --git a/modules/viz/src/viz3d_impl.hpp b/modules/viz/src/viz3d_impl.hpp index e190b720bb..ef23cc1b90 100644 --- a/modules/viz/src/viz3d_impl.hpp +++ b/modules/viz/src/viz3d_impl.hpp @@ -11,6 +11,8 @@ public: typedef cv::Ptr Ptr; typedef Viz3d::KeyboardCallback KeyboardCallback; typedef Viz3d::MouseCallback MouseCallback; + + int ref_counter; VizImpl (const String &name); virtual ~VizImpl (); @@ -67,7 +69,11 @@ public: void close () { stopped_ = true; - interactor_->TerminateApp (); // This tends to close the window... + if (interactor_) + { + interactor_->GetRenderWindow()->Finalize(); + interactor_->TerminateApp (); // This tends to close the window... + } } @@ -142,6 +148,7 @@ public: void setWindowSize (int xw, int yw); void setFullScreen (bool mode); void setWindowName (const String &name); + String getWindowName() const; void setBackgroundColor (const Color& color); void spin ();