Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
image_viewer.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2009-2012, Willow Garage, 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 Willow Garage, Inc. 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  * $Id: image_viewer.hpp 5629 2012-04-26 00:22:41Z rusu $
37  */
38 
39 #ifndef PCL_VISUALIZATION_IMAGE_VISUALIZER_HPP_
40 #define PCL_VISUALIZATION_IMAGE_VISUALIZER_HPP_
41 
42 #include <pcl/search/organized.h>
43 
45 template <typename T> void
47  const std::string &layer_id,
48  double opacity)
49 {
50  if (data_size_ < cloud.width * cloud.height)
51  {
52  data_size_ = cloud.width * cloud.height * 3;
53  data_.reset (new unsigned char[data_size_]);
54  }
55 
56  for (size_t i = 0; i < cloud.points.size (); ++i)
57  {
58  memcpy (&data_[i * 3], reinterpret_cast<const unsigned char*> (&cloud.points[i].rgba), sizeof (unsigned char) * 3);
60  unsigned char aux = data_[i*3];
61  data_[i*3] = data_[i*3+2];
62  data_[i*3+2] = aux;
63  for (int j = 0; j < 3; ++j)
64  if (pcl_isnan (data_[i * 3 + j]))
65  data_[i * 3 + j] = 0;
66  }
67  return (showRGBImage (data_.get (), cloud.width, cloud.height, layer_id, opacity));
68 }
69 
71 template <typename T> void
73  const std::string &layer_id,
74  double opacity)
75 {
76  if (data_size_ < cloud.width * cloud.height)
77  {
78  data_size_ = cloud.width * cloud.height * 3;
79  data_.reset (new unsigned char[data_size_]);
80  }
81 
82  for (size_t i = 0; i < cloud.points.size (); ++i)
83  {
84  memcpy (&data_[i * 3], reinterpret_cast<const unsigned char*> (&cloud.points[i].rgba), sizeof (unsigned char) * 3);
86  unsigned char aux = data_[i*3];
87  data_[i*3] = data_[i*3+2];
88  data_[i*3+2] = aux;
89  for (int j = 0; j < 3; ++j)
90  if (pcl_isnan (data_[i * 3 + j]))
91  data_[i * 3 + j] = 0;
92  }
93  return (addRGBImage (data_.get (), cloud.width, cloud.height, layer_id, opacity));
94 }
95 
97 template <typename T> bool
99  const typename pcl::PointCloud<T>::ConstPtr &image,
100  const pcl::PointCloud<T> &mask,
101  double r, double g, double b,
102  const std::string &layer_id, double opacity)
103 {
104  // We assume that the data passed into image is organized, otherwise this doesn't make sense
105  if (!image->isOrganized ())
106  return (false);
107 
108  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
109  LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
110  if (am_it == layer_map_.end ())
111  {
112  PCL_DEBUG ("[pcl::visualization::ImageViewer::addMask] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
113  am_it = createLayer (layer_id, image_viewer_->GetRenderWindow ()->GetSize ()[0] - 1, image_viewer_->GetRenderWindow ()->GetSize ()[1] - 1, opacity, true);
114  }
115 
116  am_it->canvas->SetDrawColor (r * 255.0, g * 255.0, b * 255.0, opacity * 255.0);
117 
118  // Construct a search object to get the camera parameters
120  search.setInputCloud (image);
121  for (size_t i = 0; i < mask.points.size (); ++i)
122  {
123  pcl::PointXY p_projected;
124  search.projectPoint (mask.points[i], p_projected);
125 
126  am_it->canvas->DrawPoint (int (p_projected.x),
127  int (float (image->height) - p_projected.y));
128  }
129 
130  return (true);
131 }
132 
134 template <typename T> bool
136  const typename pcl::PointCloud<T>::ConstPtr &image,
137  const pcl::PointCloud<T> &mask,
138  const std::string &layer_id, double opacity)
139 {
140  // We assume that the data passed into image is organized, otherwise this doesn't make sense
141  if (!image->isOrganized ())
142  return (false);
143 
144  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
145  LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
146  if (am_it == layer_map_.end ())
147  {
148  PCL_DEBUG ("[pcl::visualization::ImageViewer::addMask] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
149  am_it = createLayer (layer_id, image_viewer_->GetRenderWindow ()->GetSize ()[0] - 1, image_viewer_->GetRenderWindow ()->GetSize ()[1] - 1, opacity, true);
150  }
151 
152  am_it->canvas->SetDrawColor (255.0, 0.0, 0.0, opacity * 255.0);
153 
154  // Construct a search object to get the camera parameters
156  search.setInputCloud (image);
157  for (size_t i = 0; i < mask.points.size (); ++i)
158  {
159  pcl::PointXY p_projected;
160  search.projectPoint (mask.points[i], p_projected);
161 
162  am_it->canvas->DrawPoint (int (p_projected.x),
163  int (float (image->height) - p_projected.y));
164  }
165 
166  return (true);
167 }
168 
170 template <typename T> bool
172  const typename pcl::PointCloud<T>::ConstPtr &image,
173  const pcl::PlanarPolygon<T> &polygon,
174  double r, double g, double b,
175  const std::string &layer_id, double opacity)
176 {
177  // We assume that the data passed into image is organized, otherwise this doesn't make sense
178  if (!image->isOrganized ())
179  return (false);
180 
181  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
182  LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
183  if (am_it == layer_map_.end ())
184  {
185  PCL_DEBUG ("[pcl::visualization::ImageViewer::addPlanarPolygon] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
186  am_it = createLayer (layer_id, image_viewer_->GetRenderWindow ()->GetSize ()[0] - 1, image_viewer_->GetRenderWindow ()->GetSize ()[1] - 1, opacity, true);
187  }
188 
189  am_it->canvas->SetDrawColor (r * 255.0, g * 255.0, b * 255.0, opacity * 255.0);
190 
191  // Construct a search object to get the camera parameters
193  search.setInputCloud (image);
194  for (size_t i = 0; i < polygon.getContour ().size () - 1; ++i)
195  {
196  pcl::PointXY p1, p2;
197  search.projectPoint (polygon.getContour ()[i], p1);
198  search.projectPoint (polygon.getContour ()[i+1], p2);
199 
200  am_it->canvas->DrawSegment (int (p1.x), int (float (image->height) - p1.y),
201  int (p2.x), int (float (image->height) - p2.y));
202  }
203 
204  // Close the polygon
205  pcl::PointXY p1, p2;
206  search.projectPoint (polygon.getContour ()[polygon.getContour ().size () - 1], p1);
207  search.projectPoint (polygon.getContour ()[0], p2);
208 
209  am_it->canvas->DrawSegment (int (p1.x), int (float (image->height) - p1.y),
210  int (p2.x), int (float (image->height) - p2.y));
211 
212  return (true);
213 }
214 
216 template <typename T> bool
218  const typename pcl::PointCloud<T>::ConstPtr &image,
219  const pcl::PlanarPolygon<T> &polygon,
220  const std::string &layer_id, double opacity)
221 {
222  // We assume that the data passed into image is organized, otherwise this doesn't make sense
223  if (!image->isOrganized ())
224  return (false);
225 
226  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
227  LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
228  if (am_it == layer_map_.end ())
229  {
230  PCL_DEBUG ("[pcl::visualization::ImageViewer::addPlanarPolygon] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
231  am_it = createLayer (layer_id, image_viewer_->GetRenderWindow ()->GetSize ()[0] - 1, image_viewer_->GetRenderWindow ()->GetSize ()[1] - 1, opacity, true);
232  }
233 
234  am_it->canvas->SetDrawColor (255.0, 0.0, 0.0, opacity * 255.0);
235 
236  // Construct a search object to get the camera parameters
238  search.setInputCloud (image);
239  for (size_t i = 0; i < polygon.getContour ().size () - 1; ++i)
240  {
241  pcl::PointXY p1, p2;
242  search.projectPoint (polygon.getContour ()[i], p1);
243  search.projectPoint (polygon.getContour ()[i+1], p2);
244 
245  am_it->canvas->DrawSegment (int (p1.x), int (float (image->height) - p1.y),
246  int (p2.x), int (float (image->height) - p2.y));
247  }
248 
249  // Close the polygon
250  pcl::PointXY p1, p2;
251  search.projectPoint (polygon.getContour ()[polygon.getContour ().size () - 1], p1);
252  search.projectPoint (polygon.getContour ()[0], p2);
253 
254  am_it->canvas->DrawSegment (int (p1.x), int (float (image->height) - p1.y),
255  int (p2.x), int (float (image->height) - p2.y));
256  return (true);
257 }
258 
260 template <typename T> bool
262  const typename pcl::PointCloud<T>::ConstPtr &image,
263  const T &min_pt,
264  const T &max_pt,
265  double r, double g, double b,
266  const std::string &layer_id, double opacity)
267 {
268  // We assume that the data passed into image is organized, otherwise this doesn't make sense
269  if (!image->isOrganized ())
270  return (false);
271 
272  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
273  LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
274  if (am_it == layer_map_.end ())
275  {
276  PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
277  am_it = createLayer (layer_id, image_viewer_->GetRenderWindow ()->GetSize ()[0] - 1, image_viewer_->GetRenderWindow ()->GetSize ()[1] - 1, opacity, true);
278  }
279 
280  // Construct a search object to get the camera parameters
282  search.setInputCloud (image);
283  // Project the 8 corners
284  T p1, p2, p3, p4, p5, p6, p7, p8;
285  p1.x = min_pt.x; p1.y = min_pt.y; p1.z = min_pt.z;
286  p2.x = min_pt.x; p2.y = min_pt.y; p2.z = max_pt.z;
287  p3.x = min_pt.x; p3.y = max_pt.y; p3.z = min_pt.z;
288  p4.x = min_pt.x; p4.y = max_pt.y; p4.z = max_pt.z;
289  p5.x = max_pt.x; p5.y = min_pt.y; p5.z = min_pt.z;
290  p6.x = max_pt.x; p6.y = min_pt.y; p6.z = max_pt.z;
291  p7.x = max_pt.x; p7.y = max_pt.y; p7.z = min_pt.z;
292  p8.x = max_pt.x; p8.y = max_pt.y; p8.z = max_pt.z;
293 
294  std::vector<pcl::PointXY> pp_2d (8);
295  search.projectPoint (p1, pp_2d[0]);
296  search.projectPoint (p2, pp_2d[1]);
297  search.projectPoint (p3, pp_2d[2]);
298  search.projectPoint (p4, pp_2d[3]);
299  search.projectPoint (p5, pp_2d[4]);
300  search.projectPoint (p6, pp_2d[5]);
301  search.projectPoint (p7, pp_2d[6]);
302  search.projectPoint (p8, pp_2d[7]);
303 
304  pcl::PointXY min_pt_2d, max_pt_2d;
305  min_pt_2d.x = min_pt_2d.y = std::numeric_limits<float>::max ();
306  max_pt_2d.x = max_pt_2d.y = std::numeric_limits<float>::min ();
307  // Search for the two extrema
308  for (size_t i = 0; i < pp_2d.size (); ++i)
309  {
310  if (pp_2d[i].x < min_pt_2d.x) min_pt_2d.x = pp_2d[i].x;
311  if (pp_2d[i].y < min_pt_2d.y) min_pt_2d.y = pp_2d[i].y;
312  if (pp_2d[i].x > max_pt_2d.x) max_pt_2d.x = pp_2d[i].x;
313  if (pp_2d[i].y > max_pt_2d.y) max_pt_2d.y = pp_2d[i].y;
314  }
315  min_pt_2d.y = float (image->height) - min_pt_2d.y;
316  max_pt_2d.y = float (image->height) - max_pt_2d.y;
317 
318  am_it->canvas->SetDrawColor (r * 255.0, g * 255.0, b * 255.0, opacity * 255.0);
319 
320  am_it->canvas->DrawSegment (int (min_pt_2d.x), int (min_pt_2d.y), int (min_pt_2d.x), int (max_pt_2d.y));
321  am_it->canvas->DrawSegment (int (min_pt_2d.x), int (max_pt_2d.y), int (max_pt_2d.x), int (max_pt_2d.y));
322  am_it->canvas->DrawSegment (int (max_pt_2d.x), int (max_pt_2d.y), int (max_pt_2d.x), int (min_pt_2d.y));
323  am_it->canvas->DrawSegment (int (max_pt_2d.x), int (min_pt_2d.y), int (min_pt_2d.x), int (min_pt_2d.y));
324 
325  return (true);
326 }
327 
329 template <typename T> bool
331  const typename pcl::PointCloud<T>::ConstPtr &image,
332  const T &min_pt,
333  const T &max_pt,
334  const std::string &layer_id, double opacity)
335 {
336  // We assume that the data passed into image is organized, otherwise this doesn't make sense
337  if (!image->isOrganized ())
338  return (false);
339 
340  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
341  LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
342  if (am_it == layer_map_.end ())
343  {
344  PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
345  am_it = createLayer (layer_id, image_viewer_->GetRenderWindow ()->GetSize ()[0] - 1, image_viewer_->GetRenderWindow ()->GetSize ()[1] - 1, opacity, true);
346  }
347 
348  // Construct a search object to get the camera parameters
350  search.setInputCloud (image);
351  // Project the 8 corners
352  T p1, p2, p3, p4, p5, p6, p7, p8;
353  p1.x = min_pt.x; p1.y = min_pt.y; p1.z = min_pt.z;
354  p2.x = min_pt.x; p2.y = min_pt.y; p2.z = max_pt.z;
355  p3.x = min_pt.x; p3.y = max_pt.y; p3.z = min_pt.z;
356  p4.x = min_pt.x; p4.y = max_pt.y; p4.z = max_pt.z;
357  p5.x = max_pt.x; p5.y = min_pt.y; p5.z = min_pt.z;
358  p6.x = max_pt.x; p6.y = min_pt.y; p6.z = max_pt.z;
359  p7.x = max_pt.x; p7.y = max_pt.y; p7.z = min_pt.z;
360  p8.x = max_pt.x; p8.y = max_pt.y; p8.z = max_pt.z;
361 
362  std::vector<pcl::PointXY> pp_2d (8);
363  search.projectPoint (p1, pp_2d[0]);
364  search.projectPoint (p2, pp_2d[1]);
365  search.projectPoint (p3, pp_2d[2]);
366  search.projectPoint (p4, pp_2d[3]);
367  search.projectPoint (p5, pp_2d[4]);
368  search.projectPoint (p6, pp_2d[5]);
369  search.projectPoint (p7, pp_2d[6]);
370  search.projectPoint (p8, pp_2d[7]);
371 
372  pcl::PointXY min_pt_2d, max_pt_2d;
373  min_pt_2d.x = min_pt_2d.y = std::numeric_limits<float>::max ();
374  max_pt_2d.x = max_pt_2d.y = std::numeric_limits<float>::min ();
375  // Search for the two extrema
376  for (size_t i = 0; i < pp_2d.size (); ++i)
377  {
378  if (pp_2d[i].x < min_pt_2d.x) min_pt_2d.x = pp_2d[i].x;
379  if (pp_2d[i].y < min_pt_2d.y) min_pt_2d.y = pp_2d[i].y;
380  if (pp_2d[i].x > max_pt_2d.x) max_pt_2d.x = pp_2d[i].x;
381  if (pp_2d[i].y > max_pt_2d.y) max_pt_2d.y = pp_2d[i].y;
382  }
383  min_pt_2d.y = float (image->height) - min_pt_2d.y;
384  max_pt_2d.y = float (image->height) - max_pt_2d.y;
385 
386  am_it->canvas->SetDrawColor (0.0, 255.0, 0.0, opacity * 255.0);
387  am_it->canvas->DrawSegment (int (min_pt_2d.x), int (min_pt_2d.y), int (min_pt_2d.x), int (max_pt_2d.y));
388  am_it->canvas->DrawSegment (int (min_pt_2d.x), int (max_pt_2d.y), int (max_pt_2d.x), int (max_pt_2d.y));
389  am_it->canvas->DrawSegment (int (max_pt_2d.x), int (max_pt_2d.y), int (max_pt_2d.x), int (min_pt_2d.y));
390  am_it->canvas->DrawSegment (int (max_pt_2d.x), int (min_pt_2d.y), int (min_pt_2d.x), int (min_pt_2d.y));
391 
392  return (true);
393 }
394 
396 template <typename T> bool
398  const typename pcl::PointCloud<T>::ConstPtr &image,
399  const pcl::PointCloud<T> &mask,
400  double r, double g, double b,
401  const std::string &layer_id, double opacity)
402 {
403  // We assume that the data passed into image is organized, otherwise this doesn't make sense
404  if (!image->isOrganized ())
405  return (false);
406 
407  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
408  LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
409  if (am_it == layer_map_.end ())
410  {
411  PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
412  am_it = createLayer (layer_id, image_viewer_->GetRenderWindow ()->GetSize ()[0] - 1, image_viewer_->GetRenderWindow ()->GetSize ()[1] - 1, opacity, true);
413  }
414 
415  am_it->canvas->SetDrawColor (r * 255.0, g * 255.0, b * 255.0, opacity * 255.0);
416 
417  // Construct a search object to get the camera parameters
419  search.setInputCloud (image);
420  std::vector<pcl::PointXY> pp_2d (mask.points.size ());
421  for (size_t i = 0; i < mask.points.size (); ++i)
422  search.projectPoint (mask.points[i], pp_2d[i]);
423 
424  pcl::PointXY min_pt_2d, max_pt_2d;
425  min_pt_2d.x = min_pt_2d.y = std::numeric_limits<float>::max ();
426  max_pt_2d.x = max_pt_2d.y = std::numeric_limits<float>::min ();
427  // Search for the two extrema
428  for (size_t i = 0; i < pp_2d.size (); ++i)
429  {
430  if (pp_2d[i].x < min_pt_2d.x) min_pt_2d.x = pp_2d[i].x;
431  if (pp_2d[i].y < min_pt_2d.y) min_pt_2d.y = pp_2d[i].y;
432  if (pp_2d[i].x > max_pt_2d.x) max_pt_2d.x = pp_2d[i].x;
433  if (pp_2d[i].y > max_pt_2d.y) max_pt_2d.y = pp_2d[i].y;
434  }
435  min_pt_2d.y = float (image->height) - min_pt_2d.y;
436  max_pt_2d.y = float (image->height) - max_pt_2d.y;
437 
438  am_it->canvas->DrawSegment (int (min_pt_2d.x), int (min_pt_2d.y), int (min_pt_2d.x), int (max_pt_2d.y));
439  am_it->canvas->DrawSegment (int (min_pt_2d.x), int (max_pt_2d.y), int (max_pt_2d.x), int (max_pt_2d.y));
440  am_it->canvas->DrawSegment (int (max_pt_2d.x), int (max_pt_2d.y), int (max_pt_2d.x), int (min_pt_2d.y));
441  am_it->canvas->DrawSegment (int (max_pt_2d.x), int (min_pt_2d.y), int (min_pt_2d.x), int (min_pt_2d.y));
442 
443  return (true);
444 }
445 
447 template <typename T> bool
449  const typename pcl::PointCloud<T>::ConstPtr &image,
450  const pcl::PointCloud<T> &mask,
451  const std::string &layer_id, double opacity)
452 {
453  // We assume that the data passed into image is organized, otherwise this doesn't make sense
454  if (!image->isOrganized ())
455  return (false);
456 
457  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
458  LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
459  if (am_it == layer_map_.end ())
460  {
461  PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
462  am_it = createLayer (layer_id, image_viewer_->GetRenderWindow ()->GetSize ()[0] - 1, image_viewer_->GetRenderWindow ()->GetSize ()[1] - 1, opacity, true);
463  }
464 
465  am_it->canvas->SetDrawColor (0.0, 255.0, 0.0, opacity * 255.0);
466 
467  // Construct a search object to get the camera parameters
469  search.setInputCloud (image);
470  std::vector<pcl::PointXY> pp_2d (mask.points.size ());
471  for (size_t i = 0; i < mask.points.size (); ++i)
472  search.projectPoint (mask.points[i], pp_2d[i]);
473 
474  pcl::PointXY min_pt_2d, max_pt_2d;
475  min_pt_2d.x = min_pt_2d.y = std::numeric_limits<float>::max ();
476  max_pt_2d.x = max_pt_2d.y = std::numeric_limits<float>::min ();
477  // Search for the two extrema
478  for (size_t i = 0; i < pp_2d.size (); ++i)
479  {
480  if (pp_2d[i].x < min_pt_2d.x) min_pt_2d.x = pp_2d[i].x;
481  if (pp_2d[i].y < min_pt_2d.y) min_pt_2d.y = pp_2d[i].y;
482  if (pp_2d[i].x > max_pt_2d.x) max_pt_2d.x = pp_2d[i].x;
483  if (pp_2d[i].y > max_pt_2d.y) max_pt_2d.y = pp_2d[i].y;
484  }
485  min_pt_2d.y = float (image->height) - min_pt_2d.y;
486  max_pt_2d.y = float (image->height) - max_pt_2d.y;
487 
488  am_it->canvas->DrawSegment (int (min_pt_2d.x), int (min_pt_2d.y), int (min_pt_2d.x), int (max_pt_2d.y));
489  am_it->canvas->DrawSegment (int (min_pt_2d.x), int (max_pt_2d.y), int (max_pt_2d.x), int (max_pt_2d.y));
490  am_it->canvas->DrawSegment (int (max_pt_2d.x), int (max_pt_2d.y), int (max_pt_2d.x), int (min_pt_2d.y));
491  am_it->canvas->DrawSegment (int (max_pt_2d.x), int (min_pt_2d.y), int (min_pt_2d.x), int (min_pt_2d.y));
492 
493 
494  return (true);
495 }
496 
497 #endif // PCL_VISUALIZATION_IMAGE_VISUALIZER_HPP_