3 #include <boost/core/checked_delete.hpp>
4 #include <boost/smart_ptr/shared_ptr.hpp>
5 #include <pcl/PointIndices.h>
14 #pragma warning(push, 0)
15 #include <pcl/kdtree/kdtree_flann.h>
22 std::vector<triplet>
generateTriplets(pcl::PointCloud<pcl::PointXYZI>::ConstPtr cloud,
size_t k,
size_t n,
float a)
24 std::vector<triplet> triplets;
25 pcl::KdTreeFLANN<pcl::PointXYZI> kdtree;
26 kdtree.setInputCloud(cloud);
28 for (
size_t pointIndexB = 0; pointIndexB < cloud->size(); ++pointIndexB) {
29 pcl::PointXYZI pointB = (*cloud)[pointIndexB];
30 Eigen::Vector3f pointBEigen(pointB.x, pointB.y, pointB.z);
32 std::vector<triplet> tripletCandidates;
34 std::vector<int> nnIndices;
36 std::vector<float> nnbSquaredDistances;
37 nnbSquaredDistances.reserve(k);
38 int const nnFound = kdtree.nearestKSearch(*cloud, (
int)pointIndexB, (
int)k, nnIndices, nnbSquaredDistances);
40 for (
size_t pointIndexIndexA = 1; pointIndexIndexA < nnFound; ++pointIndexIndexA) {
42 if (nnbSquaredDistances[pointIndexIndexA] == 0)
44 size_t const pointIndexA = nnIndices[pointIndexIndexA];
45 pcl::PointXYZI pointA = (*cloud)[pointIndexA];
46 Eigen::Vector3f pointAEigen(pointA.x, pointA.y, pointA.z);
48 Eigen::Vector3f directionAB = pointBEigen - pointAEigen;
49 directionAB /= directionAB.norm();
51 for (
size_t pointIndexIndexC = pointIndexIndexA + 1; pointIndexIndexC < nnFound; ++pointIndexIndexC) {
53 if (nnbSquaredDistances[pointIndexIndexC] == 0)
55 size_t const pointIndexC = nnIndices[pointIndexIndexC];
56 pcl::PointXYZI pointC = (*cloud)[pointIndexC];
57 Eigen::Vector3f pointCEigen(pointC.x, pointC.y, pointC.z);
59 Eigen::Vector3f directionBC = pointCEigen - pointBEigen;
60 directionBC /= directionBC.norm();
62 float const angle = directionAB.dot(directionBC);
65 float const error = 1.0f - angle;
69 Eigen::Vector3f center = (pointAEigen + pointBEigen + pointCEigen) / 3.0
f;
72 Eigen::Vector3f direction = pointCEigen - pointBEigen;
73 direction /= direction.norm();
80 newTriplet.
center = center;
82 newTriplet.
error = error;
84 tripletCandidates.push_back(newTriplet);
90 std::sort(tripletCandidates.begin(), tripletCandidates.end());
93 for (
size_t i = 0; i < std::min(n, tripletCandidates.size()); ++i) {
94 triplets.push_back(tripletCandidates[i]);
114 size_t const triplet_size = triplets.size();
116 auto *result =
new double[(triplet_size * (triplet_size - 1)) / 2];
118 for (
size_t i = 0; i < triplet_size; ++i) {
119 for (
size_t j = i + 1; j < triplet_size; j++) {
120 result[k++] = triplet_metric(triplets[i], triplets[j], cloud);
142 size_t const triplet_size = triplets.size();
143 size_t k, cluster_size, i;
151 double *distance_matrix, *height =
new double[triplet_size - 1];
152 int *merge =
new int[2 * (triplet_size - 1)], *labels =
new int[triplet_size];
159 for (k = 0; k < (triplet_size - 1); ++k) {
160 if (height[k] >= t) {
164 cluster_size = triplet_size - k;
165 cutree_k(triplet_size, merge, cluster_size, labels);
168 for (i = 0; i < cluster_size; ++i) {
170 result.
clusters.push_back(new_cluster);
174 for (i = 0; i < triplet_size; ++i) {
175 result.
clusters[labels[i]].push_back(i);
178 if (opt_verbose > 1) {
180 const char *fname =
"debug_ts.csv";
181 std::ofstream of(fname);
183 for (
size_t iii = 0; i < (triplet_size - 1); ++iii) {
184 of << height[iii] << std::endl;
187 std::cerr <<
"Could Not write file '" << fname <<
"'\n";
194 delete[] distance_matrix;
207 for (
const auto &clust : clusterGroup.
clusters) {
208 if (clust.size() >= m)
209 cleanedGroup.
clusters.push_back(clust);
218 std::vector<pcl::PointIndicesPtr> result;
220 for (
auto currentCluster = clusterGroup.
clusters.begin(); currentCluster < clusterGroup.
clusters.end();
222 pcl::PointIndicesPtr pointIndices(
new pcl::PointIndices());
225 for (
auto currentTripletIndex = currentCluster->begin(); currentTripletIndex < currentCluster->end();
226 currentTripletIndex++) {
227 hc::triplet const ¤tTriplet = triplets[*currentTripletIndex];
229 pointIndices->indices.push_back((
int)currentTriplet.
pointIndexA);
230 pointIndices->indices.push_back((
int)currentTriplet.
pointIndexB);
231 pointIndices->indices.push_back((
int)currentTriplet.
pointIndexC);
235 std::sort(pointIndices->indices.begin(), pointIndices->indices.end());
236 auto newEnd = std::unique(pointIndices->indices.begin(), pointIndices->indices.end());
237 pointIndices->indices.resize(std::distance(pointIndices->indices.begin(), newEnd));
239 result.push_back(pointIndices);
242 return {result, pointIndexCount};
251 pcl::PointCloud<pcl::PointXYZI>::ConstPtr cloud)
253 float const perpendicularDistanceA =
255 float const perpendicularDistanceB =
259 return (std::sqrt(std::max(perpendicularDistanceA, perpendicularDistanceB)) / this->scale) + angle;