40 #ifndef PCL_FEATURES_IMPL_SHOT_LRF_H_
41 #define PCL_FEATURES_IMPL_SHOT_LRF_H_
44 #include <pcl/features/shot_lrf.h>
48 template<
typename Po
intInT,
typename Po
intOutT>
float
51 const Eigen::Vector4f& central_point = (*input_)[current_point_idx].getVector4fMap ();
52 std::vector<int> n_indices;
53 std::vector<float> n_sqr_distances;
55 this->searchForNeighbors (current_point_idx, search_parameter_, n_indices, n_sqr_distances);
57 Eigen::Matrix<double, Eigen::Dynamic, 4> vij (n_indices.size (), 4);
59 Eigen::Matrix3d cov_m = Eigen::Matrix3d::Zero ();
61 double distance = 0.0;
64 int valid_nn_points = 0;
66 for (
size_t i_idx = 0; i_idx < n_indices.size (); ++i_idx)
68 Eigen::Vector4f pt = surface_->points[n_indices[i_idx]].getVector4fMap ();
69 if (pt.head<3> () == central_point.head<3> ())
73 vij.row (valid_nn_points).matrix () = (pt - central_point).cast<double> ();
74 vij (valid_nn_points, 3) = 0;
76 distance = search_parameter_ - sqrt (n_sqr_distances[i_idx]);
79 cov_m += distance * (vij.row (valid_nn_points).head<3> ().transpose () * vij.row (valid_nn_points).head<3> ());
85 if (valid_nn_points < 5)
88 rf.setConstant (std::numeric_limits<float>::quiet_NaN ());
90 return (std::numeric_limits<float>::max ());
95 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver (cov_m);
97 const double& e1c = solver.eigenvalues ()[0];
98 const double& e2c = solver.eigenvalues ()[1];
99 const double& e3c = solver.eigenvalues ()[2];
101 if (!pcl_isfinite (e1c) || !pcl_isfinite (e2c) || !pcl_isfinite (e3c))
104 rf.setConstant (std::numeric_limits<float>::quiet_NaN ());
106 return (std::numeric_limits<float>::max ());
110 Eigen::Vector4d v1 = Eigen::Vector4d::Zero ();
111 Eigen::Vector4d v3 = Eigen::Vector4d::Zero ();
112 v1.head<3> ().matrix () = solver.eigenvectors ().col (2);
113 v3.head<3> ().matrix () = solver.eigenvectors ().col (0);
115 int plusNormal = 0, plusTangentDirection1=0;
116 for (
int ne = 0; ne < valid_nn_points; ne++)
118 double dp = vij.row (ne).dot (v1);
120 plusTangentDirection1++;
122 dp = vij.row (ne).dot (v3);
128 plusTangentDirection1 = 2*plusTangentDirection1 - valid_nn_points;
129 if (plusTangentDirection1 == 0)
132 int medianIndex = valid_nn_points/2;
134 for (
int i = -points/2; i <= points/2; i++)
135 if ( vij.row (medianIndex - i).dot (v1) > 0)
136 plusTangentDirection1 ++;
138 if (plusTangentDirection1 < points/2+1)
141 else if (plusTangentDirection1 < 0)
145 plusNormal = 2*plusNormal - valid_nn_points;
149 int medianIndex = valid_nn_points/2;
151 for (
int i = -points/2; i <= points/2; i++)
152 if ( vij.row (medianIndex - i).dot (v3) > 0)
155 if (plusNormal < points/2+1)
157 }
else if (plusNormal < 0)
160 rf.row (0).matrix () = v1.head<3> ().cast<float> ();
161 rf.row (2).matrix () = v3.head<3> ().cast<float> ();
162 rf.row (1).matrix () = rf.row (2).cross (rf.row (0));
168 template <
typename Po
intInT,
typename Po
intOutT>
void
172 if (this->getKSearch () != 0)
175 "[pcl::%s::computeFeature] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
176 getClassName().c_str ());
179 tree_->setSortedResults (
true);
181 for (
size_t i = 0; i < indices_->size (); ++i)
185 PointOutT& output_rf = output[i];
189 if (getLocalRF ((*indices_)[i], rf) == std::numeric_limits<float>::max ())
194 for (
int d = 0; d < 3; ++d)
196 output_rf.x_axis[d] = rf.row (0)[d];
197 output_rf.y_axis[d] = rf.row (1)[d];
198 output_rf.z_axis[d] = rf.row (2)[d];
203 #define PCL_INSTANTIATE_SHOTLocalReferenceFrameEstimation(T,OutT) template class PCL_EXPORTS pcl::SHOTLocalReferenceFrameEstimation<T,OutT>;
205 #endif // PCL_FEATURES_IMPL_SHOT_LRF_H_
PointCloud represents the base class in PCL for storing collections of 3D points. ...
virtual void computeFeature(PointCloudOut &output)
Feature estimation method.
float getLocalRF(const int &index, Eigen::Matrix3f &rf)
Computes disambiguated local RF for a point index.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values).