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