1 /// 2 /// Copyright (c) 2012, Texas A&M University 3 /// All rights reserved. 4 /// 5 /// Redistribution and use in source and binary forms, with or without 6 /// modification, are permitted provided that the following conditions 7 /// are met: 8 /// 9 /// * Redistributions of source code must retain the above copyright 10 /// notice, this list of conditions and the following disclaimer. 11 /// * Redistributions in binary form must reproduce the above 12 /// copyright notice, this list of conditions and the following 13 /// disclaimer in the documentation and/or other materials provided 14 /// with the distribution. 15 /// * Neither the name of Texas A&M University nor the names of its 16 /// contributors may be used to endorse or promote products derived 17 /// from this software without specific prior written permission. 18 /// 19 /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 /// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 /// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 /// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 /// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 /// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 /// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 /// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 /// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29 /// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 /// POSSIBILITY OF SUCH DAMAGE. 31 /// 32 /// The following software was written as part of a collaboration with the 33 /// University of South Carolina, Interdisciplinary Mathematics Institute. 34 /// 35 /// @file cloud.h 36 /// @details The declaration of the class representing the cloud data structure. 37 /// A cloud represents a single 3D set of points and associated attributes. 38 /// This class allows for the basic manipulation of the cloud as well as its 39 /// display. 40 /// @author Yue Li and Matthew Hielsberg 41 42 #pragma once 43 44 #include <QtGui/QColor> 45 #include <pcl/apps/point_cloud_editor/localTypes.h> 46 #include <pcl/apps/point_cloud_editor/statistics.h> 47 48 #include <pcl/memory.h> // for pcl::weak_ptr 49 50 #ifdef OPENGL_IS_A_FRAMEWORK 51 # include <OpenGL/gl.h> 52 # include <OpenGL/glu.h> 53 #else 54 #ifdef _WIN32 55 // Need this to pull in APIENTRY, etc. 56 #include "windows.h" 57 #endif 58 # include <GL/gl.h> 59 # include <GL/glu.h> 60 #endif 61 62 /// @brief A wrapper which allows to use any implementation of cloud provided by 63 /// a third-party library. 64 /// @details This wrapper attempts to create a simple interface for displaying 65 /// and modifying point clouds. It is common for point clouds to have 66 /// coordinate values that are exceptionally large, especially when dealing 67 /// with the GIS community. As such this class shifts the stored point cloud 68 /// according to the minimum in each of the coordinate directions. The 69 /// interface presented by this class then serves the shifted points in order to 70 /// reduce any precision errors that may occur due to sums of large values. 71 /// Functions also exist for accessing the unshifted versions of the points, 72 /// however most operations performed on the cloud will expect it to live near 73 /// the origin. 74 // XXX - handle shifting upon setting of a Cloud3D 75 // XXX - add functions for retrieving an unshifted Cloud3D 76 // XXX - add functions for retrieving unshifted points by index 77 // XXX - mark access functions below as returning shifted values 78 class Cloud : public Statistics 79 { 80 public: 81 /// The type for shared pointer pointing to a selection buffer 82 using SelectionPtr = pcl::shared_ptr<Selection>; 83 84 /// The type for weak pointer pointing to a selection buffer 85 using SelectionWeakPtr = pcl::weak_ptr<Selection>; 86 87 /// @brief Default Constructor 88 Cloud (); 89 90 /// @brief Copy Constructor 91 /// @details This constructor creates a copy of the passed cloud. The 92 /// values of the member variables of the passed cloud are deep copied. 93 /// @param copy The cloud object to be used to initialize this cloud object. 94 Cloud (const Cloud& copy); 95 96 /// @brief Construct a cloud from a Cloud3D. 97 /// @details This constructor creates a cloud object with the passed 98 /// cloud object stored with the internal representation. The member 99 /// variables of this object are initialized but not set. 100 Cloud (const Cloud3D& cloud, bool register_stats=false); 101 102 /// @brief Equal Operator 103 /// @details Deep copies all the state of the passed cloud to this cloud. 104 /// @param cloud The cloud object whose status to be copied to this object 105 /// @return A reference to this cloud containing the new values. 106 Cloud& 107 operator= (const Cloud& cloud); 108 109 /// @brief Subscript Operator 110 /// @details This operator returns a reference to the point with the 111 /// passed index in this cloud object. 112 /// @pre The index passed is expected to be within the limits of the cloud. 113 /// For debugging this is currently checked by an assert. 114 /// @param index The index of the point to be returned. 115 /// @return A reference to the indexed point. 116 Point3D& 117 operator[] (unsigned int index); 118 119 /// @brief Subscript Operator 120 /// @details This operator returns a const reference to the point with the 121 /// passed index in this cloud object. 122 /// @pre The index passed is expected to be within the limits of the cloud. 123 /// For debugging this is currently checked by an assert. 124 /// @param index The index of the point to be returned. 125 /// @return A const reference to the indexed point. 126 const Point3D& 127 operator[] (unsigned int index) const; 128 129 /// @brief Returns the center of the point cloud 130 /// @param x The x coordinate of the center (computed as the average point). 131 /// @param y The y coordinate of the center (computed as the average point). 132 /// @param z The z coordinate of the center (computed as the average point). 133 inline 134 void getCenter(float & x,float & y,float & z)135 getCenter (float &x, float &y, float &z) const 136 { 137 x = center_xyz_[X]; y = center_xyz_[Y]; z = center_xyz_[Z]; 138 } 139 140 /// @brief Returns the scaling factor for the point cloud 141 /// @return The scaling factor 142 inline 143 float getScalingFactor()144 getScalingFactor() const 145 { 146 return (display_scale_); 147 } 148 149 /// @brief Gets the transform matrix. 150 /// @details The returned matrix is used to transform the cloud for 151 /// rendering only and does not affect the values of the points stored. 152 /// @return A 1-D array representing (4 x 4) matrix in 153 /// using OpenGL's column-major format. 154 inline 155 const float* getMatrix()156 getMatrix () const 157 { 158 return (cloud_matrix_); 159 } 160 161 /// @brief Sets the transform matrix for the cloud. 162 /// @details The passed matrix is used to transform the cloud for 163 /// rendering only and does not affect the values of the points stored. 164 /// @pre The passed pointer represents a matrix having valid memory of at 165 /// least MATRIX_SIZE elements. 166 /// @param matrix a 1-D array representing (4 x 4) matrix in 167 /// using OpenGL's column-major format. 168 void 169 loadMatrix (const float* matrix); 170 171 /// @brief Right multiplies the cloud matrix with the passed matrix 172 /// @details The application of this matrix effectively transforms the 173 /// cloud from its current state. The passed matrix is used for display 174 /// only and does not affect the values of the points stored. 175 /// @pre The passed pointer represents a matrix having valid memory of at 176 /// least MATRIX_SIZE elements. 177 /// @param matrix a 1-D array representing (4 x 4) matrix in 178 /// using OpenGL's column-major format. 179 void 180 multMatrix (const float* matrix); 181 182 /// @brief Sets the selection transform matrix to the one passed. 183 /// @details The selection matrix represents the local transformations 184 /// applied to the selected points. The matrix is used relative to the 185 /// cloud's state after the application of its own matrices which can be 186 /// modified by loadMatrix and multMatrix functions. 187 /// @pre The passed pointer represents a matrix having valid memory of at 188 /// least MATRIX_SIZE elements. 189 /// @param matrix a 1-D array representing (4 x 4) matrix in 190 /// using OpenGL's column-major format. 191 /// @sa loadMatrix multMatrix 192 void 193 setSelectionRotation (const float* matrix); 194 195 void 196 setSelectionTranslation (float dx, float dy, float dz); 197 198 /// @brief Sets the selected points. 199 /// @details The cloud object is responsible for its display. As we have 200 /// tried to adopt a lazy approach in the application of modifications to 201 /// the cloud, the cloud must be notified of the selected points. This is 202 /// required as the user may move the selected points and we do not wish for 203 /// the selected points to be drawn twice, once in the user-updated position 204 /// and another in the points original location. 205 /// @pre Assumes that the selection stores the selected indices of the 206 /// points sorted. 207 /// @param A pointer pointing to a selection object. 208 /// @remarks This has been implemented using a weak pointer to allow a lazy 209 /// update to occur. When a selection is destroyed we can switch to 210 /// a faster rendering mode; this also occurs if the selection object is 211 /// empty. 212 void 213 setSelection (const SelectionPtr& selection_ptr); 214 215 /// @brief Sets the RGB values for coloring points in COLOR_BY_PURE mode. 216 /// @param r the value for red color 217 /// @param g the value for the green color 218 /// @param b the value for the blue color 219 void 220 setRGB (float r, float g, float b); 221 222 /// @brief Sets the RGB values used for highlighting the selected points. 223 /// @param r the value for red color 224 /// @param g the value for the green color 225 /// @param b the value for the blue color 226 void 227 setHighlightColor (float r, float g, float b); 228 229 /// @brief Renders the cloud and highlights any selected points. 230 /// @param disableHighlight Defaults to false. If true the selected points 231 /// will not be drawn. 232 /// @sa setColorRampAxis, setColorRamp 233 void 234 draw (bool disable_highlight = false) const; 235 236 /// @brief Renders the cloud and highlights any selected points. 237 /// @details The colors of the non-selected points come from a 1D texture 238 /// which is implemented by a color ramp. 239 void 240 drawWithTexture () const; 241 242 /// @brief Renders the cloud and highlights any selected points. 243 /// @details The colors of the non-selected points uses the native color 244 /// of the original points 245 /// @pre The cloud should be originally colored. 246 void 247 drawWithRGB () const; 248 249 /// @brief Renders the cloud and highlights any selected points. 250 /// @details The non-selected points are in a single color 251 void 252 drawWithPureColor () const; 253 254 /// @brief Renders the cloud with the color used for highlighting the 255 /// selected points. 256 void 257 drawWithHighlightColor () const; 258 259 /// @brief Sets the axis along which the displayed points should have the 260 /// color ramp applied. 261 /// @param a The axis id describing which direction the ramp should be 262 /// applied. 263 inline 264 void setColorRampAxis(Axis a)265 setColorRampAxis(Axis a) 266 { 267 color_ramp_axis_ = a; 268 } 269 270 /// @brief Enables/Disables the use of the color ramp in display. 271 /// @details The color ramp aids in the visualization of the displayed 272 /// points by varying the color according to a linear ramp along one of the 273 /// axes. 274 /// @param onOff True enables the use of the color ramp and false disables. 275 inline 276 void setColorRamp(bool on_off)277 setColorRamp(bool on_off) 278 { 279 use_color_ramp_ = on_off; 280 } 281 282 /// @brief Appends a new 3D point to the cloud. 283 /// @param point the new point to be added. 284 void 285 append (const Point3D& point); 286 287 /// @brief Appends the points of the passed cloud to this cloud. 288 /// @param cloud the cloud to be appended to this cloud. 289 void 290 append (const Cloud& cloud); 291 292 /// @brief Removes the points in selection from the cloud. 293 /// @details Each indexed point in the selection will be removed from this 294 /// container. 295 /// @pre The index of each point in the selection is expected to be within 296 /// the limits of the cloud. For debugging this is currently checked by an 297 /// assert. Also, it is expected that the selection indices are sorted. 298 /// @param selection a selection object which stores the indices of the 299 /// selected points. 300 /// @remarks This function requires the use of Selection::isSelected and its 301 /// complexity can vary based on the implementation of that function. 302 void 303 remove (const Selection& selection); 304 305 /// @brief Gets the size of the cloud 306 inline 307 unsigned int size()308 size () const 309 { 310 return (cloud_.size()); 311 } 312 313 /// @brief Sets the size of the cloud of this object to the passed new size 314 /// @details If the size is smaller than the current size, only the first 315 /// new_size points will be kept, the rest being dropped. If new_size is 316 /// larger than the current size, the new points required to fill the 317 /// extended region are created with its default constructor. 318 /// @param new_size the new size of the cloud. 319 void 320 resize (unsigned int new_size); 321 322 /// @brief Removes all points from the cloud and resets the object 323 void 324 clear (); 325 326 /// @brief Set the sizes used for rendering the unselected points. 327 /// @param size The size, in pixels, used for rendering the points. 328 void 329 setPointSize (int size); 330 331 /// @brief Set the sizes used for rendering the selected points. 332 /// @param size The size, in pixels, used for rendering the points. 333 void 334 setHighlightPointSize (int size); 335 336 /// @brief Compute the transformed coordinates of the indexed point in the 337 /// cloud according to the object transform. 338 /// @details This applies the object rotation and translation of the 339 /// indexed point according to the user transforms. 340 /// @param index The index of the point whose coordinates are 341 /// transformed. 342 /// @return The transformed point. 343 Point3D 344 getObjectSpacePoint (unsigned int index) const; 345 346 /// @brief Compute the transformed coordinates of the indexed point in the 347 /// cloud to match the display. 348 /// @details To save on computation, the points in the display are not 349 /// transformed on the cpu side, instead the gpu is allowed to manipulate 350 /// them for display. This function performs the same manipulation and 351 /// returns the transformed point. 352 /// @param index The index of the point whose coordinates are 353 /// transformed according to the display. 354 /// @return The transformed point. 355 Point3D 356 getDisplaySpacePoint (unsigned int index) const; 357 358 /// @brief Compute the transformed coordinates of the all the points in the 359 /// cloud to match the display. 360 /// @details To save on computation, the points in the display are not 361 /// transformed on the cpu side, instead the gpu is allowed to manipulate 362 /// them for display. This function performs the same manipulation and 363 /// returns the transformed points. 364 /// @param pts a vector used to store the points whose coordinates are 365 /// transformed. 366 void 367 getDisplaySpacePoints (Point3DVector& pts) const; 368 369 /// @brief Returns a const reference to the internal representation of this 370 /// object. 371 const Cloud3D& 372 getInternalCloud () const; 373 374 /// @brief Places the points in the copy buffer into the cloud according 375 /// to the indices in the selection. 376 void 377 restore (const CopyBuffer& copy_buffer, const Selection& selection); 378 379 /// @brief Get statistics of the selected points in string. 380 std::string 381 getStat () const override; 382 383 /// Default Point Size 384 static const float DEFAULT_POINT_DISPLAY_SIZE_; 385 /// Default Highlight Point Size 386 static const float DEFAULT_POINT_HIGHLIGHT_SIZE_; 387 /// Default Point Color - Red component 388 static const float DEFAULT_POINT_DISPLAY_COLOR_RED_; 389 /// Default Point Color - Green component 390 static const float DEFAULT_POINT_DISPLAY_COLOR_GREEN_; 391 /// Default Point Color - Blue component 392 static const float DEFAULT_POINT_DISPLAY_COLOR_BLUE_; 393 /// Default Point Highlight Color - Red component 394 static const float DEFAULT_POINT_HIGHLIGHT_COLOR_RED_; 395 /// Default Point Highlight Color - Green component 396 static const float DEFAULT_POINT_HIGHLIGHT_COLOR_GREEN_; 397 /// Default Point Highlight Color - Blue component 398 static const float DEFAULT_POINT_HIGHLIGHT_COLOR_BLUE_; 399 400 private: 401 /// @brief Computes the point cloud related members. 402 /// @details The cloud keeps track of certain values related to the points 403 /// in the cloud. These include the minimum coordinates and the ranges in 404 /// the coordinate directions. 405 /// @pre Assumes that there is at least one dimension of the point cloud 406 /// that has non-zero range. 407 void 408 updateCloudMembers (); 409 410 /// @brief Enable the texture used for rendering the cloud 411 void 412 enableTexture () const; 413 414 /// @brief Disable the texture used for rendering the cloud 415 void 416 disableTexture() const; 417 418 /// The internal representation of the cloud 419 Cloud3D cloud_; 420 421 /// @brief A weak pointer pointing to the selection object. 422 /// @details This implementation uses the weak pointer to allow for a lazy 423 /// update of the cloud if the selection object is destroyed. 424 SelectionWeakPtr selection_wk_ptr_; 425 426 /// Flag that indicates whether a color ramp should be used (true) or not 427 /// (false) when displaying the cloud 428 bool use_color_ramp_; 429 430 /// The axis which the color ramp is to be applied when drawing the cloud 431 Axis color_ramp_axis_; 432 433 /// A scale value used to normalize the display of clouds. This is simply 434 /// one over the maximum of the range in each coordinate direction 435 float display_scale_; 436 437 /// The center coordinate values in the point cloud. This is used for 438 /// display. 439 float center_xyz_[XYZ_SIZE]; 440 441 /// The minimum coordinate values in the point cloud. This is used for 442 /// display. 443 float min_xyz_[XYZ_SIZE]; 444 445 /// The maximum coordinate values in the point cloud. This is used for 446 /// display. 447 float max_xyz_[XYZ_SIZE]; 448 449 /// A (4x4) OpenGL transform matrix for rendering the cloud 450 float cloud_matrix_[MATRIX_SIZE]; 451 452 /// A (4x4) OpenGL transform matrix specifying the relative transformations 453 /// that are applied to the selected points in the cloud when drawing them 454 /// as highlighted. 455 float select_matrix_[MATRIX_SIZE]; 456 457 /// A vector of indices for every point in the cloud. This vector is used 458 /// when a selection is set and sorted such that the selected indices 459 /// appear first in the vector. This is used during display to allow for 460 /// separate indexed drawing of the selection and the point cloud. Note 461 /// that this vector is partitioned according to selected and not-selected. 462 IndexVector partitioned_indices_; 463 464 /// The size used for rendering the unselected points in the cloud 465 float point_size_; 466 467 /// The size used for rendering the selected points in the cloud 468 float selected_point_size_; 469 470 /// The R, G, B values used for coloring each points when the current 471 /// color scheme is COLOR_BY_PURE. 472 float color_[RGB]; 473 474 /// The R, G, B values used for highlighting the selected points. 475 float highlight_color_[RGB]; 476 477 /// The translations on x, y, and z axis on the selected points. 478 float select_translate_x_, select_translate_y_, select_translate_z_; 479 }; 480