WIP on removing unused parts of pad
This commit is contained in:
parent
90a854f704
commit
778b2cf293
@ -666,24 +666,19 @@ Polygons concave_hull(const Polygons& polys, double max_dist_mm = 50,
|
||||
return punion;
|
||||
}
|
||||
|
||||
void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h,
|
||||
float layerh, ThrowOnCancel thrfn)
|
||||
void base_plate(const TriangleMesh & mesh,
|
||||
ExPolygons & output,
|
||||
const std::vector<float> &heights,
|
||||
ThrowOnCancel thrfn)
|
||||
{
|
||||
TriangleMesh m = mesh;
|
||||
m.require_shared_vertices(); // TriangleMeshSlicer needs this
|
||||
TriangleMeshSlicer slicer(&m);
|
||||
|
||||
auto bb = mesh.bounding_box();
|
||||
float gnd = float(bb.min(Z));
|
||||
std::vector<float> heights = {float(bb.min(Z))};
|
||||
for(float hi = gnd + layerh; hi <= gnd + h; hi += layerh)
|
||||
heights.emplace_back(hi);
|
||||
|
||||
std::vector<ExPolygons> out; out.reserve(size_t(std::ceil(h/layerh)));
|
||||
// m.require_shared_vertices(); // TriangleMeshSlicer needs this
|
||||
TriangleMeshSlicer slicer(&mesh);
|
||||
|
||||
std::vector<ExPolygons> out; out.reserve(heights.size());
|
||||
slicer.slice(heights, 0.f, &out, thrfn);
|
||||
|
||||
|
||||
size_t count = 0; for(auto& o : out) count += o.size();
|
||||
|
||||
|
||||
// Now we have to unify all slice layers which can be an expensive operation
|
||||
// so we will try to simplify the polygons
|
||||
ExPolygons tmp; tmp.reserve(count);
|
||||
@ -692,15 +687,31 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h,
|
||||
auto&& exss = e.simplify(scaled(0.1));
|
||||
for(ExPolygon& ep : exss) tmp.emplace_back(std::move(ep));
|
||||
}
|
||||
|
||||
|
||||
ExPolygons utmp = unify(tmp);
|
||||
|
||||
|
||||
for(auto& o : utmp) {
|
||||
auto&& smp = o.simplify(scaled(0.1));
|
||||
output.insert(output.end(), smp.begin(), smp.end());
|
||||
}
|
||||
}
|
||||
|
||||
void base_plate(const TriangleMesh &mesh,
|
||||
ExPolygons & output,
|
||||
float h,
|
||||
float layerh,
|
||||
ThrowOnCancel thrfn)
|
||||
{
|
||||
auto bb = mesh.bounding_box();
|
||||
float gnd = float(bb.min(Z));
|
||||
std::vector<float> heights = {float(bb.min(Z))};
|
||||
|
||||
for(float hi = gnd + layerh; hi <= gnd + h; hi += layerh)
|
||||
heights.emplace_back(hi);
|
||||
|
||||
base_plate(mesh, output, heights, thrfn);
|
||||
}
|
||||
|
||||
Contour3D create_base_pool(const Polygons &ground_layer,
|
||||
const ExPolygons &obj_self_pad = {},
|
||||
const PoolConfig& cfg = PoolConfig())
|
||||
|
@ -21,10 +21,15 @@ using ThrowOnCancel = std::function<void(void)>;
|
||||
/// Calculate the polygon representing the silhouette from the specified height
|
||||
void base_plate(const TriangleMesh& mesh, // input mesh
|
||||
ExPolygons& output, // Output will be merged with
|
||||
float zlevel = 0.1f, // Plate creation level
|
||||
float samplingheight = 0.1f, // The height range to sample
|
||||
float layerheight = 0.05f, // The sampling height
|
||||
ThrowOnCancel thrfn = [](){}); // Will be called frequently
|
||||
|
||||
void base_plate(const TriangleMesh& mesh, // input mesh
|
||||
ExPolygons& output, // Output will be merged with
|
||||
const std::vector<float>&, // Exact Z levels to sample
|
||||
ThrowOnCancel thrfn = [](){}); // Will be called frequently
|
||||
|
||||
// Function to cut tiny connector cavities for a given polygon. The input poly
|
||||
// will be offsetted by "padding" and small rectangle shaped cavities will be
|
||||
// inserted along the perimeter in every "stride" distance. The stick rectangles
|
||||
|
@ -7,13 +7,15 @@
|
||||
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <libslic3r/BoundingBox.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace sla {
|
||||
|
||||
typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> Vec3d;
|
||||
using SpatElement = std::pair<Vec3d, unsigned>;
|
||||
using PointIndexEl = std::pair<Vec3d, unsigned>;
|
||||
|
||||
class SpatIndex {
|
||||
class PointIndex {
|
||||
class Impl;
|
||||
|
||||
// We use Pimpl because it takes a long time to compile boost headers which
|
||||
@ -21,30 +23,67 @@ class SpatIndex {
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
public:
|
||||
|
||||
SpatIndex();
|
||||
~SpatIndex();
|
||||
PointIndex();
|
||||
~PointIndex();
|
||||
|
||||
SpatIndex(const SpatIndex&);
|
||||
SpatIndex(SpatIndex&&);
|
||||
SpatIndex& operator=(const SpatIndex&);
|
||||
SpatIndex& operator=(SpatIndex&&);
|
||||
PointIndex(const PointIndex&);
|
||||
PointIndex(PointIndex&&);
|
||||
PointIndex& operator=(const PointIndex&);
|
||||
PointIndex& operator=(PointIndex&&);
|
||||
|
||||
void insert(const SpatElement&);
|
||||
bool remove(const SpatElement&);
|
||||
void insert(const PointIndexEl&);
|
||||
bool remove(const PointIndexEl&);
|
||||
|
||||
inline void insert(const Vec3d& v, unsigned idx)
|
||||
{
|
||||
insert(std::make_pair(v, unsigned(idx)));
|
||||
}
|
||||
|
||||
std::vector<SpatElement> query(std::function<bool(const SpatElement&)>);
|
||||
std::vector<SpatElement> nearest(const Vec3d&, unsigned k);
|
||||
std::vector<PointIndexEl> query(std::function<bool(const PointIndexEl&)>);
|
||||
std::vector<PointIndexEl> nearest(const Vec3d&, unsigned k);
|
||||
|
||||
// For testing
|
||||
size_t size() const;
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
void foreach(std::function<void(const SpatElement& el)> fn);
|
||||
void foreach(std::function<void(const PointIndexEl& el)> fn);
|
||||
};
|
||||
|
||||
using BoxIndexEl = std::pair<Slic3r::BoundingBox, unsigned>;
|
||||
|
||||
class BoxIndex {
|
||||
class Impl;
|
||||
|
||||
// We use Pimpl because it takes a long time to compile boost headers which
|
||||
// is the engine of this class. We include it only in the cpp file.
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
public:
|
||||
|
||||
BoxIndex();
|
||||
~BoxIndex();
|
||||
|
||||
BoxIndex(const BoxIndex&);
|
||||
BoxIndex(BoxIndex&&);
|
||||
BoxIndex& operator=(const BoxIndex&);
|
||||
BoxIndex& operator=(BoxIndex&&);
|
||||
|
||||
void insert(const BoxIndexEl&);
|
||||
inline void insert(const BoundingBox& bb, unsigned idx)
|
||||
{
|
||||
insert(std::make_pair(bb, unsigned(idx)));
|
||||
}
|
||||
|
||||
bool remove(const BoxIndexEl&);
|
||||
|
||||
enum QueryType { qtIntersects, qtWithin };
|
||||
|
||||
std::vector<BoxIndexEl> query(const BoundingBox&, QueryType qt);
|
||||
|
||||
// For testing
|
||||
size_t size() const;
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
void foreach(std::function<void(const BoxIndexEl& el)> fn);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -569,37 +569,74 @@ struct Pad {
|
||||
sla::get_pad_elevation(pcfg))
|
||||
{
|
||||
Polygons basep;
|
||||
cfg.throw_on_cancel();
|
||||
auto &thr = cfg.throw_on_cancel;
|
||||
|
||||
// The 0.1f is the layer height with which the mesh is sampled and then
|
||||
// the layers are unified into one vector of polygons.
|
||||
ExPolygons platetmp;
|
||||
base_plate(object_support_mesh, platetmp,
|
||||
float(cfg.min_wall_height_mm + cfg.min_wall_thickness_mm),
|
||||
0.1f, pcfg.throw_on_cancel);
|
||||
thr();
|
||||
|
||||
for (const ExPolygon &bp : platetmp) basep.emplace_back(bp.contour);
|
||||
// Get a sample for the pad from the support mesh
|
||||
{
|
||||
ExPolygons platetmp;
|
||||
float plateZ = float(get_pad_fullheight(pcfg) + EPSILON);
|
||||
|
||||
base_plate(object_support_mesh, platetmp, plateZ, 0.1f, thr);
|
||||
|
||||
// We don't need no... holes control...
|
||||
for (const ExPolygon &bp : platetmp)
|
||||
basep.emplace_back(std::move(bp.contour));
|
||||
}
|
||||
|
||||
if(pcfg.embed_object) {
|
||||
ExPolygons modelbase_sticks = modelbase;
|
||||
|
||||
// If the zero elevation mode is ON, we need to process the model
|
||||
// base silhouette. Create the offsetted version and punch the
|
||||
// breaksticks across its perimeter.
|
||||
|
||||
ExPolygons modelbase_sticks = modelbase;
|
||||
|
||||
if (pcfg.embed_object.object_gap_mm > 0.0)
|
||||
modelbase_sticks
|
||||
= offset_ex(modelbase_sticks,
|
||||
coord_t(pcfg.embed_object.object_gap_mm
|
||||
/ SCALING_FACTOR));
|
||||
float(scaled(pcfg.embed_object.object_gap_mm)));
|
||||
|
||||
BoxIndex bindex;
|
||||
{
|
||||
unsigned idx = 0;
|
||||
for(auto &bp : basep) {
|
||||
auto bb = bp.bounding_box();
|
||||
bb.offset(float(scaled(pcfg.min_wall_thickness_mm)));
|
||||
bindex.insert(bb, idx++);
|
||||
}
|
||||
}
|
||||
|
||||
ExPolygons pad_stickholes; pad_stickholes.reserve(modelbase.size());
|
||||
for(auto& poly : modelbase_sticks) {
|
||||
basep.emplace_back(poly.contour);
|
||||
sla::breakstick_holes(
|
||||
poly,
|
||||
pcfg.embed_object.object_gap_mm, // padding
|
||||
pcfg.embed_object.stick_stride_mm,
|
||||
pcfg.embed_object.stick_width_mm,
|
||||
pcfg.embed_object.stick_penetration_mm);
|
||||
|
||||
if (!bindex.query(poly.contour.bounding_box(),
|
||||
BoxIndex::qtIntersects).empty()) {
|
||||
|
||||
basep.emplace_back(poly.contour);
|
||||
|
||||
auto it = poly.holes.begin();
|
||||
while(it != poly.holes.end()) {
|
||||
if (bindex.query(it->bounding_box(),
|
||||
BoxIndex::qtIntersects).empty())
|
||||
it = poly.holes.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
sla::breakstick_holes(
|
||||
poly,
|
||||
pcfg.embed_object.object_gap_mm, // padding
|
||||
pcfg.embed_object.stick_stride_mm,
|
||||
pcfg.embed_object.stick_width_mm,
|
||||
pcfg.embed_object.stick_penetration_mm);
|
||||
|
||||
pad_stickholes.emplace_back(poly);
|
||||
}
|
||||
}
|
||||
|
||||
create_base_pool(basep, tmesh, modelbase_sticks, cfg);
|
||||
create_base_pool(basep, tmesh, pad_stickholes, cfg);
|
||||
} else {
|
||||
for (const ExPolygon &bp : modelbase) basep.emplace_back(bp.contour);
|
||||
create_base_pool(basep, tmesh, {}, cfg);
|
||||
@ -630,7 +667,7 @@ inline Vec2d to_vec2(const Vec3d& v3) {
|
||||
return {v3(X), v3(Y)};
|
||||
}
|
||||
|
||||
bool operator==(const SpatElement& e1, const SpatElement& e2) {
|
||||
bool operator==(const PointIndexEl& e1, const PointIndexEl& e2) {
|
||||
return e1.second == e2.second;
|
||||
}
|
||||
|
||||
@ -647,7 +684,7 @@ ClusteredPoints cluster(const PointSet& points,
|
||||
ClusteredPoints cluster(
|
||||
const std::vector<unsigned>& indices,
|
||||
std::function<Vec3d(unsigned)> pointfn,
|
||||
std::function<bool(const SpatElement&, const SpatElement&)> predicate,
|
||||
std::function<bool(const PointIndexEl&, const PointIndexEl&)> predicate,
|
||||
unsigned max_points);
|
||||
|
||||
// This class will hold the support tree meshes with some additional bookkeeping
|
||||
@ -974,7 +1011,7 @@ class SLASupportTree::Algorithm {
|
||||
ThrowOnCancel m_thr;
|
||||
|
||||
// A spatial index to easily find strong pillars to connect to.
|
||||
SpatIndex m_pillar_index;
|
||||
PointIndex m_pillar_index;
|
||||
|
||||
inline double ray_mesh_intersect(const Vec3d& s,
|
||||
const Vec3d& dir)
|
||||
@ -1367,7 +1404,7 @@ class SLASupportTree::Algorithm {
|
||||
}
|
||||
|
||||
bool search_pillar_and_connect(const Head& head) {
|
||||
SpatIndex spindex = m_pillar_index;
|
||||
PointIndex spindex = m_pillar_index;
|
||||
|
||||
long nearest_id = -1;
|
||||
|
||||
@ -1747,8 +1784,8 @@ public:
|
||||
return m_result.head(i).junction_point();
|
||||
};
|
||||
|
||||
auto predicate = [this](const SpatElement &e1,
|
||||
const SpatElement &e2) {
|
||||
auto predicate = [this](const PointIndexEl &e1,
|
||||
const PointIndexEl &e2) {
|
||||
double d2d = distance(to_2d(e1.first), to_2d(e2.first));
|
||||
double d3d = distance(e1.first, e2.first);
|
||||
return d2d < 2 * m_cfg.base_radius_mm
|
||||
@ -2070,7 +2107,7 @@ public:
|
||||
// be connected multiple times this is ensured by the 'pairs' set which
|
||||
// remembers the processed pillar pairs
|
||||
auto cascadefn =
|
||||
[this, d, &pairs, min_height_ratio, H1] (const SpatElement& el)
|
||||
[this, d, &pairs, min_height_ratio, H1] (const PointIndexEl& el)
|
||||
{
|
||||
Vec3d qp = el.first; // endpoint of the pillar
|
||||
|
||||
@ -2083,13 +2120,13 @@ public:
|
||||
if(pillar.links >= neighbors) return;
|
||||
|
||||
// Query all remaining points within reach
|
||||
auto qres = m_pillar_index.query([qp, d](const SpatElement& e){
|
||||
auto qres = m_pillar_index.query([qp, d](const PointIndexEl& e){
|
||||
return distance(e.first, qp) < d;
|
||||
});
|
||||
|
||||
// sort the result by distance (have to check if this is needed)
|
||||
std::sort(qres.begin(), qres.end(),
|
||||
[qp](const SpatElement& e1, const SpatElement& e2){
|
||||
[qp](const PointIndexEl& e1, const PointIndexEl& e2){
|
||||
return distance(e1.first, qp) < distance(e2.first, qp);
|
||||
});
|
||||
|
||||
|
@ -29,69 +29,137 @@ namespace sla {
|
||||
using igl::PI;
|
||||
|
||||
/* **************************************************************************
|
||||
* SpatIndex implementation
|
||||
* PointIndex implementation
|
||||
* ************************************************************************** */
|
||||
|
||||
class SpatIndex::Impl {
|
||||
class PointIndex::Impl {
|
||||
public:
|
||||
using BoostIndex = boost::geometry::index::rtree< SpatElement,
|
||||
using BoostIndex = boost::geometry::index::rtree< PointIndexEl,
|
||||
boost::geometry::index::rstar<16, 4> /* ? */ >;
|
||||
|
||||
BoostIndex m_store;
|
||||
};
|
||||
|
||||
SpatIndex::SpatIndex(): m_impl(new Impl()) {}
|
||||
SpatIndex::~SpatIndex() {}
|
||||
PointIndex::PointIndex(): m_impl(new Impl()) {}
|
||||
PointIndex::~PointIndex() {}
|
||||
|
||||
SpatIndex::SpatIndex(const SpatIndex &cpy): m_impl(new Impl(*cpy.m_impl)) {}
|
||||
SpatIndex::SpatIndex(SpatIndex&& cpy): m_impl(std::move(cpy.m_impl)) {}
|
||||
PointIndex::PointIndex(const PointIndex &cpy): m_impl(new Impl(*cpy.m_impl)) {}
|
||||
PointIndex::PointIndex(PointIndex&& cpy): m_impl(std::move(cpy.m_impl)) {}
|
||||
|
||||
SpatIndex& SpatIndex::operator=(const SpatIndex &cpy)
|
||||
PointIndex& PointIndex::operator=(const PointIndex &cpy)
|
||||
{
|
||||
m_impl.reset(new Impl(*cpy.m_impl));
|
||||
return *this;
|
||||
}
|
||||
|
||||
SpatIndex& SpatIndex::operator=(SpatIndex &&cpy)
|
||||
PointIndex& PointIndex::operator=(PointIndex &&cpy)
|
||||
{
|
||||
m_impl.swap(cpy.m_impl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SpatIndex::insert(const SpatElement &el)
|
||||
void PointIndex::insert(const PointIndexEl &el)
|
||||
{
|
||||
m_impl->m_store.insert(el);
|
||||
}
|
||||
|
||||
bool SpatIndex::remove(const SpatElement& el)
|
||||
bool PointIndex::remove(const PointIndexEl& el)
|
||||
{
|
||||
return m_impl->m_store.remove(el) == 1;
|
||||
}
|
||||
|
||||
std::vector<SpatElement>
|
||||
SpatIndex::query(std::function<bool(const SpatElement &)> fn)
|
||||
std::vector<PointIndexEl>
|
||||
PointIndex::query(std::function<bool(const PointIndexEl &)> fn)
|
||||
{
|
||||
namespace bgi = boost::geometry::index;
|
||||
|
||||
std::vector<SpatElement> ret;
|
||||
std::vector<PointIndexEl> ret;
|
||||
m_impl->m_store.query(bgi::satisfies(fn), std::back_inserter(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<SpatElement> SpatIndex::nearest(const Vec3d &el, unsigned k = 1)
|
||||
std::vector<PointIndexEl> PointIndex::nearest(const Vec3d &el, unsigned k = 1)
|
||||
{
|
||||
namespace bgi = boost::geometry::index;
|
||||
std::vector<SpatElement> ret; ret.reserve(k);
|
||||
std::vector<PointIndexEl> ret; ret.reserve(k);
|
||||
m_impl->m_store.query(bgi::nearest(el, k), std::back_inserter(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t SpatIndex::size() const
|
||||
size_t PointIndex::size() const
|
||||
{
|
||||
return m_impl->m_store.size();
|
||||
}
|
||||
|
||||
void SpatIndex::foreach(std::function<void (const SpatElement &)> fn)
|
||||
void PointIndex::foreach(std::function<void (const PointIndexEl &)> fn)
|
||||
{
|
||||
for(auto& el : m_impl->m_store) fn(el);
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* BoxIndex implementation
|
||||
* ************************************************************************** */
|
||||
|
||||
class BoxIndex::Impl {
|
||||
public:
|
||||
using BoostIndex = boost::geometry::index::
|
||||
rtree<BoxIndexEl, boost::geometry::index::rstar<16, 4> /* ? */>;
|
||||
|
||||
BoostIndex m_store;
|
||||
};
|
||||
|
||||
BoxIndex::BoxIndex(): m_impl(new Impl()) {}
|
||||
BoxIndex::~BoxIndex() {}
|
||||
|
||||
BoxIndex::BoxIndex(const BoxIndex &cpy): m_impl(new Impl(*cpy.m_impl)) {}
|
||||
BoxIndex::BoxIndex(BoxIndex&& cpy): m_impl(std::move(cpy.m_impl)) {}
|
||||
|
||||
BoxIndex& BoxIndex::operator=(const BoxIndex &cpy)
|
||||
{
|
||||
m_impl.reset(new Impl(*cpy.m_impl));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BoxIndex& BoxIndex::operator=(BoxIndex &&cpy)
|
||||
{
|
||||
m_impl.swap(cpy.m_impl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void BoxIndex::insert(const BoxIndexEl &el)
|
||||
{
|
||||
m_impl->m_store.insert(el);
|
||||
}
|
||||
|
||||
bool BoxIndex::remove(const BoxIndexEl& el)
|
||||
{
|
||||
return m_impl->m_store.remove(el) == 1;
|
||||
}
|
||||
|
||||
std::vector<BoxIndexEl> BoxIndex::query(const BoundingBox &qrbb,
|
||||
BoxIndex::QueryType qt)
|
||||
{
|
||||
namespace bgi = boost::geometry::index;
|
||||
|
||||
std::vector<BoxIndexEl> ret; ret.reserve(m_impl->m_store.size());
|
||||
|
||||
switch (qt) {
|
||||
case qtIntersects:
|
||||
m_impl->m_store.query(bgi::intersects(qrbb), std::back_inserter(ret));
|
||||
break;
|
||||
case qtWithin:
|
||||
m_impl->m_store.query(bgi::within(qrbb), std::back_inserter(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t BoxIndex::size() const
|
||||
{
|
||||
return m_impl->m_store.size();
|
||||
}
|
||||
|
||||
void BoxIndex::foreach(std::function<void (const BoxIndexEl &)> fn)
|
||||
{
|
||||
for(auto& el : m_impl->m_store) fn(el);
|
||||
}
|
||||
@ -352,12 +420,14 @@ PointSet normals(const PointSet& points,
|
||||
return ret;
|
||||
}
|
||||
namespace bgi = boost::geometry::index;
|
||||
using Index3D = bgi::rtree< SpatElement, bgi::rstar<16, 4> /* ? */ >;
|
||||
using Index3D = bgi::rtree< PointIndexEl, bgi::rstar<16, 4> /* ? */ >;
|
||||
|
||||
ClusteredPoints cluster(Index3D& sindex, unsigned max_points,
|
||||
std::function<std::vector<SpatElement>(const Index3D&, const SpatElement&)> qfn)
|
||||
ClusteredPoints cluster(Index3D &sindex,
|
||||
unsigned max_points,
|
||||
std::function<std::vector<PointIndexEl>(
|
||||
const Index3D &, const PointIndexEl &)> qfn)
|
||||
{
|
||||
using Elems = std::vector<SpatElement>;
|
||||
using Elems = std::vector<PointIndexEl>;
|
||||
|
||||
// Recursive function for visiting all the points in a given distance to
|
||||
// each other
|
||||
@ -365,8 +435,8 @@ ClusteredPoints cluster(Index3D& sindex, unsigned max_points,
|
||||
[&sindex, &group, max_points, qfn](Elems& pts, Elems& cluster)
|
||||
{
|
||||
for(auto& p : pts) {
|
||||
std::vector<SpatElement> tmp = qfn(sindex, p);
|
||||
auto cmp = [](const SpatElement& e1, const SpatElement& e2){
|
||||
std::vector<PointIndexEl> tmp = qfn(sindex, p);
|
||||
auto cmp = [](const PointIndexEl& e1, const PointIndexEl& e2){
|
||||
return e1.second < e2.second;
|
||||
};
|
||||
|
||||
@ -410,12 +480,12 @@ ClusteredPoints cluster(Index3D& sindex, unsigned max_points,
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::vector<SpatElement> distance_queryfn(const Index3D& sindex,
|
||||
const SpatElement& p,
|
||||
std::vector<PointIndexEl> distance_queryfn(const Index3D& sindex,
|
||||
const PointIndexEl& p,
|
||||
double dist,
|
||||
unsigned max_points)
|
||||
{
|
||||
std::vector<SpatElement> tmp; tmp.reserve(max_points);
|
||||
std::vector<PointIndexEl> tmp; tmp.reserve(max_points);
|
||||
sindex.query(
|
||||
bgi::nearest(p.first, max_points),
|
||||
std::back_inserter(tmp)
|
||||
@ -442,7 +512,7 @@ ClusteredPoints cluster(
|
||||
for(auto idx : indices) sindex.insert( std::make_pair(pointfn(idx), idx));
|
||||
|
||||
return cluster(sindex, max_points,
|
||||
[dist, max_points](const Index3D& sidx, const SpatElement& p)
|
||||
[dist, max_points](const Index3D& sidx, const PointIndexEl& p)
|
||||
{
|
||||
return distance_queryfn(sidx, p, dist, max_points);
|
||||
});
|
||||
@ -452,7 +522,7 @@ ClusteredPoints cluster(
|
||||
ClusteredPoints cluster(
|
||||
const std::vector<unsigned>& indices,
|
||||
std::function<Vec3d(unsigned)> pointfn,
|
||||
std::function<bool(const SpatElement&, const SpatElement&)> predicate,
|
||||
std::function<bool(const PointIndexEl&, const PointIndexEl&)> predicate,
|
||||
unsigned max_points)
|
||||
{
|
||||
// A spatial index for querying the nearest points
|
||||
@ -462,10 +532,10 @@ ClusteredPoints cluster(
|
||||
for(auto idx : indices) sindex.insert( std::make_pair(pointfn(idx), idx));
|
||||
|
||||
return cluster(sindex, max_points,
|
||||
[max_points, predicate](const Index3D& sidx, const SpatElement& p)
|
||||
[max_points, predicate](const Index3D& sidx, const PointIndexEl& p)
|
||||
{
|
||||
std::vector<SpatElement> tmp; tmp.reserve(max_points);
|
||||
sidx.query(bgi::satisfies([p, predicate](const SpatElement& e){
|
||||
std::vector<PointIndexEl> tmp; tmp.reserve(max_points);
|
||||
sidx.query(bgi::satisfies([p, predicate](const PointIndexEl& e){
|
||||
return predicate(p, e);
|
||||
}), std::back_inserter(tmp));
|
||||
return tmp;
|
||||
@ -482,7 +552,7 @@ ClusteredPoints cluster(const PointSet& pts, double dist, unsigned max_points)
|
||||
sindex.insert(std::make_pair(Vec3d(pts.row(i)), unsigned(i)));
|
||||
|
||||
return cluster(sindex, max_points,
|
||||
[dist, max_points](const Index3D& sidx, const SpatElement& p)
|
||||
[dist, max_points](const Index3D& sidx, const PointIndexEl& p)
|
||||
{
|
||||
return distance_queryfn(sidx, p, dist, max_points);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user