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