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 selectionTransformTool.cpp
37 /// @details the implementation of class CloudTransformTool
38 /// @author Yue Li and Matthew Hielsberg
39 
40 #include <pcl/apps/point_cloud_editor/selectionTransformTool.h>
41 #include <pcl/apps/point_cloud_editor/cloud.h>
42 #include <pcl/apps/point_cloud_editor/selection.h>
43 #include <pcl/apps/point_cloud_editor/transformCommand.h>
44 #include <pcl/apps/point_cloud_editor/commandQueue.h>
45 #include <pcl/apps/point_cloud_editor/common.h>
46 
47 const float SelectionTransformTool::DEFAULT_TRANSLATE_FACTOR_ = 0.001;
48 
SelectionTransformTool(ConstSelectionPtr selection_ptr,CloudPtr cloud_ptr,CommandQueuePtr command_queue_ptr)49 SelectionTransformTool::SelectionTransformTool (ConstSelectionPtr selection_ptr,
50                                                 CloudPtr cloud_ptr,
51                                                 CommandQueuePtr command_queue_ptr)
52   : selection_ptr_(std::move(selection_ptr)),
53     cloud_ptr_(std::move(cloud_ptr)),
54     command_queue_ptr_(std::move(command_queue_ptr)),
55     translate_factor_(DEFAULT_TRANSLATE_FACTOR_)
56 {
57   std::fill_n(center_xyz_, XYZ_SIZE, 0);
58   setIdentity(transform_matrix_);
59 }
60 
61 void
start(int x,int y,BitMask modifiers,BitMask buttons)62 SelectionTransformTool::start (int x, int y, BitMask modifiers, BitMask buttons)
63 {
64   if ((!cloud_ptr_) || (!selection_ptr_) || selection_ptr_->empty())
65     return;
66   if (!(buttons & LEFT))
67     return;
68   modifiers_ = modifiers;
69   x_ = x;
70   y_ = y;
71   findSelectionCenter();
72   setIdentity(transform_matrix_);
73   trackball_.start(x, y);
74 }
75 
76 void
update(int x,int y,BitMask,BitMask buttons)77 SelectionTransformTool::update (int x, int y, BitMask, BitMask buttons)
78 {
79   if (!cloud_ptr_)
80     return;
81   if (!(buttons & LEFT))
82     return;
83   int dx = (x - x_);
84   int dy = (y - y_);
85   if (dx == 0 && dy == 0)
86     return;
87   trackball_.update(x, y);
88 
89   if (modifiers_ & CTRL)
90   {
91     // selection motion is not applied directly (waits for end)
92     // as such we can not update x and y immediately
93     float scale = 1.0f / cloud_ptr_->getScalingFactor();
94     cloud_ptr_->setSelectionTranslation ((float) dx * translate_factor_ * scale,
95                                          (float) -dy * translate_factor_ * scale,
96                                          0.0f);
97     return;
98   }
99   if (modifiers_ & ALT)
100   {
101     // selection motion is not applied directly (waits for end)
102     // as such we can not update x and y immediately
103     float scale = 1.0f / cloud_ptr_->getScalingFactor();
104     cloud_ptr_->setSelectionTranslation (0.0f,
105                                          0.0f,
106                                          (float) dy * translate_factor_ * scale);
107     return;
108   }
109   float transform[MATRIX_SIZE];
110   trackball_.getRotationMatrix(transform);
111   transform_matrix_[12] -= center_xyz_[0];
112   transform_matrix_[13] -= center_xyz_[1];
113   transform_matrix_[14] -= center_xyz_[2];
114   ::multMatrix(transform_matrix_, transform, transform_matrix_);
115   transform_matrix_[12] += center_xyz_[0];
116   transform_matrix_[13] += center_xyz_[1];
117   transform_matrix_[14] += center_xyz_[2];
118   cloud_ptr_ -> setSelectionRotation(transform_matrix_);
119 
120   x_ = x;
121   y_ = y;
122 }
123 
124 void
end(int x,int y,BitMask modifiers,BitMask buttons)125 SelectionTransformTool::end (int x, int y, BitMask modifiers, BitMask buttons)
126 {
127   if (!(buttons & LEFT))
128     return;
129 
130   float scale = 1.0f / cloud_ptr_->getScalingFactor();
131   int dx = (x - x_);
132   int dy = (y - y_);
133   update(x, y, modifiers, buttons);
134   if (modifiers_ & CTRL)
135   {
136     std::shared_ptr<TransformCommand> c(new TransformCommand(selection_ptr_,
137       cloud_ptr_, transform_matrix_, (float) dx * translate_factor_ * scale,
138       (float) -dy * translate_factor_ * scale, 0.0f));
139     command_queue_ptr_->execute(c);
140   }
141   else if (modifiers_ & ALT)
142   {
143     std::shared_ptr<TransformCommand> c(new TransformCommand(selection_ptr_,
144       cloud_ptr_, transform_matrix_, 0.0f, 0.0f,
145       (float) dy * translate_factor_ * scale));
146     command_queue_ptr_->execute(c);
147   }
148   else
149   {
150     std::shared_ptr<TransformCommand> c(new TransformCommand(selection_ptr_,
151       cloud_ptr_, transform_matrix_, 0.0f, 0.0f, 0.0f));
152     command_queue_ptr_->execute(c);
153   }
154   setIdentity(transform_matrix_);
155   cloud_ptr_->setSelectionRotation(transform_matrix_);
156   cloud_ptr_->setSelectionTranslation(0.0f, 0.0f, 0.0f);
157 }
158 
159 /*void
160 SelectionTransformTool::getRotateMatrix (int dx, int dy,
161                                          float* rotation_matrix_a,
162                                          float* rotation_matrix_b,
163                                          BitMask buttons) const
164 {
165   setIdentity(rotation_matrix_a);
166   setIdentity(rotation_matrix_b);
167   float rad_dx = (float) dx  * M_PI / 180.0f;
168   float rad_dy = (float) dy  * M_PI / 180.0f;
169   rotation_matrix_a[5]  = std::cos(rad_dy);
170   rotation_matrix_a[6]  = std::sin(rad_dy);
171   rotation_matrix_a[9]  = -std::sin(rad_dy);
172   rotation_matrix_a[10] = std::cos(rad_dy);
173   if (buttons & LEFT)
174   {
175     rotation_matrix_b[0]  = std::cos(rad_dx);
176     rotation_matrix_b[2]  = -std::sin(rad_dx);
177     rotation_matrix_b[8]  = std::sin(rad_dx);
178     rotation_matrix_b[10] = std::cos(rad_dx);
179   }
180   else if (buttons & RIGHT)
181   {
182     rotation_matrix_b[0]  = std::cos(rad_dx);
183     rotation_matrix_b[1]  = std::sin(rad_dx);
184     rotation_matrix_b[4]  = -std::sin(rad_dx);
185     rotation_matrix_b[5]  = std::cos(rad_dx);
186   }
187 }*/
188 
189 void
findSelectionCenter()190 SelectionTransformTool::findSelectionCenter ()
191 {
192   if (!selection_ptr_ || selection_ptr_->empty())
193     return;
194   float min_xyz[XYZ_SIZE] = {0.0f};
195   float max_xyz[XYZ_SIZE] = {0.0f};
196   Selection::const_iterator it = selection_ptr_->begin();
197   Point3D point_3d = cloud_ptr_->getObjectSpacePoint (*it);
198   float *pt = &(point_3d.data[X]);
199   std::copy(pt, pt+XYZ_SIZE, max_xyz);
200   std::copy(max_xyz, max_xyz+XYZ_SIZE, min_xyz);
201 
202   for (++it; it != selection_ptr_->end(); ++it)
203   {
204     Point3D point_3d = cloud_ptr_->getObjectSpacePoint (*it);
205     pt = &(point_3d.data[X]);
206     for (unsigned int j = 0; j < XYZ_SIZE; ++j)
207     {
208       min_xyz[j] = std::min(min_xyz[j], pt[j]);
209       max_xyz[j] = std::max(max_xyz[j], pt[j]);
210     }
211   }
212   for (unsigned int j = 0; j < XYZ_SIZE; ++j)
213   {
214     center_xyz_[j] = 0.5f * (max_xyz[j] + min_xyz[j]);
215   }
216 }
217 
218 
219 
220 
221 
222 
223 
224 
225 
226 
227 
228 
229 
230 
231 
232