PointViewSet PMFFilter::run(PointViewPtr input) { bool logOutput = log()->getLevel() > LogLevel::Debug1; if (logOutput) log()->floatPrecision(8); log()->get(LogLevel::Debug2) << "Process PMFFilter...\n"; auto idx = processGround(input); PointViewSet viewSet; if (!idx.empty() && (m_classify || m_extract)) { if (m_classify) { log()->get(LogLevel::Debug2) << "Labeled " << idx.size() << " ground returns!\n"; // set the classification label of ground returns as 2 // (corresponding to ASPRS LAS specification) for (const auto& i : idx) { input->setField(Dimension::Id::Classification, i, 2); } viewSet.insert(input); } if (m_extract) { log()->get(LogLevel::Debug2) << "Extracted " << idx.size() << " ground returns!\n"; // create new PointView containing only ground returns PointViewPtr output = input->makeNew(); for (const auto& i : idx) { output->appendPoint(*input, i); } viewSet.erase(input); viewSet.insert(output); } } else { if (idx.empty()) log()->get(LogLevel::Debug2) << "Filtered cloud has no ground returns!\n"; if (!(m_classify || m_extract)) log()->get(LogLevel::Debug2) << "Must choose --classify or --extract\n"; // return the input buffer unchanged viewSet.insert(input); } return viewSet; }
PointViewSet Stage::execute(PointTableRef table) { //printf("called %s\n", this->classname()); log()->setLevel(LogLevel::Enum::Debug); std::string cn(this->classname()); log()->setLeader(cn + " Stage::execute"); log()->get(LogLevel::Debug) << "Called by class " << std::endl; table.layout()->finalize(); PointViewSet views; if (m_inputs.empty()) { log()->get(LogLevel::Debug) << "if block, class" << std::endl; views.insert(PointViewPtr(new PointView(table))); } else { for (size_t i = 0; i < m_inputs.size(); ++i) { log()->get(LogLevel::Debug) << "block, class" << "input number "<< i << std::endl; log()->get(LogLevel::Debug) << "if block, class" << std::endl; Stage *prev = m_inputs[i]; PointViewSet temp = prev->execute(table); views.insert(temp.begin(), temp.end()); } } PointViewSet outViews; std::vector<StageRunnerPtr> runners; ready(table); for (auto const& it : views) { log()->get(LogLevel::Debug) << "run, class" << std::endl; StageRunnerPtr runner(new StageRunner(this, it)); runners.push_back(runner); runner->run(); } for (auto const& it : runners) { log()->get(LogLevel::Debug) << "wait, class" << std::endl; StageRunnerPtr runner(it); PointViewSet temp = runner->wait(); outViews.insert(temp.begin(), temp.end()); } l_done(table); done(table); return outViews; }
PointViewSet SMRFilter::run(PointViewPtr view) { log()->get(LogLevel::Info) << "run: Process SMRFilter...\n"; std::vector<PointId> idx = processGround(view); PointViewSet viewSet; if (!idx.empty() && (m_classify || m_extract)) { if (m_classify) { log()->get(LogLevel::Info) << "run: Labeled " << idx.size() << " ground returns!\n"; // set the classification label of ground returns as 2 // (corresponding to ASPRS LAS specification) for (const auto& i : idx) { view->setField(Dimension::Id::Classification, i, 2); } viewSet.insert(view); } if (m_extract) { log()->get(LogLevel::Info) << "run: Extracted " << idx.size() << " ground returns!\n"; // create new PointView containing only ground returns PointViewPtr output = view->makeNew(); for (const auto& i : idx) { output->appendPoint(*view, i); } viewSet.erase(view); viewSet.insert(output); } } else { if (idx.empty()) log()->get(LogLevel::Info) << "run: Filtered cloud has no ground returns!\n"; if (!(m_classify || m_extract)) log()->get(LogLevel::Info) << "run: Must choose --classify or --extract\n"; // return the view buffer unchanged viewSet.insert(view); } return viewSet; }
virtual PointViewSet run(PointViewPtr view) { PointViewSet out; PointViewPtr v = view->makeNew(); for (PointId i = 0; i < view->size(); ++i) { if (i && (i % m_viewSize == 0)) { out.insert(v); v = v->makeNew(); } v->appendPoint(*view, i); } out.insert(v); return out; }
TEST(PointViewTest, order) { PointTable table; const size_t COUNT(1000); std::array<PointViewPtr, COUNT> views; std::random_device dev; std::mt19937 generator(dev()); for (size_t i = 0; i < COUNT; ++i) views[i] = PointViewPtr(new PointView(table)); std::shuffle(views.begin(), views.end(), generator); PointViewSet set; for (size_t i = 0; i < COUNT; ++i) set.insert(views[i]); PointViewSet::iterator pi; for (auto si = set.begin(); si != set.end(); ++si) { if (si != set.begin()) EXPECT_TRUE((*pi)->id() < (*si)->id()); pi = si; } }
PointViewSet PredicateFilter::run(PointViewPtr view) { MetadataNode n; m_pythonMethod->resetArguments(); m_pythonMethod->begin(*view, n); m_pythonMethod->execute(); if (!m_pythonMethod->hasOutputVariable("Mask")) throw pdal::pdal_error("Mask variable not set in predicate " "filter function."); PointViewPtr outview = view->makeNew(); void *pydata = m_pythonMethod->extractResult("Mask", Dimension::Type::Unsigned8); char *ok = (char *)pydata; for (PointId idx = 0; idx < view->size(); ++idx) if (*ok++) outview->appendPoint(*view, idx); PointViewSet viewSet; viewSet.insert(outview); return viewSet; }
PointViewSet LocateFilter::run(PointViewPtr inView) { PointViewSet viewSet; if (!inView->size()) return viewSet; PointId minidx, maxidx; double minval = (std::numeric_limits<double>::max)(); double maxval = std::numeric_limits<double>::lowest(); for (PointId idx = 0; idx < inView->size(); idx++) { double val = inView->getFieldAs<double>(m_dimId, idx); if (val > maxval) { maxval = val; maxidx = idx; } if (val < minval) { minval = val; minidx = idx; } } PointViewPtr outView = inView->makeNew(); if (Utils::iequals("min", m_minmax)) outView->appendPoint(*inView.get(), minidx); if (Utils::iequals("max", m_minmax)) outView->appendPoint(*inView.get(), maxidx); viewSet.insert(outView); return viewSet; }
PointViewSet DecimationFilter::run(PointViewPtr inView) { PointViewSet viewSet; PointViewPtr outView = inView->makeNew(); decimate(*inView.get(), *outView.get()); viewSet.insert(outView); return viewSet; }
PointViewSet run(PointViewPtr view) { if (m_count > view->size()) log()->get(LogLevel::Warning) << "Requested number of points (count=" << m_count << ") exceeds number of available points.\n"; PointViewSet viewSet; PointViewPtr outView = view->makeNew(); for (PointId i = view->size() - std::min(m_count, view->size()); i < view->size(); ++i) outView->appendPoint(*view, i); viewSet.insert(outView); return viewSet; }
PointViewSet MergeFilter::run(PointViewPtr in) { PointViewSet viewSet; // If the SRS of all the point views aren't the same, print a warning // unless we're explicitly overriding the SRS. if (getSpatialReference().empty() && (in->spatialReference() != m_view->spatialReference())) log()->get(LogLevel::Warning) << getName() << ": merging points " "with inconsistent spatial references." << std::endl; m_view->append(*in.get()); viewSet.insert(m_view); return viewSet; }
TEST(PointViewTest, calcBounds) { auto set_points = [](PointViewPtr view, PointId i, double x, double y, double z) { view->setField(Dimension::Id::X, i, x); view->setField(Dimension::Id::Y, i, y); view->setField(Dimension::Id::Z, i, z); }; PointTable table; PointLayoutPtr layout(table.layout()); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); layout->registerDim(Dimension::Id::Z); const double lim_min = (std::numeric_limits<double>::lowest)(); const double lim_max = (std::numeric_limits<double>::max)(); PointViewPtr b0(new PointView(table)); BOX3D box_b0; b0->calculateBounds(box_b0); check_bounds(box_b0, lim_max, lim_min, lim_max, lim_min, lim_max, lim_min); PointViewPtr b1(new PointView(table)); set_points(b1, 0, 0.0, 0.0, 0.0); set_points(b1, 1, 2.0, 2.0, 2.0); PointViewPtr b2(new PointView(table)); set_points(b2, 0, 3.0, 3.0, 3.0); set_points(b2, 1, 1.0, 1.0, 1.0); PointViewSet bs; bs.insert(b1); bs.insert(b2); BOX3D box_b1; b1->calculateBounds(box_b1); check_bounds(box_b1, 0.0, 2.0, 0.0, 2.0, 0.0, 2.0); BOX3D box_b2; b2->calculateBounds(box_b2); check_bounds(box_b2, 1.0, 3.0, 1.0, 3.0, 1.0, 3.0); BOX3D box_bs; PointView::calculateBounds(bs, box_bs); check_bounds(box_bs, 0.0, 3.0, 0.0, 3.0, 0.0, 3.0); }
PointViewSet SampleFilter::run(PointViewPtr inView) { point_count_t np = inView->size(); // Return empty PointViewSet if the input PointView has no points. // Otherwise, make a new output PointView. PointViewSet viewSet; if (!np) return viewSet; PointViewPtr outView = inView->makeNew(); // Build the 3D KD-tree. KD3Index index(*inView); index.build(); // All points are marked as kept (1) by default. As they are masked by // neighbors within the user-specified radius, their value is changed to 0. std::vector<int> keep(np, 1); // We are able to subsample in a single pass over the shuffled indices. for (PointId i = 0; i < np; ++i) { // If a point is masked, it is forever masked, and cannot be part of the // sampled cloud. Otherwise, the current index is appended to the output // PointView. if (keep[i] == 0) continue; outView->appendPoint(*inView, i); // We now proceed to mask all neighbors within m_radius of the kept // point. auto ids = index.radius(i, m_radius); for (auto const& id : ids) keep[id] = 0; } // Simply calculate the percentage of retained points. double frac = (double)outView->size() / (double)inView->size(); log()->get(LogLevel::Debug2) << "Retaining " << outView->size() << " of " << inView->size() << " points (" << 100 * frac << "%)\n"; viewSet.insert(outView); return viewSet; }
PointViewSet VoxelGridFilter::run(PointViewPtr input) { PointViewPtr output = input->makeNew(); PointViewSet viewSet; viewSet.insert(output); bool logOutput = log()->getLevel() > LogLevel::Debug1; if (logOutput) log()->floatPrecision(8); log()->get(LogLevel::Debug2) << "Process VoxelGridFilter..." << std::endl; BOX3D buffer_bounds; input->calculateBounds(buffer_bounds); // convert PointView to PointNormal typedef pcl::PointCloud<pcl::PointXYZ> Cloud; Cloud::Ptr cloud(new Cloud); pclsupport::PDALtoPCD(input, *cloud, buffer_bounds); pclsupport::setLogLevel(log()->getLevel()); // initial setup pcl::VoxelGrid<pcl::PointXYZ> vg; vg.setInputCloud(cloud); vg.setLeafSize(m_leaf_x, m_leaf_y, m_leaf_z); // create PointCloud for results Cloud::Ptr cloud_f(new Cloud); vg.filter(*cloud_f); if (cloud_f->points.empty()) { log()->get(LogLevel::Debug2) << "Filtered cloud has no points!" << std::endl; return viewSet; } pclsupport::PCDtoPDAL(*cloud_f, output, buffer_bounds); log()->get(LogLevel::Debug2) << cloud->points.size() << " before, " << cloud_f->points.size() << " after" << std::endl; log()->get(LogLevel::Debug2) << output->size() << std::endl; return viewSet; }
PointViewSet RangeFilter::run(PointViewPtr inView) { PointViewSet viewSet; if (!inView->size()) return viewSet; PointViewPtr outView = inView->makeNew(); for (PointId i = 0; i < inView->size(); ++i) { PointRef point = inView->point(i); if (processOne(point)) outView->appendPoint(*inView, i); } viewSet.insert(outView); return viewSet; }
PointViewSet MADFilter::run(PointViewPtr view) { using namespace Dimension; PointViewSet viewSet; PointViewPtr output = view->makeNew(); auto estimate_median = [](std::vector<double> vals) { std::nth_element(vals.begin(), vals.begin()+vals.size()/2, vals.end()); return *(vals.begin()+vals.size()/2); }; std::vector<double> z(view->size()); for (PointId j = 0; j < view->size(); ++j) z[j] = view->getFieldAs<double>(m_dimId, j); double median = estimate_median(z); log()->get(LogLevel::Debug) << getName() << " estimated median value: " << median << std::endl; std::transform(z.begin(), z.end(), z.begin(), [median](double v) { return std::fabs(v - median); }); double mad = estimate_median(z)*m_madMultiplier; log()->get(LogLevel::Debug) << getName() << " mad " << mad << std::endl; for (PointId j = 0; j < view->size(); ++j) { if (z[j]/mad < m_multiplier) output->appendPoint(*view, j); } double low_fence = median - m_multiplier * mad; double hi_fence = median + m_multiplier * mad; log()->get(LogLevel::Debug) << getName() << " cropping " << m_dimName << " in the range (" << low_fence << "," << hi_fence << ")" << std::endl; viewSet.erase(view); viewSet.insert(output); return viewSet; }
PointViewSet SplitterFilter::run(PointViewPtr inView) { PointViewSet viewSet; if (!inView->size()) return viewSet; // Use the location of the first point as the origin, unless specified. // (!= test == isnan(), which doesn't exist on windows) if (m_xOrigin != m_xOrigin) m_xOrigin = inView->getFieldAs<double>(Dimension::Id::X, 0); if (m_yOrigin != m_yOrigin) m_yOrigin = inView->getFieldAs<double>(Dimension::Id::Y, 0); // Overlay a grid of squares on the points (m_length sides). Each square // corresponds to a new point buffer. Place the points falling in the // each square in the corresponding point buffer. for (PointId idx = 0; idx < inView->size(); idx++) { double x = inView->getFieldAs<double>(Dimension::Id::X, idx); x -= m_xOrigin; int xpos = x / m_length; if (x < 0) xpos--; double y = inView->getFieldAs<double>(Dimension::Id::Y, idx); y -= m_yOrigin; int ypos = y / m_length; if (y < 0) ypos--; Coord loc(xpos, ypos); PointViewPtr& outView = m_viewMap[loc]; if (!outView) outView = inView->makeNew(); outView->appendPoint(*inView.get(), idx); } // Pull the buffers out of the map and stick them in the standard // output set. for (auto bi = m_viewMap.begin(); bi != m_viewMap.end(); ++bi) viewSet.insert(bi->second); return viewSet; }
PointViewSet GroupByFilter::run(PointViewPtr inView) { PointViewSet viewSet; if (!inView->size()) return viewSet; for (PointId idx = 0; idx < inView->size(); idx++) { uint64_t val = inView->getFieldAs<uint64_t>(m_dimId, idx); PointViewPtr& outView = m_viewMap[val]; if (!outView) outView = inView->makeNew(); outView->appendPoint(*inView.get(), idx); } // Pull the buffers out of the map and stick them in the standard // output set. for (auto bi = m_viewMap.begin(); bi != m_viewMap.end(); ++bi) viewSet.insert(bi->second); return viewSet; }
PointViewSet StatisticalOutlierFilter::run(PointViewPtr input) { bool logOutput = log()->getLevel() > LogLevel::Debug1; if (logOutput) log()->floatPrecision(8); log()->get(LogLevel::Debug2) << "Process StatisticalOutlierFilter...\n"; // convert PointView to PointXYZ typedef pcl::PointCloud<pcl::PointXYZ> Cloud; Cloud::Ptr cloud(new Cloud); BOX3D bounds; input->calculateBounds(bounds); pclsupport::PDALtoPCD(input, *cloud, bounds); // PCL should provide console output at similar verbosity level as PDAL int level = log()->getLevel(); switch (level) { case 0: pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS); break; case 1: pcl::console::setVerbosityLevel(pcl::console::L_ERROR); break; case 2: pcl::console::setVerbosityLevel(pcl::console::L_WARN); break; case 3: pcl::console::setVerbosityLevel(pcl::console::L_INFO); break; case 4: pcl::console::setVerbosityLevel(pcl::console::L_DEBUG); break; default: pcl::console::setVerbosityLevel(pcl::console::L_VERBOSE); break; } // setup the outlier filter pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor(true); sor.setInputCloud(cloud); sor.setMeanK(m_meanK); sor.setStddevMulThresh(m_multiplier); pcl::PointCloud<pcl::PointXYZ> output; sor.setNegative(true); sor.filter(output); // filtered to return inliers pcl::PointIndicesPtr inliers(new pcl::PointIndices); sor.getRemovedIndices(*inliers); log()->get(LogLevel::Debug2) << inliers->indices.size() << std::endl; PointViewSet viewSet; if (inliers->indices.empty()) { log()->get(LogLevel::Warning) << "Requested filter would remove all points. Try increasing the multiplier.\n"; viewSet.insert(input); return viewSet; } // inverse are the outliers std::vector<int> outliers(input->size()-inliers->indices.size()); for (PointId i = 0, j = 0, k = 0; i < input->size(); ++i) { if (i == (PointId)inliers->indices[j]) { j++; continue; } outliers[k++] = i; } if (!outliers.empty() && (m_classify || m_extract)) { if (m_classify) { log()->get(LogLevel::Debug2) << "Labeled " << outliers.size() << " outliers as noise!\n"; // set the classification label of outlier returns as 18 // (corresponding to ASPRS LAS specification for high noise) for (const auto& i : outliers) { input->setField(Dimension::Id::Classification, i, 18); } viewSet.insert(input); } if (m_extract) { log()->get(LogLevel::Debug2) << "Extracted " << inliers->indices.size() << " inliers!\n"; // create new PointView containing only outliers PointViewPtr output = input->makeNew(); for (const auto& i : inliers->indices) { output->appendPoint(*input, i); } viewSet.erase(input); viewSet.insert(output); } } else { if (outliers.empty()) log()->get(LogLevel::Warning) << "Filtered cloud has no outliers!\n"; if (!(m_classify || m_extract)) log()->get(LogLevel::Warning) << "Must choose --classify or --extract\n"; // return the input buffer unchanged viewSet.insert(input); } return viewSet; }
PointViewSet DartSampleFilter::run(PointViewPtr input) { PointViewSet viewSet; PointViewPtr output = input->makeNew(); log()->floatPrecision(2); log()->get(LogLevel::Info) << "DartSampleFilter (radius=" << m_radius << ")\n"; BOX3D buffer_bounds; input->calculateBounds(buffer_bounds); typedef pcl::PointCloud<pcl::PointXYZ> Cloud; Cloud::Ptr cloud(new Cloud); pclsupport::PDALtoPCD(input, *cloud, buffer_bounds); int level = log()->getLevel(); switch (level) { case 0: pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS); break; case 1: pcl::console::setVerbosityLevel(pcl::console::L_ERROR); break; case 2: pcl::console::setVerbosityLevel(pcl::console::L_WARN); break; case 3: pcl::console::setVerbosityLevel(pcl::console::L_INFO); break; case 4: pcl::console::setVerbosityLevel(pcl::console::L_DEBUG); break; default: pcl::console::setVerbosityLevel(pcl::console::L_VERBOSE); break; } pcl::DartSample<pcl::PointXYZ> ds; ds.setInputCloud(cloud); ds.setRadius(m_radius); std::vector<int> samples; ds.filter(samples); if (samples.empty()) { log()->get(LogLevel::Warning) << "Filtered cloud has no points!\n"; return viewSet; } for (const auto& i : samples) output->appendPoint(*input, i); double frac = (double)samples.size() / (double)cloud->size(); log()->get(LogLevel::Info) << "Retaining " << samples.size() << " of " << cloud->size() << " points (" << 100*frac << "%)\n"; viewSet.insert(output); return viewSet; }
PointViewSet RadiusOutlierFilter::run(PointViewPtr input) { bool logOutput = log()->getLevel() > LogLevel::Debug1; if (logOutput) log()->floatPrecision(8); log()->get(LogLevel::Debug2) << "Process RadiusOutlierFilter...\n"; // convert PointView to PointXYZ typedef pcl::PointCloud<pcl::PointXYZ> Cloud; Cloud::Ptr cloud(new Cloud); BOX3D bounds; input->calculateBounds(bounds); pclsupport::PDALtoPCD(input, *cloud, bounds); pclsupport::setLogLevel(log()->getLevel()); // setup the outlier filter pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror(true); ror.setInputCloud(cloud); ror.setMinNeighborsInRadius(m_min_neighbors); ror.setRadiusSearch(m_radius); pcl::PointCloud<pcl::PointXYZ> output; ror.setNegative(true); ror.filter(output); // filtered to return inliers pcl::PointIndicesPtr inliers(new pcl::PointIndices); ror.getRemovedIndices(*inliers); PointViewSet viewSet; if (inliers->indices.empty()) { log()->get(LogLevel::Warning) << "Requested filter would remove all points. Try a larger radius/smaller minimum neighbors.\n"; viewSet.insert(input); return viewSet; } // inverse are the outliers std::vector<int> outliers(input->size()-inliers->indices.size()); for (PointId i = 0, j = 0, k = 0; i < input->size(); ++i) { if (i == (PointId)inliers->indices[j]) { j++; continue; } outliers[k++] = i; } if (!outliers.empty() && (m_classify || m_extract)) { if (m_classify) { log()->get(LogLevel::Debug2) << "Labeled " << outliers.size() << " outliers as noise!\n"; // set the classification label of outlier returns as 18 // (corresponding to ASPRS LAS specification for high noise) for (const auto& i : outliers) { input->setField(Dimension::Id::Classification, i, 18); } viewSet.insert(input); } if (m_extract) { log()->get(LogLevel::Debug2) << "Extracted " << inliers->indices.size() << " inliers!\n"; // create new PointView containing only outliers PointViewPtr output = input->makeNew(); for (const auto& i : inliers->indices) { output->appendPoint(*input, i); } viewSet.erase(input); viewSet.insert(output); } } else { if (outliers.empty()) log()->get(LogLevel::Warning) << "Filtered cloud has no outliers!\n"; if (!(m_classify || m_extract)) log()->get(LogLevel::Warning) << "Must choose --classify or --extract\n"; // return the input buffer unchanged viewSet.insert(input); } return viewSet; }
PointViewSet Stage::execute(PointTableRef table) { table.finalize(); PointViewSet views; // If the inputs are empty, we're a reader. if (m_inputs.empty()) { views.insert(PointViewPtr(new PointView(table))); } else { for (size_t i = 0; i < m_inputs.size(); ++i) { Stage *prev = m_inputs[i]; PointViewSet temp = prev->execute(table); views.insert(temp.begin(), temp.end()); } } PointViewSet outViews; std::vector<StageRunnerPtr> runners; // Put the spatial references from the views onto the table. // The table's spatial references are only valid as long as the stage // is running. // ABELL - Should we clear the references once the stage run has // completed? Wondering if that would break something where a // writer wants to check a table's SRS. SpatialReference srs; table.clearSpatialReferences(); for (auto const& it : views) table.addSpatialReference(it->spatialReference()); // Do the ready operation and then start running all the views // through the stage. ready(table); for (auto const& it : views) { StageRunnerPtr runner(new StageRunner(this, it)); runners.push_back(runner); runner->run(); } // As the stages complete (synchronously at this time), propagate the // spatial reference and merge the output views. srs = getSpatialReference(); for (auto const& it : runners) { StageRunnerPtr runner(it); PointViewSet temp = runner->wait(); // If our stage has a spatial reference, the view takes it on once // the stage has been run. if (!srs.empty()) for (PointViewPtr v : temp) v->setSpatialReference(srs); outViews.insert(temp.begin(), temp.end()); } done(table); return outViews; }
PointViewSet MyFilter::run(PointViewPtr input) { PointViewSet viewSet; viewSet.insert(input); return viewSet; }
PointViewSet PoissonFilter::run(PointViewPtr input) { PointViewPtr output = input->makeNew(); PointViewSet viewSet; viewSet.insert(output); bool logOutput = log()->getLevel() > LogLevel::Debug1; if (logOutput) log()->floatPrecision(8); log()->get(LogLevel::Debug2) << "Process PoissonFilter..." << std::endl; BOX3D buffer_bounds; input->calculateBounds(buffer_bounds); // convert PointView to PointNormal typedef pcl::PointCloud<pcl::PointXYZ> Cloud; Cloud::Ptr cloud(new Cloud); pclsupport::PDALtoPCD(input, *cloud, buffer_bounds); pclsupport::setLogLevel(log()->getLevel()); // pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree; pcl::search::KdTree<pcl::PointNormal>::Ptr tree2; // Create search tree tree.reset(new pcl::search::KdTree<pcl::PointXYZ> (false)); tree->setInputCloud(cloud); // Normal estimation pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n; pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal> ()); n.setInputCloud(cloud); n.setSearchMethod(tree); n.setKSearch(20); n.compute(*normals); // Concatenate XYZ and normal information pcl::concatenateFields(*cloud, *normals, *cloud_with_normals); // Create search tree tree2.reset(new pcl::search::KdTree<pcl::PointNormal>); tree2->setInputCloud(cloud_with_normals); // initial setup pcl::Poisson<pcl::PointNormal> p; p.setInputCloud(cloud_with_normals); p.setSearchMethod(tree2); p.setDepth(m_depth); p.setPointWeight(m_point_weight); // create PointCloud for results pcl::PolygonMesh grid; p.reconstruct(grid); Cloud::Ptr cloud_f(new Cloud); pcl::fromPCLPointCloud2(grid.cloud, *cloud_f); if (cloud_f->points.empty()) { log()->get(LogLevel::Debug2) << "Filtered cloud has no points!" << std::endl; return viewSet; } pclsupport::PCDtoPDAL(*cloud_f, output, buffer_bounds); log()->get(LogLevel::Debug2) << cloud->points.size() << " before, " << cloud_f->points.size() << " after" << std::endl; log()->get(LogLevel::Debug2) << output->size() << std::endl; return viewSet; }