00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00039
00040 #include <algorithm>
00041
00042
00043 #include <GL/gl.h>
00044 #include <GL/glu.h>
00045 #include <pcl/apps/point_cloud_editor/cloud.h>
00046 #include <pcl/apps/point_cloud_editor/selection.h>
00047 #include <pcl/apps/point_cloud_editor/localTypes.h>
00048 #include <pcl/apps/point_cloud_editor/common.h>
00049 #include <pcl/apps/point_cloud_editor/copyBuffer.h>
00050
00051 const float Cloud::DEFAULT_POINT_DISPLAY_SIZE_ = 2.0f;
00052 const float Cloud::DEFAULT_POINT_HIGHLIGHT_SIZE_ = 4.0f;
00053
00054 const float Cloud::DEFAULT_POINT_DISPLAY_COLOR_RED_ = 1.0f;
00055 const float Cloud::DEFAULT_POINT_DISPLAY_COLOR_GREEN_ = 1.0f;
00056 const float Cloud::DEFAULT_POINT_DISPLAY_COLOR_BLUE_ = 1.0f;
00057
00058 const float Cloud::DEFAULT_POINT_HIGHLIGHT_COLOR_RED_ = 0.0f;
00059 const float Cloud::DEFAULT_POINT_HIGHLIGHT_COLOR_GREEN_ = 1.0f;
00060 const float Cloud::DEFAULT_POINT_HIGHLIGHT_COLOR_BLUE_ = 0.0f;
00061
00062
00063 Cloud::Cloud ()
00064 : use_color_ramp_(true), color_ramp_axis_(Y),
00065 display_scale_(1.0f),
00066 point_size_(DEFAULT_POINT_DISPLAY_SIZE_),
00067 selected_point_size_(DEFAULT_POINT_HIGHLIGHT_SIZE_),
00068 select_translate_x_(0), select_translate_y_(0), select_translate_z_(0)
00069 {
00070 std::fill_n(center_xyz_, XYZ_SIZE, 0.0f);
00071 setIdentity(cloud_matrix_);
00072 setIdentity(select_matrix_);
00073 color_[RED] = DEFAULT_POINT_DISPLAY_COLOR_RED_;
00074 color_[GREEN] = DEFAULT_POINT_DISPLAY_COLOR_GREEN_;
00075 color_[BLUE] = DEFAULT_POINT_DISPLAY_COLOR_BLUE_;
00076 highlight_color_[RED] = DEFAULT_POINT_HIGHLIGHT_COLOR_RED_;
00077 highlight_color_[GREEN] = DEFAULT_POINT_HIGHLIGHT_COLOR_GREEN_;
00078 highlight_color_[BLUE] = DEFAULT_POINT_HIGHLIGHT_COLOR_BLUE_;
00079 }
00080
00081 Cloud::Cloud (const Cloud3D &cloud, bool register_stats)
00082 : cloud_(cloud),
00083 use_color_ramp_(true), color_ramp_axis_(Y),
00084 display_scale_(1.0f),
00085 point_size_(DEFAULT_POINT_DISPLAY_SIZE_),
00086 selected_point_size_(DEFAULT_POINT_HIGHLIGHT_SIZE_),
00087 select_translate_x_(0), select_translate_y_(0), select_translate_z_(0)
00088 {
00089 std::fill_n(center_xyz_, XYZ_SIZE, 0.0f);
00090 setIdentity(cloud_matrix_);
00091 setIdentity(select_matrix_);
00092 color_[RED] = DEFAULT_POINT_DISPLAY_COLOR_RED_;
00093 color_[GREEN] = DEFAULT_POINT_DISPLAY_COLOR_GREEN_;
00094 color_[BLUE] = DEFAULT_POINT_DISPLAY_COLOR_BLUE_;
00095 highlight_color_[RED] = DEFAULT_POINT_HIGHLIGHT_COLOR_RED_;
00096 highlight_color_[GREEN] = DEFAULT_POINT_HIGHLIGHT_COLOR_GREEN_;
00097 highlight_color_[BLUE] = DEFAULT_POINT_HIGHLIGHT_COLOR_BLUE_;
00098 updateCloudMembers();
00099 if (register_stats)
00100 registerStats();
00101 }
00102
00103 Cloud::Cloud (const Cloud ©)
00104 : cloud_(copy.cloud_), selection_wk_ptr_(copy.selection_wk_ptr_),
00105 use_color_ramp_(copy.use_color_ramp_),
00106 color_ramp_axis_(copy.color_ramp_axis_),
00107 display_scale_(copy.display_scale_),
00108 point_size_(copy.point_size_),
00109 selected_point_size_(copy.selected_point_size_),
00110 select_translate_x_(copy.select_translate_x_),
00111 select_translate_y_(copy.select_translate_y_),
00112 select_translate_z_(copy.select_translate_z_),
00113 partitioned_indices_(copy.partitioned_indices_)
00114 {
00115 std::copy(copy.center_xyz_, copy.center_xyz_+XYZ_SIZE, center_xyz_);
00116 std::copy(copy.cloud_matrix_, copy.cloud_matrix_+MATRIX_SIZE, cloud_matrix_);
00117 std::copy(copy.select_matrix_, copy.select_matrix_+MATRIX_SIZE,
00118 select_matrix_);
00119 std::copy(copy.color_, copy.color_+RGB, color_);
00120 std::copy(copy.highlight_color_, copy.highlight_color_+RGB, highlight_color_);
00121 }
00122
00123 Cloud::~Cloud () {}
00124
00125 Cloud&
00126 Cloud::operator= (const Cloud &cloud)
00127 {
00128 cloud_ = cloud.cloud_;
00129 selection_wk_ptr_ = cloud.selection_wk_ptr_;
00130 use_color_ramp_ = cloud.use_color_ramp_;
00131 color_ramp_axis_ = cloud.color_ramp_axis_;
00132 display_scale_ = cloud.display_scale_;
00133 point_size_ = cloud.point_size_;
00134 selected_point_size_ = cloud.selected_point_size_;
00135 std::copy(cloud.center_xyz_, cloud.center_xyz_+XYZ_SIZE, center_xyz_);
00136 std::copy(cloud.cloud_matrix_, cloud.cloud_matrix_+MATRIX_SIZE,
00137 cloud_matrix_);
00138 std::copy(cloud.select_matrix_, cloud.select_matrix_+MATRIX_SIZE,
00139 select_matrix_);
00140 partitioned_indices_ = cloud.partitioned_indices_;
00141 std::copy(cloud.color_, cloud.color_+RGB, color_);
00142 std::copy(cloud.highlight_color_,cloud.highlight_color_+RGB,highlight_color_);
00143 select_translate_x_ = cloud.select_translate_x_;
00144 select_translate_y_ = cloud.select_translate_y_;
00145 select_translate_z_ = cloud.select_translate_z_;
00146 return (*this);
00147 }
00148
00149 Point3D&
00150 Cloud::operator[] (unsigned int index)
00151 {
00152 assert(index < cloud_.size());
00153 return (cloud_[index]);
00154 }
00155
00156 const Point3D&
00157 Cloud::operator[] (unsigned int index) const
00158 {
00159 assert(index < cloud_.size());
00160 return (cloud_[index]);
00161 }
00162
00163 void
00164 Cloud::loadMatrix (const float *matrix)
00165 {
00166 std::copy(matrix, matrix+MATRIX_SIZE, cloud_matrix_);
00167 }
00168
00169 void
00170 Cloud::multMatrix (const float *matrix)
00171 {
00172 ::multMatrix(cloud_matrix_, matrix, cloud_matrix_);
00173 }
00174
00175 void
00176 Cloud::setSelectionRotation (const float* matrix)
00177 {
00178 std::copy(matrix, matrix+MATRIX_SIZE, select_matrix_);
00179 }
00180
00181 void
00182 Cloud::setSelectionTranslation (float dx, float dy, float dz)
00183 {
00184 select_translate_x_ = dx;
00185 select_translate_y_ = dy;
00186 select_translate_z_ = dz;
00187 }
00188
00189 void
00190 Cloud::setSelection (SelectionPtr selection_ptr)
00191 {
00192 selection_wk_ptr_ = selection_ptr;
00193 if (!selection_ptr || selection_ptr->empty())
00194 return;
00195 IncIndex inc;
00196 partitioned_indices_.resize(cloud_.size());
00197 std::generate(partitioned_indices_.begin(), partitioned_indices_.end(), inc);
00198 unsigned int pos = 0;
00199 Selection::const_iterator it;
00200
00201 for (it = selection_ptr->begin(); it != selection_ptr->end(); ++it, ++pos)
00202 {
00203 std::swap(partitioned_indices_[pos], partitioned_indices_[*it]);
00204 }
00205 }
00206
00207 void
00208 Cloud::setRGB (float r, float g, float b)
00209 {
00210 color_[RED] = r;
00211 color_[GREEN] = g;
00212 color_[BLUE] = b;
00213 }
00214
00215 void
00216 Cloud::setHighlightColor (float r, float g, float b)
00217 {
00218 highlight_color_[RED] = r;
00219 highlight_color_[GREEN] = g;
00220 highlight_color_[BLUE] = b;
00221 }
00222
00223 void
00224 Cloud::drawWithTexture () const
00225 {
00226 enableTexture();
00227 draw();
00228 disableTexture();
00229 }
00230
00231 void
00232 Cloud::drawWithRGB () const
00233 {
00234 glEnableClientState(GL_COLOR_ARRAY);
00235 glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(Point3D),
00236 &(cloud_.points[0].b));
00237 draw();
00238 }
00239
00240 void
00241 Cloud::drawWithPureColor () const
00242 {
00243 glDisableClientState(GL_COLOR_ARRAY);
00244 glColor3fv(color_);
00245 draw();
00246 }
00247
00248 void
00249 Cloud::drawWithHighlightColor () const
00250 {
00251 glDisableClientState(GL_COLOR_ARRAY);
00252 glDisable(GL_TEXTURE_1D);
00253 glColor3fv(highlight_color_);
00254 draw();
00255 }
00256
00257 void
00258 Cloud::draw (bool disable_highlight) const
00259 {
00260 SelectionPtr selection_ptr;
00261 try
00262 {
00263 selection_ptr = selection_wk_ptr_.lock();
00264 }
00265 catch (boost::bad_weak_ptr)
00266 {
00267 selection_ptr.reset();
00268 }
00269 glPushAttrib(GL_CURRENT_BIT | GL_POINT_BIT | GL_COLOR_BUFFER_BIT);
00270 {
00271 glPointSize(point_size_);
00272 glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
00273 {
00274 glPushMatrix();
00275 {
00276 glLoadIdentity();
00277 glTranslatef(0.0f, 0.0f, DISPLAY_Z_TRANSLATION);
00278 glScalef(display_scale_, display_scale_, display_scale_);
00279 glMultMatrixf(cloud_matrix_);
00280 glTranslatef(-center_xyz_[0], -center_xyz_[1], -center_xyz_[2]);
00281
00282 glEnableClientState(GL_VERTEX_ARRAY);
00283 glVertexPointer(3, GL_FLOAT, sizeof(Point3D), &(cloud_.points[0].x));
00284
00285 if (disable_highlight || (!selection_ptr) || selection_ptr->empty())
00286 {
00287
00288 glDrawArrays(GL_POINTS, 0, cloud_.size());
00289 }
00290 else
00291 {
00292
00293 glDrawElements(GL_POINTS, cloud_.size()-selection_ptr->size(),
00294 GL_UNSIGNED_INT,
00295 (&(partitioned_indices_[selection_ptr->size()-1]))+1);
00296
00297
00298 glLoadIdentity();
00299 glTranslatef(0.0f, 0.0f, DISPLAY_Z_TRANSLATION);
00300 glScalef(display_scale_, display_scale_, display_scale_);
00301 glTranslatef(select_translate_x_,
00302 select_translate_y_, select_translate_z_);
00303 glMultMatrixf(select_matrix_);
00304 glMultMatrixf(cloud_matrix_);
00305 glTranslatef(-center_xyz_[0], -center_xyz_[1], -center_xyz_[2]);
00306
00307
00308
00309 glDisable(GL_TEXTURE_1D);
00310 glDisableClientState(GL_COLOR_ARRAY);
00311 glColor3fv(highlight_color_);
00312 glPointSize(selected_point_size_);
00313 glBlendFunc( GL_SRC_ALPHA, GL_ZERO );
00314
00315
00316 glDrawElements(GL_POINTS, selection_ptr->size(), GL_UNSIGNED_INT,
00317 &(partitioned_indices_[0]));
00318 }
00319 }
00320 glPopMatrix();
00321 }
00322 glPopClientAttrib();
00323 }
00324 glPopAttrib();
00325 }
00326
00327 void
00328 Cloud::append (const Point3D &pt)
00329 {
00330 cloud_.push_back(pt);
00331 }
00332
00333 void
00334 Cloud::append (const Cloud & cloud)
00335 {
00336 cloud_ += cloud.cloud_;
00337 }
00338
00339 void
00340 Cloud::remove(const Selection& selection)
00341 {
00342 unsigned int pos = cloud_.size();
00343 Selection::const_reverse_iterator rit;
00344 for (rit = selection.rbegin(); rit != selection.rend(); ++rit)
00345 std::swap(cloud_.points[--pos], cloud_.points[*rit]);
00346 resize(cloud_.size()-selection.size());
00347 }
00348
00349 void
00350 Cloud::resize(unsigned int new_size)
00351 {
00352 cloud_.resize(new_size);
00353 cloud_.width = new_size;
00354 cloud_.height = 1;
00355 }
00356
00357 void
00358 Cloud::clear ()
00359 {
00360 cloud_.clear();
00361 }
00362
00363 void
00364 Cloud::setPointSize (int size)
00365 {
00366 point_size_ = size;
00367 }
00368
00369 void
00370 Cloud::setHighlightPointSize (int size)
00371 {
00372 selected_point_size_ = size;
00373 }
00374
00375 Point3D
00376 Cloud::getObjectSpacePoint (unsigned int index) const
00377 {
00378 Point3D pt = cloud_[index];
00379 float x, y, z;
00380 pt.x -= center_xyz_[0];
00381 pt.y -= center_xyz_[1];
00382 pt.z -= center_xyz_[2];
00383 x = cloud_matrix_[0] * pt.x +
00384 cloud_matrix_[4] * pt.y +
00385 cloud_matrix_[8] * pt.z +
00386 cloud_matrix_[12];
00387 y = cloud_matrix_[1] * pt.x +
00388 cloud_matrix_[5] * pt.y +
00389 cloud_matrix_[9] * pt.z +
00390 cloud_matrix_[13];
00391 z = cloud_matrix_[2] * pt.x +
00392 cloud_matrix_[6] * pt.y +
00393 cloud_matrix_[10] * pt.z +
00394 cloud_matrix_[14];
00395 pt.x = x;
00396 pt.y = y;
00397 pt.z = z;
00398
00399 return (pt);
00400 }
00401
00402 Point3D
00403 Cloud::getDisplaySpacePoint (unsigned int index) const
00404 {
00405 Point3D pt = cloud_[index];
00406 float x, y, z;
00407 pt.x -= center_xyz_[0];
00408 pt.y -= center_xyz_[1];
00409 pt.z -= center_xyz_[2];
00410 x = cloud_matrix_[0] * pt.x +
00411 cloud_matrix_[4] * pt.y +
00412 cloud_matrix_[8] * pt.z +
00413 cloud_matrix_[12];
00414 y = cloud_matrix_[1] * pt.x +
00415 cloud_matrix_[5] * pt.y +
00416 cloud_matrix_[9] * pt.z +
00417 cloud_matrix_[13];
00418 z = cloud_matrix_[2] * pt.x +
00419 cloud_matrix_[6] * pt.y +
00420 cloud_matrix_[10] * pt.z +
00421 cloud_matrix_[14];
00422 pt.x = x * display_scale_;
00423 pt.y = y * display_scale_;
00424 pt.z = z * display_scale_;
00425 pt.z += DISPLAY_Z_TRANSLATION;
00426
00427 return (pt);
00428 }
00429
00430 void
00431 Cloud::getDisplaySpacePoints (std::vector<Point3D>& pts) const
00432 {
00433 for(unsigned int i = 0; i < cloud_.size(); ++i)
00434 pts.push_back(getDisplaySpacePoint(i));
00435 }
00436
00437 const Cloud3D&
00438 Cloud::getInternalCloud () const
00439 {
00440 return (cloud_);
00441 }
00442
00443 void
00444 Cloud::restore (const CopyBuffer& copy_buffer, const Selection& selection)
00445 {
00446
00447 if (selection.empty())
00448 return;
00449 const Cloud& copied_cloud = copy_buffer.get();
00450 if (copied_cloud.size() != selection.size())
00451 return;
00452
00453 append(copied_cloud);
00454 unsigned int pos = cloud_.size();
00455 Selection::const_reverse_iterator rit;
00456 for (rit = selection.rbegin(); rit != selection.rend(); ++rit)
00457 std::swap(cloud_.points[--pos], cloud_.points[*rit]);
00458 }
00459
00460 std::string
00461 Cloud::getStat () const
00462 {
00463 std::string title = "Total number of points: ";
00464 std::string num_str;
00465 ::toString(cloud_.size(), num_str);
00466 return (title + num_str);
00467 }
00468
00469 void
00470 Cloud::updateCloudMembers ()
00471 {
00472 if (cloud_.empty())
00473 return;
00474
00475 std::fill_n(min_xyz_, XYZ_SIZE, 0.0f);
00476 std::fill_n(max_xyz_, XYZ_SIZE, 0.0f);
00477 float *pt = &(cloud_.points[0].data[X]);
00478 std::copy(pt, pt+XYZ_SIZE, max_xyz_);
00479 std::copy(max_xyz_, max_xyz_+XYZ_SIZE, min_xyz_);
00480 for (unsigned int i = 1; i < cloud_.size(); ++i)
00481 {
00482 for (unsigned int j = 0; j < XYZ_SIZE; ++j)
00483 {
00484 min_xyz_[j] = std::min(min_xyz_[j], cloud_.points[i].data[j]);
00485 max_xyz_[j] = std::max(max_xyz_[j], cloud_.points[i].data[j]);
00486 }
00487 }
00488 float range = 0.0f;
00489 for (unsigned int j = 0; j < XYZ_SIZE; ++j)
00490 {
00491 range = std::max(range, max_xyz_[j] - min_xyz_[j]);
00492 center_xyz_[j] = 0.5f * (max_xyz_[j] + min_xyz_[j]);
00493 }
00494 display_scale_ = 1.0f / range;
00495 }
00496
00497 void
00498 Cloud::enableTexture () const
00499 {
00500 if (!use_color_ramp_)
00501 return;
00502 float ranges[3] ={max_xyz_[0] - min_xyz_[0],
00503 max_xyz_[1] - min_xyz_[1],
00504 max_xyz_[2] - min_xyz_[2]};
00505 float transvals[3] = {-min_xyz_[0], -min_xyz_[1], -min_xyz_[2]};
00506 float range = ranges[color_ramp_axis_];
00507 float transval = transvals[color_ramp_axis_];
00508 glEnable(GL_TEXTURE_1D);
00509 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00510 glTexCoordPointer(1, GL_FLOAT, sizeof(Point3D),
00511 &(cloud_.points[0].data[color_ramp_axis_]));
00512 glMatrixMode(GL_TEXTURE);
00513 glPushMatrix();
00514 glLoadIdentity();
00515 if (range <= 0.0f)
00516 range = 1.0f;
00517 glScalef(1.0f/range, 1.0f, 1.0f);
00518 glTranslatef(transval, 0.0f, 0.0f);
00519 glMatrixMode(GL_MODELVIEW);
00520 }
00521
00522 void
00523 Cloud::disableTexture () const
00524 {
00525 if (!use_color_ramp_)
00526 return;
00527 glMatrixMode(GL_TEXTURE);
00528 glPopMatrix();
00529 glDisable(GL_TEXTURE_1D);
00530 glMatrixMode(GL_MODELVIEW);
00531 }