1 /*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2010-2012, Willow Garage, Inc.
6 * Copyright (c) 2012-, Open Perception, Inc.
7 *
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided
19 * with the distribution.
20 * * Neither the name of the copyright holder(s) nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 * $Id$
38 *
39 */
40
41 #include <pcl/filters/impl/extract_indices.hpp>
42
43 ///////////////////////////////////////////////////////////////////////////////////////////
44 void
applyFilter(PCLPointCloud2 & output)45 pcl::ExtractIndices<pcl::PCLPointCloud2>::applyFilter (PCLPointCloud2 &output)
46 {
47 if (keep_organized_)
48 {
49 output = *input_;
50 if (negative_)
51 {
52 // Prepare the output and copy the data
53 for (std::size_t i = 0; i < indices_->size (); ++i)
54 for (std::size_t j = 0; j < output.fields.size(); ++j)
55 memcpy (&output.data[(*indices_)[i] * output.point_step + output.fields[j].offset],
56 &user_filter_value_, sizeof(float));
57 }
58 else
59 {
60 // Prepare a vector holding all indices
61 Indices all_indices (input_->width * input_->height);
62 for (index_t i = 0; i < static_cast<index_t>(all_indices.size ()); ++i)
63 all_indices[i] = i;
64
65 Indices indices = *indices_;
66 std::sort (indices.begin (), indices.end ());
67
68 // Get the diference
69 Indices remaining_indices;
70 set_difference (all_indices.begin (), all_indices.end (), indices.begin (), indices.end (),
71 inserter (remaining_indices, remaining_indices.begin ()));
72
73 // Prepare the output and copy the data
74 for (const auto &remaining_index : remaining_indices)
75 for (std::size_t j = 0; j < output.fields.size(); ++j)
76 memcpy (&output.data[remaining_index * output.point_step + output.fields[j].offset],
77 &user_filter_value_, sizeof(float));
78 }
79 if (!std::isfinite (user_filter_value_))
80 output.is_dense = false;
81 return;
82 }
83 if (indices_->empty () || (input_->width * input_->height == 0))
84 {
85 output.width = output.height = 0;
86 output.data.clear ();
87 // If negative, copy all the data
88 if (negative_)
89 output = *input_;
90 return;
91 }
92 if (indices_->size () == (input_->width * input_->height))
93 {
94 // If negative, then return an empty cloud
95 if (negative_)
96 {
97 output.width = output.height = 0;
98 output.data.clear ();
99 }
100 // else, we need to return all points
101 else
102 output = *input_;
103 return;
104 }
105
106 // Copy the common fields (header and fields should have already been copied)
107 output.is_bigendian = input_->is_bigendian;
108 output.point_step = input_->point_step;
109 output.height = 1;
110 // TODO: check the output cloud and assign is_dense based on whether the points are valid or not
111 output.is_dense = false;
112
113 if (negative_)
114 {
115 // Prepare a vector holding all indices
116 Indices all_indices (input_->width * input_->height);
117 for (index_t i = 0; i < static_cast<index_t>(all_indices.size ()); ++i)
118 all_indices[i] = i;
119
120 Indices indices = *indices_;
121 std::sort (indices.begin (), indices.end ());
122
123 // Get the diference
124 Indices remaining_indices;
125 set_difference (all_indices.begin (), all_indices.end (), indices.begin (), indices.end (),
126 inserter (remaining_indices, remaining_indices.begin ()));
127
128 // Prepare the output and copy the data
129 output.width = remaining_indices.size ();
130 output.data.resize (remaining_indices.size () * output.point_step);
131 for (std::size_t i = 0; i < remaining_indices.size (); ++i)
132 memcpy (&output.data[i * output.point_step], &input_->data[remaining_indices[i] * output.point_step], output.point_step);
133 }
134 else
135 {
136 // Prepare the output and copy the data
137 output.width = indices_->size ();
138 output.data.resize (indices_->size () * output.point_step);
139 for (std::size_t i = 0; i < indices_->size (); ++i)
140 memcpy (&output.data[i * output.point_step], &input_->data[(*indices_)[i] * output.point_step], output.point_step);
141 }
142 output.row_step = output.point_step * output.width;
143 }
144
145 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
146 void
applyFilter(Indices & indices)147 pcl::ExtractIndices<pcl::PCLPointCloud2>::applyFilter (Indices &indices)
148 {
149 if (indices_->size () > (input_->width * input_->height))
150 {
151 PCL_ERROR ("[pcl::%s::applyFilter] The indices size exceeds the size of the input.\n", getClassName ().c_str ());
152 indices.clear ();
153 removed_indices_->clear ();
154 return;
155 }
156
157 if (!negative_) // Normal functionality
158 {
159 indices = *indices_;
160
161 if (extract_removed_indices_)
162 {
163 // Set up the full indices set
164 Indices full_indices (input_->width * input_->height);
165 for (index_t fii = 0; fii < static_cast<index_t> (full_indices.size ()); ++fii) // fii = full indices iterator
166 full_indices[fii] = fii;
167
168 // Set up the sorted input indices
169 Indices sorted_input_indices = *indices_;
170 std::sort (sorted_input_indices.begin (), sorted_input_indices.end ());
171
172 // Store the difference in removed_indices
173 removed_indices_->clear ();
174 std::set_difference (full_indices.begin (), full_indices.end (), sorted_input_indices.begin (), sorted_input_indices.end (), std::inserter (*removed_indices_, removed_indices_->begin ()));
175 }
176 }
177 else // Inverted functionality
178 {
179 // Set up the full indices set
180 Indices full_indices (input_->width * input_->height);
181 for (index_t fii = 0; fii < static_cast<index_t> (full_indices.size ()); ++fii) // fii = full indices iterator
182 full_indices[fii] = fii;
183
184 // Set up the sorted input indices
185 Indices sorted_input_indices = *indices_;
186 std::sort (sorted_input_indices.begin (), sorted_input_indices.end ());
187
188 // Store the difference in indices
189 indices.clear ();
190 std::set_difference (full_indices.begin (), full_indices.end (), sorted_input_indices.begin (), sorted_input_indices.end (), std::inserter (indices, indices.begin ()));
191
192 if (extract_removed_indices_)
193 removed_indices_ = indices_;
194 }
195 }
196
197 #ifndef PCL_NO_PRECOMPILE
198 #include <pcl/impl/instantiate.hpp>
199 #include <pcl/point_types.h>
200
201 #ifdef PCL_ONLY_CORE_POINT_TYPES
202 PCL_INSTANTIATE(ExtractIndices, (pcl::PointXYZ)(pcl::PointXYZI)(pcl::PointXYZRGB)(pcl::PointXYZRGBA)(pcl::Normal)(pcl::PointNormal)(pcl::PointXYZRGBNormal))
203 #else
204 PCL_INSTANTIATE(ExtractIndices, PCL_POINT_TYPES)
205 #endif
206
207 #endif // PCL_NO_PRECOMPILE
208
209