1 /*
2  * Software License Agreement (BSD License)
3  *
4  *  Point Cloud Library (PCL) - www.pointclouds.org
5  *  Copyright (c) 2012-, Open Perception, Inc.
6  *
7  *  All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *
13  *   * Redistributions of source code must retain the above copyright
14  *     notice, this list of conditions and the following disclaimer.
15  *   * Redistributions in binary form must reproduce the above
16  *     copyright notice, this list of conditions and the following
17  *     disclaimer in the documentation and/or other materials provided
18  *     with the distribution.
19  *   * Neither the name of the copyright holder(s) nor the names of its
20  *     contributors may be used to endorse or promote products derived
21  *     from this software without specific prior written permission.
22  *
23  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  *  POSSIBILITY OF SUCH DAMAGE.
35  *
36  *
37  */
38 
39 #pragma once
40 
41 #include <vector>
42 #include <pcl/pcl_exports.h>
43 #include <vtkRenderer.h>
44 #include <vtkRenderWindow.h>
45 #include <vtkRenderWindowInteractor.h>
46 #include <vtkSmartPointer.h>
47 #include <vtkObjectFactory.h>
48 #include <vtkContext2D.h>
49 #include <vtkTransform2D.h>
50 #include <vtkContextItem.h>
51 #include <vtkContextView.h>
52 #include <vtkContextScene.h>
53 #include <vtkPen.h>
54 #include <vtkBrush.h>
55 #include <vtkTextProperty.h>
56 #include <vtkOpenGLContextDevice2D.h>
57 #include <vtkPoints2D.h>
58 #include "vtkCommand.h"
59 
60 namespace pcl
61 {
62   namespace visualization
63   {
64 
65    /** \brief Abstract class for storing figure information. All the derived class uses the same method draw() to invoke different drawing function of vtkContext2D
66      * \author Kripasindhu Sarkar
67      * \ingroup visualization
68      */
69     struct Figure2D
70     {
71       std::vector<float> info_;     //information stored in a general form for every object
72       vtkPen *pen_;                 //the corresponding pen and brush for the figure
73       vtkBrush *brush_;
74       vtkTransform2D *transform_;
75 
Figure2DFigure2D76       Figure2D (std::vector<float> info, vtkPen *p, vtkBrush * b, vtkTransform2D *t)
77       {
78         this->pen_ = vtkPen::New ();
79         this->brush_ = vtkBrush::New ();
80         this->transform_ = vtkTransform2D::New();
81 
82         this->pen_->DeepCopy (p);
83         this->brush_->DeepCopy (b);
84         this->transform_->SetMatrix (t->GetMatrix());
85         this->info_ = info; //note: it copies :-)
86       }
87 
Figure2DFigure2D88       Figure2D (vtkPen *p, vtkBrush * b, vtkTransform2D *t)
89       {
90         this->pen_ = vtkPen::New ();
91         this->brush_ = vtkBrush::New ();
92         this->transform_ = vtkTransform2D::New();
93 
94         this->pen_->DeepCopy (p);
95         this->brush_->DeepCopy (b);
96         this->transform_->SetMatrix (t->GetMatrix());
97       }
98 
applyInternalsFigure2D99       void applyInternals (vtkContext2D *painter) const
100       {
101         painter->ApplyPen (pen_);
102         painter->ApplyBrush (brush_);
103         painter->GetDevice ()->SetMatrix (transform_->GetMatrix());
104       }
105 
drawFigure2D106       virtual void draw (vtkContext2D *) {}
107     };
108 
109    /** \brief Class for PolyLine
110      */
111     struct FPolyLine2D : public Figure2D
112     {
113 
FPolyLine2DFPolyLine2D114       FPolyLine2D (std::vector<float> info, vtkPen *p, vtkBrush * b, vtkTransform2D *t) : Figure2D (info, p, b, t){}
115 
drawFPolyLine2D116       void draw (vtkContext2D * painter) override
117       {
118         applyInternals(painter);
119         painter->DrawPoly (&info_[0], static_cast<unsigned int> (info_.size ()) / 2);
120       }
121     };
122 
123    /** \brief Class for storing Points
124      */
125     struct FPoints2D : public Figure2D
126     {
127 
FPoints2DFPoints2D128       FPoints2D (std::vector<float> info, vtkPen *p, vtkBrush * b, vtkTransform2D *t) : Figure2D (info, p, b, t) {}
129 
drawFPoints2D130       void draw (vtkContext2D * painter) override
131       {
132         applyInternals(painter);
133         painter->DrawPoints (&info_[0], static_cast<unsigned int> (info_.size ()) / 2);
134       }
135     };
136 
137    /** \brief Class for storing Quads
138      */
139     struct FQuad2D : public Figure2D
140     {
141 
FQuad2DFQuad2D142       FQuad2D (std::vector<float> info, vtkPen *p, vtkBrush * b, vtkTransform2D *t) : Figure2D (info, p, b, t) {}
143 
drawFQuad2D144       void draw (vtkContext2D * painter) override
145       {
146         applyInternals(painter);
147         painter->DrawQuad (&info_[0]);
148       }
149     };
150 
151     /** \brief Class for Polygon
152      */
153     struct FPolygon2D : public Figure2D
154     {
155 
FPolygon2DFPolygon2D156       FPolygon2D (std::vector<float> info, vtkPen *p, vtkBrush * b, vtkTransform2D *t) : Figure2D (info, p, b, t){}
157 
drawFPolygon2D158       void draw (vtkContext2D * painter) override
159       {
160         applyInternals(painter);
161         painter->DrawPolygon (&info_[0], static_cast<unsigned int> (info_.size ()) / 2);
162       }
163     };
164 
165    /** \brief Class for storing EllipticArc; every ellipse , circle are covered by this
166      */
167     struct FEllipticArc2D : public Figure2D
168     {
169 
FEllipticArc2DFEllipticArc2D170       FEllipticArc2D (std::vector<float> info, vtkPen *p, vtkBrush * b, vtkTransform2D *t) : Figure2D (info, p, b, t) {}
171 
FEllipticArc2DFEllipticArc2D172       FEllipticArc2D (float x, float y, float rx, float ry, float sa, float ea, vtkPen *p, vtkBrush * b, vtkTransform2D *t) : Figure2D (p, b, t)
173       {
174         info_.resize (6);
175         info_[0] = x;
176         info_[1] = y;
177         info_[2] = rx;
178         info_[3] = ry;
179         info_[4] = sa;
180         info_[5] = ea;
181       }
182 
drawFEllipticArc2D183       void draw (vtkContext2D * painter) override
184       {
185         applyInternals(painter);
186         painter->DrawEllipticArc (info_[0], info_[1], info_[2], info_[3], info_[4], info_[5]);
187       }
188     };
189 
190 
191     ////////////////////////////////////The Main Painter Class begins here//////////////////////////////////////
192     /** \brief PCL Painter2D main class. Class for drawing 2D figures
193      * \author Kripasindhu Sarkar
194      * \ingroup visualization
195      */
196     class PCL_EXPORTS PCLPainter2D: public vtkContextItem
197     {
198     public:
199 
200       //static PCLPainter2D *New();
201 
202       /** \brief Constructor of the class
203        */
204       PCLPainter2D (char const * name = "PCLPainter2D");
205       vtkTypeMacro (PCLPainter2D, vtkContextItem);
206 
207       /** \brief Paint event for the chart, called whenever the chart needs to be drawn
208        *  \param[in] painter Name of the window
209        */
210       bool
211       Paint (vtkContext2D *painter) override;
212 
213       /** \brief Draw a line between the specified points.
214        * \param[in] x1 X coordinate of the starting point of the line
215        * \param[in] y1 Y coordinate of the starting point of the line
216        * \param[in] x2 X coordinate of the ending point of the line
217        * \param[in] y2 Y coordinate of the ending point of the line
218        */
219       void
220       addLine (float x1, float y1, float x2, float y2);
221 
222       /** \brief Draw line(s) between the specified points
223        *  \param[in] p a vector of size 2*n and the points are packed x1, y1, x2, y2 etc.
224        */
225       void
226       addLine (std::vector<float> p);
227 
228 
229       /** \brief Draw specified point(s).
230        * \param[in] x X coordinate of the point
231        * \param[in] y Y coordinate of the point
232        */
233       void
234       addPoint (float x, float y);
235       /** \brief Draw specified point(s).
236        * \param[in] points a vector of size 2*n and the points are packed x1, y1, x2, y2 etc.
237        */
238 
239       void
240       addPoints (std::vector<float> points);
241 
242 
243       /** \brief Draw a rectangle based on the given points
244        * \param[in] x X coordinate of the origin
245        * \param[in] y Y coordinate of the origin
246        * \param[in] width width of the rectangle
247        * \param[in] height height of the rectangle
248        */
249       void
250       addRect (float x, float y, float width, float height);
251 
252       /** \brief Draw a quadrilateral based on the given points
253        * \param[in] p a vector of size 8 and the points are packed x1, y1, x2, y2, x3, y3 and x4, y4.
254        */
255       void
256       addQuad (std::vector<float> p);
257 
258         /** \brief Draw a polygon between the specified points
259        *  \param[in] p a vector of size 2*n and the points are packed x1, y1, x2, y2 etc.
260        */
261       void
262       addPolygon (std::vector<float> p);
263 
264 
265       /** \brief Draw an ellipse based on the inputs
266        * \param[in] x X coordinate of the origin
267        * \param[in] y Y coordinate of the origin
268        * \param[in] rx X radius of the ellipse
269        * \param[in] ry Y radius of the ellipse
270        */
271       void
272       addEllipse (float x, float y, float rx, float ry);
273 
274       /** \brief Draw a circle based on the inputs
275        * \param[in] x X coordinate of the origin
276        * \param[in] y Y coordinate of the origin
277        * \param[in] r radius of the circle
278        */
279       void
280       addCircle (float x, float y, float r);
281 
282       /** \brief Draw an elliptic arc based on the inputs
283        * \param[in] x X coordinate of the origin
284        * \param[in] y Y coordinate of the origin
285        * \param[in] rx X radius of the ellipse
286        * \param[in] ry Y radius of the ellipse
287        * \param[in] start_angle the starting angle of the arc expressed in degrees
288        * \param[in] end_angle the ending angle of the arc expressed in degrees
289        */
290       void
291       addEllipticArc (float x, float y, float rx, float ry, float start_angle, float end_angle);
292 
293       /** \brief Draw an arc based on the inputs
294        * \param[in] x X coordinate of the origin
295        * \param[in] y Y coordinate of the origin
296        * \param[in] r radius of the circle
297        * \param[in] start_angle the starting angle of the arc expressed in degrees
298        * \param[in] end_angle the ending angle of the arc expressed in degrees
299        */
300       void
301       addArc (float x, float y, float r, float start_angle, float end_angle);
302 
303 
304       /** \brief Create a translation matrix and concatenate it with the current transformation.
305        * \param[in] x translation along X axis
306        * \param[in] y translation along Y axis
307        */
308       void
309       translatePen (double x, double y);
310 
311       /** \brief Create a rotation matrix and concatenate it with the current transformation.
312        * \param[in] angle angle in degrees
313        */
314       void
315       rotatePen(double angle);
316 
317       /** \brief Create a scale matrix and concatenate it with the current transformation.
318        * \param[in] x translation along X axis
319        * \param[in] y translation along Y axis
320        */
321       void
322       scalePen(double x, double y);
323 
324       /** \brief Create a translation matrix and concatenate it with the current transformation.
325        * \param[in] matrix the transformation matrix
326        */
327       void
328       setTransform(vtkMatrix3x3 *matrix);
329 
330       /** \brief Returns the current transformation matrix.
331        */
332       vtkMatrix3x3 *
333       getTransform();
334 
335       /** \brief Clears all the transformation applied. Sets the transformation matrix to Identity
336        */
337       void
338       clearTransform();
339 
340       /** \brief remove all the figures from the window
341        */
342        void
343        clearFigures();
344 
345       /** \brief set/get methods for current working vtkPen
346        */
347       void setPenColor (unsigned char r, unsigned char g, unsigned char b, unsigned char a);
348       void setPenWidth (float w);
349       void setPenType (int type);
350 
351       /** \brief set/get methods for current working vtkPen
352        */
353       unsigned char* getPenColor ();
354       float getPenWidth ();
355       int getPenType ();
356       void setPen (vtkPen *pen);
357       vtkPen* getPen ();
358 
359       /** \brief set/get methods for current working vtkBrush
360        */
361       void setBrush (vtkBrush *brush);
362       vtkBrush* getBrush ();
363       void setBrushColor (unsigned char r, unsigned char g, unsigned char b, unsigned char a);
364       unsigned char* getBrushColor ();
365 
366       /** \brief set/get method for the viewport's background color.
367        * \param[in] r the red component of the RGB color
368        * \param[in] g the green component of the RGB color
369        * \param[in] b the blue component of the RGB color
370        */
371       void
372       setBackgroundColor (const double r, const double g, const double b);
373 
374       /** \brief set/get method for the viewport's background color.
375        * \param [in] color the array containing the 3 component of the RGB color
376        */
377       void
378       setBackgroundColor (const double color[3]);
379 
380       /** \brief set/get method for the viewport's background color.
381        * \return [out] color the array containing the 3 component of the RGB color
382        */
383       double *
384       getBackgroundColor ();
385 
386 
387       /** \brief set/get method for the window size.
388        * \param[in] w the width of the window
389        * \param[in] h the height of the window
390        */
391       void
392       setWindowSize (int w, int h);
393 
394       /** \brief set/get method for the window size.
395        * \return[in] array containing the width and height of the window
396        */
397       int *
398       getWindowSize () const;
399 
400       /** \brief displays all the figures added in a window.
401        */
402       void display ();
403 
404       /** \brief spins (runs the event loop) the interactor for spin_time amount of time. The name is confusing and will be probably obsolete in the future release with a single overloaded spin()/display() function.
405         *  \param[in] spin_time - How long (in ms) should the visualization loop be allowed to run.
406         */
407       void spinOnce ( const int spin_time = 0 );
408 
409       /** \brief spins (runs the event loop) the interactor indefinitely. Same as display() - added to retain the similarity between other existing visualization classes
410        */
411       void spin ();
412 
413     private:
414       //std::map< int, std::vector< std::vector<float> > > figures_; //FIG_TYPE -> std::vector<array>
415 
416       //All the figures drawn till now gets stored here
417       std::vector<Figure2D *> figures_;
418 
419       //state variables of the class
420       vtkPen *current_pen_;
421       vtkBrush *current_brush_;
422       vtkTransform2D *current_transform_;
423       int win_width_, win_height_;
424       double bkg_color_[3];
425 
426       vtkContextView *view_;
427 
428       //####event callback class####
429         struct ExitMainLoopTimerCallback : public vtkCommand
430         {
NewExitMainLoopTimerCallback431           static ExitMainLoopTimerCallback* New ()
432           {
433             return (new ExitMainLoopTimerCallback);
434           }
435           void
ExecuteExitMainLoopTimerCallback436           Execute (vtkObject* vtkNotUsed (caller), unsigned long event_id, void* call_data) override
437           {
438             if (event_id != vtkCommand::TimerEvent)
439               return;
440             int timer_id = *(reinterpret_cast<int*> (call_data));
441 
442             if (timer_id != right_timer_id)
443               return;
444 
445             // Stop vtk loop and send notification to app to wake it up
446             interactor->TerminateApp ();
447           }
448           int right_timer_id;
449           vtkRenderWindowInteractor *interactor;
450         };
451 
452         /** \brief Callback object enabling us to leave the main loop, when a timer fires. */
453         vtkSmartPointer<ExitMainLoopTimerCallback> exit_loop_timer_;
454     };
455 
456   }
457 }
458