1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of the copyright holders may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 // Authors:
41 //  * Ozan Tonkal, ozantonkal@gmail.com
42 //  * Anatoly Baksheev, Itseez Inc.  myname.mysurname <> mycompany.com
43 //
44 //M*/
45 
46 #include "precomp.hpp"
47 
48 ///////////////////////////////////////////////////////////////////////////////////////////////
49 /// widget implementation
50 
51 class cv::viz::Widget::Impl
52 {
53 public:
54     vtkSmartPointer<vtkProp> prop;
Impl()55     Impl() : prop(0) {}
56 };
57 
Widget()58 cv::viz::Widget::Widget() : impl_( new Impl() ) { }
59 
Widget(const Widget & other)60 cv::viz::Widget::Widget(const Widget& other) : impl_( new Impl() )
61 {
62     if (other.impl_ && other.impl_->prop)
63         impl_->prop = other.impl_->prop;
64 }
65 
operator =(const Widget & other)66 cv::viz::Widget& cv::viz::Widget::operator=(const Widget& other)
67 {
68     if (!impl_)
69         impl_ = new Impl();
70 
71     if (other.impl_)
72         impl_->prop = other.impl_->prop;
73     return *this;
74 }
75 
~Widget()76 cv::viz::Widget::~Widget()
77 {
78     if (impl_)
79     {
80         delete impl_;
81         impl_ = 0;
82     }
83 }
84 
fromPlyFile(const String & file_name)85 cv::viz::Widget cv::viz::Widget::fromPlyFile(const String &file_name)
86 {
87     CV_Assert(vtkPLYReader::CanReadFile(file_name.c_str()));
88 
89     vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();
90     reader->SetFileName(file_name.c_str());
91 
92     vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
93     mapper->SetInputConnection( reader->GetOutputPort() );
94     mapper->ImmediateModeRenderingOff();
95 
96     vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
97     actor->GetProperty()->SetInterpolationToFlat();
98     actor->GetProperty()->BackfaceCullingOn();
99     actor->SetMapper(mapper);
100 
101     Widget widget;
102     WidgetAccessor::setProp(widget, actor);
103     return widget;
104 }
105 
setRenderingProperty(int property,double value)106 void cv::viz::Widget::setRenderingProperty(int property, double value)
107 {
108     vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
109     CV_Assert("Widget type is not supported." && actor);
110 
111     switch (property)
112     {
113         case POINT_SIZE:          actor->GetProperty()->SetPointSize(float(value)); break;
114         case OPACITY:             actor->GetProperty()->SetOpacity(value);          break;
115         case LINE_WIDTH:          actor->GetProperty()->SetLineWidth(float(value)); break;
116         case IMMEDIATE_RENDERING: actor->GetMapper()->SetImmediateModeRendering(int(value)); break;
117         case FONT_SIZE:
118         {
119             vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor);
120             CV_Assert("Widget does not have text content." && text_actor);
121             text_actor->GetTextProperty()->SetFontSize(int(value));
122             break;
123         }
124         case REPRESENTATION:
125         {
126             switch (int(value))
127             {
128                 case REPRESENTATION_POINTS:    actor->GetProperty()->SetRepresentationToPoints(); break;
129                 case REPRESENTATION_WIREFRAME: actor->GetProperty()->SetRepresentationToWireframe(); break;
130                 case REPRESENTATION_SURFACE:   actor->GetProperty()->SetRepresentationToSurface();  break;
131             }
132             break;
133         }
134         case SHADING:
135         {
136             switch (int(value))
137             {
138                 case SHADING_FLAT: actor->GetProperty()->SetInterpolationToFlat(); break;
139                 case SHADING_GOURAUD:
140                 {
141                     if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals())
142                     {
143                         vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
144                         CV_Assert("Can't set shading property for such type of widget" && mapper);
145 
146                         vtkSmartPointer<vtkPolyData> with_normals = VtkUtils::ComputeNormals(mapper->GetInput());
147                         VtkUtils::SetInputData(mapper, with_normals);
148                     }
149                     actor->GetProperty()->SetInterpolationToGouraud();
150                     break;
151                 }
152                 case SHADING_PHONG:
153                 {
154                     if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals())
155                     {
156                         vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
157                         CV_Assert("Can't set shading property for such type of widget" && mapper);
158 
159                         vtkSmartPointer<vtkPolyData> with_normals = VtkUtils::ComputeNormals(mapper->GetInput());
160                         VtkUtils::SetInputData(mapper, with_normals);
161                     }
162                     actor->GetProperty()->SetInterpolationToPhong();
163                     break;
164                 }
165             }
166             break;
167         }
168         default:
169             CV_Assert("setPointCloudRenderingProperties: Unknown property");
170     }
171     actor->Modified();
172 }
173 
getRenderingProperty(int property) const174 double cv::viz::Widget::getRenderingProperty(int property) const
175 {
176     vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
177     CV_Assert("Widget type is not supported." && actor);
178 
179     double value = 0.0;
180     switch (property)
181     {
182         case POINT_SIZE: value = actor->GetProperty()->GetPointSize(); break;
183         case OPACITY:    value = actor->GetProperty()->GetOpacity();   break;
184         case LINE_WIDTH: value = actor->GetProperty()->GetLineWidth(); break;
185         case IMMEDIATE_RENDERING:  value = actor->GetMapper()->GetImmediateModeRendering();  break;
186 
187         case FONT_SIZE:
188         {
189             vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor);
190             CV_Assert("Widget does not have text content." && text_actor);
191             value = text_actor->GetTextProperty()->GetFontSize();;
192             break;
193         }
194         case REPRESENTATION:
195         {
196             switch (actor->GetProperty()->GetRepresentation())
197             {
198                 case VTK_POINTS:    value = REPRESENTATION_POINTS; break;
199                 case VTK_WIREFRAME: value = REPRESENTATION_WIREFRAME; break;
200                 case VTK_SURFACE:   value = REPRESENTATION_SURFACE; break;
201             }
202             break;
203         }
204         case SHADING:
205         {
206             switch (actor->GetProperty()->GetInterpolation())
207             {
208                 case VTK_FLAT:      value = SHADING_FLAT; break;
209                 case VTK_GOURAUD:   value = SHADING_GOURAUD; break;
210                 case VTK_PHONG:     value = SHADING_PHONG; break;
211             }
212             break;
213         }
214         default:
215             CV_Assert("getPointCloudRenderingProperties: Unknown property");
216     }
217     return value;
218 }
219 
220 ///////////////////////////////////////////////////////////////////////////////////////////////
221 /// widget accessor implementaion
222 
getProp(const Widget & widget)223 vtkSmartPointer<vtkProp> cv::viz::WidgetAccessor::getProp(const Widget& widget)
224 {
225     return widget.impl_->prop;
226 }
227 
setProp(Widget & widget,vtkSmartPointer<vtkProp> prop)228 void cv::viz::WidgetAccessor::setProp(Widget& widget, vtkSmartPointer<vtkProp> prop)
229 {
230     widget.impl_->prop = prop;
231 }
232 
233 ///////////////////////////////////////////////////////////////////////////////////////////////
234 /// widget3D implementation
235 
setPose(const Affine3d & pose)236 void cv::viz::Widget3D::setPose(const Affine3d &pose)
237 {
238     vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this));
239     CV_Assert("Widget is not 3D." && actor);
240 
241     vtkSmartPointer<vtkMatrix4x4> matrix = vtkmatrix(pose.matrix);
242     actor->SetUserMatrix(matrix);
243     actor->Modified();
244 }
245 
updatePose(const Affine3d & pose)246 void cv::viz::Widget3D::updatePose(const Affine3d &pose)
247 {
248     vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this));
249     CV_Assert("Widget is not 3D." && actor);
250 
251     vtkSmartPointer<vtkMatrix4x4> matrix = actor->GetUserMatrix();
252     if (!matrix)
253     {
254         setPose(pose);
255         return;
256     }
257 
258     Affine3d updated_pose = pose * Affine3d(*matrix->Element);
259     matrix = vtkmatrix(updated_pose.matrix);
260 
261     actor->SetUserMatrix(matrix);
262     actor->Modified();
263 }
264 
getPose() const265 cv::Affine3d cv::viz::Widget3D::getPose() const
266 {
267     vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this));
268     CV_Assert("Widget is not 3D." && actor);
269     return Affine3d(*actor->GetUserMatrix()->Element);
270 }
271 
applyTransform(const Affine3d & transform)272 void cv::viz::Widget3D::applyTransform(const Affine3d &transform)
273 {
274     vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
275     CV_Assert("Widget is not 3D actor." && actor);
276 
277     vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
278     CV_Assert("Widget doesn't have a polydata mapper" && mapper);
279     mapper->Update();
280 
281     VtkUtils::SetInputData(mapper, VtkUtils::TransformPolydata(mapper->GetInput(), transform));
282 }
283 
setColor(const Color & color)284 void cv::viz::Widget3D::setColor(const Color &color)
285 {
286     // Cast to actor instead of prop3d since prop3d doesn't provide getproperty
287     vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
288     CV_Assert("Widget type is not supported." && actor);
289 
290     Color c = vtkcolor(color);
291     actor->GetMapper()->ScalarVisibilityOff();
292     actor->GetProperty()->SetColor(c.val);
293     actor->GetProperty()->SetEdgeColor(c.val);
294     actor->Modified();
295 }
296 
cast()297 template<> cv::viz::Widget3D cv::viz::Widget::cast<cv::viz::Widget3D>()
298 {
299     vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this));
300     CV_Assert("Widget cannot be cast." && actor);
301 
302     Widget3D widget;
303     WidgetAccessor::setProp(widget, actor);
304     return widget;
305 }
306 
307 ///////////////////////////////////////////////////////////////////////////////////////////////
308 /// widget2D implementation
309 
setColor(const Color & color)310 void cv::viz::Widget2D::setColor(const Color &color)
311 {
312     vtkActor2D *actor = vtkActor2D::SafeDownCast(WidgetAccessor::getProp(*this));
313     CV_Assert("Widget type is not supported." && actor);
314     Color c = vtkcolor(color);
315     actor->GetProperty()->SetColor(c.val);
316     actor->Modified();
317 }
318 
cast()319 template<> cv::viz::Widget2D cv::viz::Widget::cast<cv::viz::Widget2D>()
320 {
321     vtkActor2D *actor = vtkActor2D::SafeDownCast(WidgetAccessor::getProp(*this));
322     CV_Assert("Widget cannot be cast." && actor);
323 
324     Widget2D widget;
325     WidgetAccessor::setProp(widget, actor);
326     return widget;
327 }
328