Reputation: 81
There are similar questions, but my main concern here is regarding processing time.
I have two PCL, both of type pcl::PointXYZL
, this is, there is a label/id info together with each point. I want to remove in PC B all the points existent in A (recognized by the label info).
An iteration of this type takes too much time.
I decide to save the labels from PC A into boost::container::flat_set<int> labels
, and set cloud B as std::map<int, pcl::PointXYZL> cloud_B
, where the key is the label/id from the point. Then I do:
for(boost::container::flat_set<int>::iterator it = labels.begin() ; it != labels.end(); ++it){
if ( auto point{ cloud_B.find( *it ) }; point != std::end(cloud_B)){
cloud_B.erase(*it);
}
}
It is now much much faster, but honestly, I think there may have a more efficient solution.
I also try:
for(boost::container::flat_set<int>::iterator it = labels.begin() ; it != labels.end(); ++it){
try{
cloud_B.erase(*it);
throw 505;
}
catch (...){
continue;
}
}
But it takes more time than the first example I brought.
I appreciated any help with this!
Upvotes: 1
Views: 925
Reputation: 81
This is my solution so far...
First, I set both clouds as type std::map<int, pcl::PointXYZL>
. Remembering that I want to remove from cloud_B all points that are in cloud_A. Then:
std::map<int, pcl::PointXYZL>::iterator it = cloud_B.begin();
for ( ; it != cloud_B.end(); ){
if (auto point{ cloud_A.find(it->first) }; point != std::end(cloud_A)){ // if the label was found
it = cloud_B.erase(it);
}
else
++it;
}
Upvotes: 0
Reputation: 725
Both of your solution are roughly O(n^2) complexity.
Use unordered_set<std::uint32_t>
to check if it exist or not. the average case of unordered_set<std::uint32_t>::count
is constant, so it should be better than your solution
Sample code(untested) but you get the rough idea.
pcl::PointCloud<pcl::PointXYZL> cloud_a;
pcl::PointCloud<pcl::PointXYZL> cloud_b;
... (fill cloud)
// generate unordered_set<uint32_t> O(n)
std::unordered_set<std::uint32_t> labels_in_cloud_a;
for (int i = 0; i < cloud_a.size(); ++i) {
labels_in_cloud_a.insert(cloud_a.points[i].label);
}
// indices where in cloud_b where label doesn't exist in labels_in_clouda O(n*1) = O(n)
std::vector<int> indices;
for (int i = 0; i < cloud_b.size(); ++i) {
if (labels_in_cloud_a.count(cloud_b.points[i].label) == 0) {
indices.push_back(i);
}
}
// only indices that doesn't exist in cloud_a will remain. O(n)
pcl::copyPointCloud(cloud_b, indices, cloud_b);
Upvotes: 1