diff --git a/modules/viz/include/opencv2/viz/widget_accessor.hpp b/modules/viz/include/opencv2/viz/widget_accessor.hpp index 0cc39f7ff..ec2a02030 100644 --- a/modules/viz/include/opencv2/viz/widget_accessor.hpp +++ b/modules/viz/include/opencv2/viz/widget_accessor.hpp @@ -13,5 +13,6 @@ namespace temp_viz struct CV_EXPORTS WidgetAccessor { static vtkSmartPointer getActor(const Widget &widget); + static void setVtkProp(Widget &widget, vtkSmartPointer actor); }; } diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index b5b9b65cd..b22be4040 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -13,32 +13,44 @@ namespace temp_viz Widget(); Widget(const Widget &other); Widget& operator =(const Widget &other); - + ~Widget(); - void copyTo(Widget &dst); - - void setColor(const Color &color); + private: + class Impl; + Impl *impl_; + friend struct WidgetAccessor; + + }; + + ///////////////////////////////////////////////////////////////////////////// + /// The base class for all 3D widgets + class CV_EXPORTS Widget3D : public Widget + { + public: + Widget3D(); + void setPose(const Affine3f &pose); void updatePose(const Affine3f &pose); Affine3f getPose() const; - protected: - Widget(bool text_widget); + void setColor(const Color &color); private: - class Impl; - Impl* impl_; + struct MatrixConverter; - void create(); - void release(); - void create(bool text_widget); - - friend struct WidgetAccessor; }; + + ///////////////////////////////////////////////////////////////////////////// + /// The base class for all 2D widgets + class CV_EXPORTS Widget2D : public Widget + { + public: + Widget2D(); + }; + - - class CV_EXPORTS LineWidget : public Widget + class CV_EXPORTS LineWidget : public Widget3D { public: LineWidget(const Point3f &pt1, const Point3f &pt2, const Color &color = Color::white()); @@ -47,58 +59,56 @@ namespace temp_viz float getLineWidth(); }; - class CV_EXPORTS PlaneWidget : public Widget + class CV_EXPORTS PlaneWidget : public Widget3D { public: PlaneWidget(const Vec4f& coefs, double size = 1.0, const Color &color = Color::white()); PlaneWidget(const Vec4f& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); }; - class CV_EXPORTS SphereWidget : public Widget + class CV_EXPORTS SphereWidget : public Widget3D { public: SphereWidget(const cv::Point3f ¢er, float radius, int sphere_resolution = 10, const Color &color = Color::white()); }; - class CV_EXPORTS ArrowWidget : public Widget + class CV_EXPORTS ArrowWidget : public Widget3D { public: ArrowWidget(const Point3f& pt1, const Point3f& pt2, const Color &color = Color::white()); }; - class CV_EXPORTS CircleWidget : public Widget + class CV_EXPORTS CircleWidget : public Widget3D { public: CircleWidget(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); }; - class CV_EXPORTS CylinderWidget : public Widget + class CV_EXPORTS CylinderWidget : public Widget3D { public: CylinderWidget(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); }; - class CV_EXPORTS CubeWidget : public Widget + class CV_EXPORTS CubeWidget : public Widget3D { public: CubeWidget(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, const Color &color = Color::white()); }; - class CV_EXPORTS CoordinateSystemWidget : public Widget + class CV_EXPORTS CoordinateSystemWidget : public Widget3D { public: CoordinateSystemWidget(double scale, const Affine3f& affine); }; - class CV_EXPORTS TextWidget : public Widget + class CV_EXPORTS TextWidget : public Widget2D { public: TextWidget(const String &text, const Point2i &pos, int font_size = 10, const Color &color = Color::white()); - - // TODO Overload setColor method, and hide setPose, updatePose, getPose methods }; - class CV_EXPORTS CloudWidget : public Widget + class CV_EXPORTS CloudWidget : public Widget3D { public: CloudWidget(InputArray _cloud, InputArray _colors); @@ -107,7 +117,7 @@ namespace temp_viz struct CreateCloudWidget; }; - class CV_EXPORTS CloudNormalsWidget : public Widget + class CV_EXPORTS CloudNormalsWidget : public Widget3D { public: CloudNormalsWidget(InputArray _cloud, InputArray _normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); diff --git a/modules/viz/src/simple_widgets.cpp b/modules/viz/src/simple_widgets.cpp index 640e85c98..8cb77ee44 100644 --- a/modules/viz/src/simple_widgets.cpp +++ b/modules/viz/src/simple_widgets.cpp @@ -9,6 +9,8 @@ namespace temp_viz /// line widget implementation temp_viz::LineWidget::LineWidget(const Point3f &pt1, const Point3f &pt2, const Color &color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1 (pt1.x, pt1.y, pt1.z); line->SetPoint2 (pt2.x, pt2.y, pt2.z); @@ -40,6 +42,8 @@ float temp_viz::LineWidget::getLineWidth() temp_viz::PlaneWidget::PlaneWidget(const Vec4f& coefs, double size, const Color &color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer plane = vtkSmartPointer::New (); plane->SetNormal (coefs[0], coefs[1], coefs[2]); double norm = cv::norm(cv::Vec3f(coefs.val)); @@ -57,6 +61,8 @@ temp_viz::PlaneWidget::PlaneWidget(const Vec4f& coefs, double size, const Color temp_viz::PlaneWidget::PlaneWidget(const Vec4f& coefs, const Point3f& pt, double size, const Color &color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer plane = vtkSmartPointer::New (); cv::Point3f coefs3(coefs[0], coefs[1], coefs[2]); double norm_sqr = 1.0 / coefs3.dot (coefs3); @@ -81,6 +87,8 @@ temp_viz::PlaneWidget::PlaneWidget(const Vec4f& coefs, const Point3f& pt, double temp_viz::SphereWidget::SphereWidget(const cv::Point3f ¢er, float radius, int sphere_resolution, const Color &color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer sphere = vtkSmartPointer::New (); sphere->SetRadius (radius); sphere->SetCenter (center.x, center.y, center.z); @@ -103,6 +111,8 @@ temp_viz::SphereWidget::SphereWidget(const cv::Point3f ¢er, float radius, in temp_viz::ArrowWidget::ArrowWidget(const Point3f& pt1, const Point3f& pt2, const Color &color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer arrowSource = vtkSmartPointer::New (); float startPoint[3], endPoint[3]; @@ -165,6 +175,8 @@ temp_viz::ArrowWidget::ArrowWidget(const Point3f& pt1, const Point3f& pt2, const temp_viz::CircleWidget::CircleWidget(const temp_viz::Point3f& pt, double radius, double thickness, const temp_viz::Color& color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer disk = vtkSmartPointer::New (); // Maybe the resolution should be lower e.g. 50 or 25 disk->SetCircumferentialResolution (50); @@ -194,6 +206,8 @@ temp_viz::CircleWidget::CircleWidget(const temp_viz::Point3f& pt, double radius, temp_viz::CylinderWidget::CylinderWidget(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides, const Color &color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + const cv::Point3f pt2 = pt_on_axis + axis_direction; vtkSmartPointer line = vtkSmartPointer::New (); line->SetPoint1 (pt_on_axis.x, pt_on_axis.y, pt_on_axis.z); @@ -218,6 +232,8 @@ temp_viz::CylinderWidget::CylinderWidget(const Point3f& pt_on_axis, const Point3 temp_viz::CubeWidget::CubeWidget(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame, const Color &color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer cube = vtkSmartPointer::New (); cube->SetBounds (pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); @@ -238,6 +254,8 @@ temp_viz::CubeWidget::CubeWidget(const Point3f& pt_min, const Point3f& pt_max, b temp_viz::CoordinateSystemWidget::CoordinateSystemWidget(double scale, const Affine3f& affine) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer axes = vtkSmartPointer::New (); axes->SetOrigin (0, 0, 0); axes->SetScaleFactor (scale); @@ -285,8 +303,10 @@ temp_viz::CoordinateSystemWidget::CoordinateSystemWidget(double scale, const Aff /////////////////////////////////////////////////////////////////////////////////////////////// /// text widget implementation -temp_viz::TextWidget::TextWidget(const String &text, const Point2i &pos, int font_size, const Color &color) : Widget(true) +temp_viz::TextWidget::TextWidget(const String &text, const Point2i &pos, int font_size, const Color &color) { + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkTextActor *actor = vtkTextActor::SafeDownCast(WidgetAccessor::getActor(*this)); actor->SetPosition (pos.x, pos.y); actor->SetInput (text.c_str ()); @@ -400,6 +420,8 @@ temp_viz::CloudWidget::CloudWidget(InputArray _cloud, InputArray _colors) CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); CV_Assert(colors.type() == CV_8UC3 && cloud.size() == colors.size()); + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkLODActor * actor = vtkLODActor::SafeDownCast(WidgetAccessor::getActor(*this)); vtkIdType nr_points; vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); @@ -441,6 +463,8 @@ temp_viz::CloudWidget::CloudWidget(InputArray _cloud, const Color &color) Mat cloud = _cloud.getMat(); CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkLODActor * actor = vtkLODActor::SafeDownCast(WidgetAccessor::getActor(*this)); vtkIdType nr_points; vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); @@ -551,6 +575,8 @@ temp_viz::CloudNormalsWidget::CloudNormalsWidget(InputArray _cloud, InputArray _ CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); CV_Assert(cloud.size() == normals.size() && cloud.type() == normals.type()); + WidgetAccessor::setVtkProp(*this, vtkSmartPointer::New()); + vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer lines = vtkSmartPointer::New(); vtkIdType nr_normals = 0; diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index f75827f8f..4fed46d1c 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -1,90 +1,132 @@ #include "precomp.hpp" +/////////////////////////////////////////////////////////////////////////////////////////////// +/// widget implementation + class temp_viz::Widget::Impl { public: vtkSmartPointer actor; - int ref_counter; - - Impl() : actor(vtkSmartPointer::New()) {} - Impl(bool text_widget) - { - if (text_widget) - actor = vtkSmartPointer::New(); - else - actor = vtkSmartPointer::New(); - } - - void setColor(const Color& color) - { - vtkLODActor *lod_actor = vtkLODActor::SafeDownCast(actor); - Color c = vtkcolor(color); - lod_actor->GetMapper ()->ScalarVisibilityOff (); - lod_actor->GetProperty ()->SetColor (c.val); - lod_actor->GetProperty ()->SetEdgeColor (c.val); - lod_actor->GetProperty ()->SetAmbient (0.8); - lod_actor->GetProperty ()->SetDiffuse (0.8); - lod_actor->GetProperty ()->SetSpecular (0.8); - lod_actor->GetProperty ()->SetLighting (0); - lod_actor->Modified (); - } - - void setPose(const Affine3f& pose) - { - vtkLODActor *lod_actor = vtkLODActor::SafeDownCast(actor); - vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); - lod_actor->SetUserMatrix (matrix); - lod_actor->Modified (); - } - - void updatePose(const Affine3f& pose) - { - vtkLODActor *lod_actor = vtkLODActor::SafeDownCast(actor); - vtkSmartPointer matrix = lod_actor->GetUserMatrix(); - if (!matrix) - { - setPose(pose); - return ; - } - Matx44f matrix_cv = convertToMatx(matrix); - - Affine3f updated_pose = pose * Affine3f(matrix_cv); - matrix = convertToVtkMatrix(updated_pose.matrix); - - lod_actor->SetUserMatrix (matrix); - lod_actor->Modified (); - } - - Affine3f getPose() const - { - vtkLODActor *lod_actor = vtkLODActor::SafeDownCast(actor); - vtkSmartPointer matrix = lod_actor->GetUserMatrix(); - Matx44f matrix_cv = convertToMatx(matrix); - return Affine3f(matrix_cv); - } - -protected: - - static vtkSmartPointer convertToVtkMatrix (const cv::Matx44f& m) - { - vtkSmartPointer vtk_matrix = vtkSmartPointer::New (); - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - vtk_matrix->SetElement(i, k, m(i, k)); - return vtk_matrix; - } - - static cv::Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix) - { - cv::Matx44f m; - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - m(i, k) = vtk_matrix->GetElement (i, k); - return m; - } + Impl() : actor(0) {} }; +temp_viz::Widget::Widget() : impl_(0) +{ + impl_ = new Impl(); +} + +temp_viz::Widget::Widget(const Widget &other) : impl_(other.impl_) +{ + +} + +temp_viz::Widget& temp_viz::Widget::operator =(const Widget &other) +{ + if (this != &other) + { + delete impl_; + impl_ = other.impl_; + } + return *this; +} + +temp_viz::Widget::~Widget() +{ + if (impl_) + { + delete impl_; + impl_ = 0; + } +} + + + +// class temp_viz::Widget::Impl +// { +// public: +// vtkSmartPointer actor; +// int ref_counter; +// +// Impl() : actor(vtkSmartPointer::New()) {} +// +// Impl(bool text_widget) +// { +// if (text_widget) +// actor = vtkSmartPointer::New(); +// else +// actor = vtkSmartPointer::New(); +// } +// +// void setColor(const Color& color) +// { +// vtkLODActor *lod_actor = vtkLODActor::SafeDownCast(actor); +// Color c = vtkcolor(color); +// lod_actor->GetMapper ()->ScalarVisibilityOff (); +// lod_actor->GetProperty ()->SetColor (c.val); +// lod_actor->GetProperty ()->SetEdgeColor (c.val); +// lod_actor->GetProperty ()->SetAmbient (0.8); +// lod_actor->GetProperty ()->SetDiffuse (0.8); +// lod_actor->GetProperty ()->SetSpecular (0.8); +// lod_actor->GetProperty ()->SetLighting (0); +// lod_actor->Modified (); +// } +// +// void setPose(const Affine3f& pose) +// { +// vtkLODActor *lod_actor = vtkLODActor::SafeDownCast(actor); +// vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); +// lod_actor->SetUserMatrix (matrix); +// lod_actor->Modified (); +// } +// +// void updatePose(const Affine3f& pose) +// { +// vtkLODActor *lod_actor = vtkLODActor::SafeDownCast(actor); +// vtkSmartPointer matrix = lod_actor->GetUserMatrix(); +// if (!matrix) +// { +// setPose(pose); +// return ; +// } +// Matx44f matrix_cv = convertToMatx(matrix); +// +// Affine3f updated_pose = pose * Affine3f(matrix_cv); +// matrix = convertToVtkMatrix(updated_pose.matrix); +// +// lod_actor->SetUserMatrix (matrix); +// lod_actor->Modified (); +// } +// +// Affine3f getPose() const +// { +// vtkLODActor *lod_actor = vtkLODActor::SafeDownCast(actor); +// vtkSmartPointer matrix = lod_actor->GetUserMatrix(); +// Matx44f matrix_cv = convertToMatx(matrix); +// return Affine3f(matrix_cv); +// } +// +// protected: +// +// static vtkSmartPointer convertToVtkMatrix (const cv::Matx44f& m) +// { +// vtkSmartPointer vtk_matrix = vtkSmartPointer::New (); +// for (int i = 0; i < 4; i++) +// for (int k = 0; k < 4; k++) +// vtk_matrix->SetElement(i, k, m(i, k)); +// return vtk_matrix; +// } +// +// static cv::Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix) +// { +// cv::Matx44f m; +// for (int i = 0; i < 4; i++) +// for (int k = 0; k < 4; k++) +// m(i, k) = vtk_matrix->GetElement (i, k); +// return m; +// } +// }; + /////////////////////////////////////////////////////////////////////////////////////////////// /// stream accessor implementaion @@ -94,74 +136,101 @@ vtkSmartPointer temp_viz::WidgetAccessor::getActor(const Widget& widget return widget.impl_->actor; } +void temp_viz::WidgetAccessor::setVtkProp(Widget& widget, vtkSmartPointer actor) +{ + widget.impl_->actor = actor; +} + /////////////////////////////////////////////////////////////////////////////////////////////// -/// widget implementaion +/// widget3D implementation -temp_viz::Widget::Widget() : impl_(0) +struct temp_viz::Widget3D::MatrixConverter { - create(); -} - -temp_viz::Widget::Widget(bool text_widget) : impl_(0) -{ - create(text_widget); -} - -temp_viz::Widget::Widget(const Widget& other) : impl_(other.impl_) -{ - if (impl_) - CV_XADD(&impl_->ref_counter, 1); -} - -temp_viz::Widget& temp_viz::Widget::operator =(const Widget &other) -{ - if (this != &other) + static cv::Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix) { - release(); - impl_ = other.impl_; - if (impl_) - CV_XADD(&impl_->ref_counter, 1); + cv::Matx44f m; + for (int i = 0; i < 4; i++) + for (int k = 0; k < 4; k++) + m(i, k) = vtk_matrix->GetElement (i, k); + return m; } - return *this; -} - -temp_viz::Widget::~Widget() -{ - release(); -} - -void temp_viz::Widget::copyTo(Widget& /*dst*/) -{ - // TODO Deep copy the data if there is any -} - -void temp_viz::Widget::setColor(const Color& color) { impl_->setColor(color); } -void temp_viz::Widget::setPose(const Affine3f& pose) { impl_->setPose(pose); } -void temp_viz::Widget::updatePose(const Affine3f& pose) { impl_->updatePose(pose); } -temp_viz::Affine3f temp_viz::Widget::getPose() const { return impl_->getPose(); } - -void temp_viz::Widget::create() -{ - if (impl_) - release(); - impl_ = new Impl(); - impl_->ref_counter = 1; -} - -void temp_viz::Widget::release() -{ - if (impl_ && CV_XADD(&impl_->ref_counter, -1) == 1) + + static vtkSmartPointer convertToVtkMatrix (const cv::Matx44f& m) { - delete impl_; - impl_ = 0; + vtkSmartPointer vtk_matrix = vtkSmartPointer::New (); + for (int i = 0; i < 4; i++) + for (int k = 0; k < 4; k++) + vtk_matrix->SetElement(i, k, m(i, k)); + return vtk_matrix; } -} +}; -void temp_viz::Widget::create(bool text_widget) +temp_viz::Widget3D::Widget3D() { - if (impl_) - release(); - impl_ = new Impl(text_widget); - impl_->ref_counter = 1; + } +void temp_viz::Widget3D::setPose(const Affine3f &pose) +{ + vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getActor(*this)); + CV_Assert(actor); + + vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); + actor->SetUserMatrix (matrix); + actor->Modified (); +} + +void temp_viz::Widget3D::updatePose(const Affine3f &pose) +{ + vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getActor(*this)); + CV_Assert(actor); + + vtkSmartPointer matrix = actor->GetUserMatrix(); + if (!matrix) + { + setPose(pose); + return ; + } + Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix); + + Affine3f updated_pose = pose * Affine3f(matrix_cv); + matrix = MatrixConverter::convertToVtkMatrix(updated_pose.matrix); + + actor->SetUserMatrix (matrix); + actor->Modified (); +} + +temp_viz::Affine3f temp_viz::Widget3D::getPose() const +{ + vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getActor(*this)); + CV_Assert(actor); + + vtkSmartPointer matrix = actor->GetUserMatrix(); + Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix); + return Affine3f(matrix_cv); +} + +void temp_viz::Widget3D::setColor(const Color &color) +{ + // Cast to actor instead of prop3d since prop3d doesn't provide getproperty + vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getActor(*this)); + CV_Assert(actor); + + Color c = vtkcolor(color); + actor->GetMapper ()->ScalarVisibilityOff (); + actor->GetProperty ()->SetColor (c.val); + actor->GetProperty ()->SetEdgeColor (c.val); + actor->GetProperty ()->SetAmbient (0.8); + actor->GetProperty ()->SetDiffuse (0.8); + actor->GetProperty ()->SetSpecular (0.8); + actor->GetProperty ()->SetLighting (0); + actor->Modified (); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// widget2D implementation + +temp_viz::Widget2D::Widget2D() +{ + +}