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 
36 /// @file   select2DTool.cpp
37 /// @details the implementation of Select2DTool class.
38 /// @author  Yue Li and Matthew Hielsberg
39 
40 #include <pcl/apps/point_cloud_editor/select2DTool.h>
41 #include <pcl/apps/point_cloud_editor/cloud.h>
42 #include <pcl/apps/point_cloud_editor/selection.h>
43 
44 const float Select2DTool::DEFAULT_TOOL_DISPLAY_SIZE_ = 2.0f;
45 
46 const float Select2DTool::DEFAULT_TOOL_DISPLAY_COLOR_RED_ = 1.0f;
47 const float Select2DTool::DEFAULT_TOOL_DISPLAY_COLOR_GREEN_ = 1.0f;
48 const float Select2DTool::DEFAULT_TOOL_DISPLAY_COLOR_BLUE_ = 1.0f;
49 
50 
Select2DTool(SelectionPtr selection_ptr,CloudPtr cloud_ptr)51 Select2DTool::Select2DTool (SelectionPtr selection_ptr, CloudPtr cloud_ptr)
52   : selection_ptr_(std::move(selection_ptr)), cloud_ptr_(std::move(cloud_ptr)), display_box_(false)
53 {
54 }
55 
~Select2DTool()56 Select2DTool::~Select2DTool ()
57 {
58 }
59 
60 void
start(int x,int y,BitMask,BitMask)61 Select2DTool::start (int x, int y, BitMask, BitMask)
62 {
63   if (!cloud_ptr_)
64     return;
65   origin_x_ = x;
66   origin_y_ = y;
67 }
68 
69 void
update(int x,int y,BitMask,BitMask)70 Select2DTool::update (int x, int y, BitMask, BitMask)
71 {
72   if (!cloud_ptr_)
73     return;
74   final_x_ = x;
75   final_y_ = y;
76   display_box_ = true;
77 }
78 
79 void
end(int x,int y,BitMask modifiers,BitMask)80 Select2DTool::end (int x, int y, BitMask modifiers, BitMask)
81 {
82   if (!cloud_ptr_)
83     return;
84   final_x_ = x;
85   final_y_ = y;
86   display_box_ = false;
87   // don't select anything if we don't have a selection box.
88   if ((final_x_ == origin_x_) || (final_y_ == origin_y_))
89     return;
90 
91   GLint viewport[4];
92   glGetIntegerv(GL_VIEWPORT,viewport);
93   IndexVector indices;
94   GLfloat project[16];
95   glGetFloatv(GL_PROJECTION_MATRIX, project);
96 
97   Point3DVector ptsvec;
98   cloud_ptr_->getDisplaySpacePoints(ptsvec);
99   for(std::size_t i = 0; i < ptsvec.size(); ++i)
100   {
101     Point3D pt = ptsvec[i];
102     if (isInSelectBox(pt, project, viewport))
103       indices.push_back(i);
104   }
105 
106   if (modifiers & SHFT)
107   {
108     selection_ptr_->addIndex(indices);
109   }
110   else if (modifiers & CTRL)
111   {
112     selection_ptr_->removeIndex(indices);
113   }
114   else
115   {
116     selection_ptr_->clear();
117     selection_ptr_->addIndex(indices);
118   }
119   cloud_ptr_->setSelection(selection_ptr_);
120 }
121 
122 bool
isInSelectBox(const Point3D & pt,const GLfloat * project,const GLint * viewport) const123 Select2DTool::isInSelectBox (const Point3D& pt,
124                              const GLfloat* project,
125                              const GLint* viewport) const
126 {
127   float w = pt.z * project[11];
128   float x = (pt.x * project[0] + pt.z * project[8]) / w;
129   float y = (pt.y * project[5] + pt.z * project[9]) / w;
130   float min_x = std::min(origin_x_, final_x_)/(viewport[2]*0.5) - 1.0;
131   float max_x = std::max(final_x_, origin_x_)/(viewport[2]*0.5) - 1.0;
132   float max_y = (viewport[3] - std::min(origin_y_, final_y_))/(viewport[3]*0.5) - 1.0;
133   float min_y = (viewport[3] - std::max(origin_y_, final_y_))/(viewport[3]*0.5) - 1.0;
134   // Ignore the points behind the camera
135   if (w < 0)
136     return (false);
137   // Check the left and right sides
138   if ((x < min_x) || (x > max_x))
139     return (false);
140   // Check the bottom and top
141   if ((y < min_y) || (y > max_y))
142     return (false);
143   return (true);
144 }
145 
146 void
draw() const147 Select2DTool::draw() const
148 {
149   if (!display_box_)
150     return;
151   GLint viewport[4];
152   glGetIntegerv(GL_VIEWPORT, viewport);
153   // draw the selection box
154   drawRubberBand(viewport);
155   // highlight all the points in the rubberband
156   highlightPoints(viewport);
157 }
158 
159 void
drawRubberBand(GLint * viewport) const160 Select2DTool::drawRubberBand (GLint* viewport) const
161 {
162   // set the line width of the rubberband
163   glLineWidth(DEFAULT_TOOL_DISPLAY_SIZE_);
164   // set the color of the rubberband
165   glColor3f(DEFAULT_TOOL_DISPLAY_COLOR_RED_,
166             DEFAULT_TOOL_DISPLAY_COLOR_GREEN_,
167             DEFAULT_TOOL_DISPLAY_COLOR_BLUE_);
168   glMatrixMode(GL_PROJECTION);
169   glPushMatrix();
170   {
171     glLoadIdentity();
172     glOrtho(0, viewport[2], viewport[3], 0, -1, 1);
173     glMatrixMode(GL_MODELVIEW);
174     glPushMatrix();
175     {
176       glLoadIdentity();
177       glLineStipple (3, 0x8888);
178       glEnable(GL_LINE_STIPPLE);
179       glBegin(GL_LINE_LOOP);
180       {
181         glVertex2d(origin_x_, origin_y_); // Top Left
182         glVertex2d(final_x_,  origin_y_); // Top Right
183         glVertex2d(final_x_,  final_y_);  // Bottom Right
184         glVertex2d(origin_x_, final_y_);  // Bottom Left
185       }
186       glEnd();
187       glDisable(GL_LINE_STIPPLE);
188     }
189     glPopMatrix();
190     glMatrixMode(GL_PROJECTION);
191   }
192   glPopMatrix();
193   glMatrixMode(GL_MODELVIEW);
194 }
195 
196 void
highlightPoints(GLint * viewport) const197 Select2DTool::highlightPoints (GLint* viewport) const
198 {
199   double width = std::abs(origin_x_ - final_x_);
200   double height = std::abs(origin_y_ - final_y_);
201   glPushAttrib(GL_SCISSOR_BIT);
202   {
203     glEnable(GL_SCISSOR_TEST);
204     glScissor(std::min(origin_x_, final_x_),
205               std::min(viewport[3] - final_y_, viewport[3] - origin_y_),
206               width, height);
207     cloud_ptr_ -> drawWithHighlightColor();
208   }
209   glPopAttrib();
210 }
211 
212