Merge branch 'master' of https://github.com/Prusa3d/Slic3r
This commit is contained in:
commit
1925a34043
@ -2389,6 +2389,13 @@ void PrintConfigDef::init_sla_params()
|
|||||||
def->min = 100;
|
def->min = 100;
|
||||||
def->default_value = new ConfigOptionInt(1440);
|
def->default_value = new ConfigOptionInt(1440);
|
||||||
|
|
||||||
|
def = this->add("display_flip_xy", coBool);
|
||||||
|
def->label = ("Flip X and Y axis");
|
||||||
|
def->tooltip = L("Flip X and Y axis in the output raster");
|
||||||
|
def->cli = "display-flip-xy=i";
|
||||||
|
def->min = 0;
|
||||||
|
def->default_value = new ConfigOptionBool(true);
|
||||||
|
|
||||||
def = this->add("printer_correction", coFloats);
|
def = this->add("printer_correction", coFloats);
|
||||||
def->full_label = L("Printer scaling correction");
|
def->full_label = L("Printer scaling correction");
|
||||||
def->tooltip = L("Printer scaling correction");
|
def->tooltip = L("Printer scaling correction");
|
||||||
|
@ -1035,6 +1035,7 @@ public:
|
|||||||
ConfigOptionFloat display_height;
|
ConfigOptionFloat display_height;
|
||||||
ConfigOptionInt display_pixels_x;
|
ConfigOptionInt display_pixels_x;
|
||||||
ConfigOptionInt display_pixels_y;
|
ConfigOptionInt display_pixels_y;
|
||||||
|
ConfigOptionBool display_flip_xy;
|
||||||
ConfigOptionFloats printer_correction;
|
ConfigOptionFloats printer_correction;
|
||||||
protected:
|
protected:
|
||||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||||
@ -1046,6 +1047,7 @@ protected:
|
|||||||
OPT_PTR(display_height);
|
OPT_PTR(display_height);
|
||||||
OPT_PTR(display_pixels_x);
|
OPT_PTR(display_pixels_x);
|
||||||
OPT_PTR(display_pixels_y);
|
OPT_PTR(display_pixels_y);
|
||||||
|
OPT_PTR(display_flip_xy);
|
||||||
OPT_PTR(printer_correction);
|
OPT_PTR(printer_correction);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -447,8 +447,11 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h,
|
|||||||
ExPolygons tmp; tmp.reserve(count);
|
ExPolygons tmp; tmp.reserve(count);
|
||||||
for(auto& o : out) for(auto& e : o) tmp.emplace_back(std::move(e));
|
for(auto& o : out) for(auto& e : o) tmp.emplace_back(std::move(e));
|
||||||
|
|
||||||
output = unify(tmp);
|
ExPolygons utmp = unify(tmp);
|
||||||
for(auto& o : output) o = o.simplify(0.1/SCALING_FACTOR).front();
|
for(auto& o : utmp) {
|
||||||
|
auto&& smp = o.simplify(0.1/SCALING_FACTOR);
|
||||||
|
output.insert(output.end(), smp.begin(), smp.end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||||
|
@ -20,7 +20,6 @@ std::array<double, 3> find_best_rotation(const ModelObject& modelobj,
|
|||||||
using libnest2d::opt::Optimizer;
|
using libnest2d::opt::Optimizer;
|
||||||
using libnest2d::opt::TOptimizer;
|
using libnest2d::opt::TOptimizer;
|
||||||
using libnest2d::opt::StopCriteria;
|
using libnest2d::opt::StopCriteria;
|
||||||
using Quaternion = Eigen::Quaternion<double>;
|
|
||||||
|
|
||||||
static const unsigned MAX_TRIES = 100000;
|
static const unsigned MAX_TRIES = 100000;
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) {
|
|||||||
auto steps = int(ssteps);
|
auto steps = int(ssteps);
|
||||||
auto& points = ret.points;
|
auto& points = ret.points;
|
||||||
auto& indices = ret.indices;
|
auto& indices = ret.indices;
|
||||||
points.reserve(2*steps);
|
points.reserve(2*ssteps);
|
||||||
double a = 2*PI/steps;
|
double a = 2*PI/steps;
|
||||||
|
|
||||||
Vec3d jp = {0, 0, 0};
|
Vec3d jp = {0, 0, 0};
|
||||||
@ -189,7 +189,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) {
|
|||||||
points.emplace_back(x, y, jp(Z));
|
points.emplace_back(x, y, jp(Z));
|
||||||
}
|
}
|
||||||
|
|
||||||
indices.reserve(2*steps);
|
indices.reserve(2*ssteps);
|
||||||
auto offs = steps;
|
auto offs = steps;
|
||||||
for(int i = 0; i < steps - 1; ++i) {
|
for(int i = 0; i < steps - 1; ++i) {
|
||||||
indices.emplace_back(i, i + offs, offs + i + 1);
|
indices.emplace_back(i, i + offs, offs + i + 1);
|
||||||
@ -347,19 +347,22 @@ struct Pillar {
|
|||||||
double radius = 1, size_t st = 45):
|
double radius = 1, size_t st = 45):
|
||||||
r(radius), steps(st), endpoint(endp), starts_from_head(false)
|
r(radius), steps(st), endpoint(endp), starts_from_head(false)
|
||||||
{
|
{
|
||||||
|
assert(steps > 0);
|
||||||
|
int steps_1 = int(steps - 1);
|
||||||
|
|
||||||
auto& points = mesh.points;
|
auto& points = mesh.points;
|
||||||
auto& indices = mesh.indices;
|
auto& indices = mesh.indices;
|
||||||
points.reserve(2*steps);
|
points.reserve(2*steps);
|
||||||
double a = 2*PI/steps;
|
double a = 2*PI/steps;
|
||||||
|
|
||||||
for(int i = 0; i < steps; ++i) {
|
for(size_t i = 0; i < steps; ++i) {
|
||||||
double phi = i*a;
|
double phi = i*a;
|
||||||
double x = jp(X) + r*std::cos(phi);
|
double x = jp(X) + r*std::cos(phi);
|
||||||
double y = jp(Y) + r*std::sin(phi);
|
double y = jp(Y) + r*std::sin(phi);
|
||||||
points.emplace_back(x, y, jp(Z));
|
points.emplace_back(x, y, jp(Z));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < steps; ++i) {
|
for(size_t i = 0; i < steps; ++i) {
|
||||||
double phi = i*a;
|
double phi = i*a;
|
||||||
double ex = endp(X) + r*std::cos(phi);
|
double ex = endp(X) + r*std::cos(phi);
|
||||||
double ey = endp(Y) + r*std::sin(phi);
|
double ey = endp(Y) + r*std::sin(phi);
|
||||||
@ -368,14 +371,13 @@ struct Pillar {
|
|||||||
|
|
||||||
indices.reserve(2*steps);
|
indices.reserve(2*steps);
|
||||||
int offs = int(steps);
|
int offs = int(steps);
|
||||||
for(int i = 0; i < steps - 1; ++i) {
|
for(int i = 0; i < steps_1 ; ++i) {
|
||||||
indices.emplace_back(i, i + offs, offs + i + 1);
|
indices.emplace_back(i, i + offs, offs + i + 1);
|
||||||
indices.emplace_back(i, offs + i + 1, i + 1);
|
indices.emplace_back(i, offs + i + 1, i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int last = int(steps) - 1;
|
indices.emplace_back(0, steps_1, offs);
|
||||||
indices.emplace_back(0, last, offs);
|
indices.emplace_back(steps_1, offs + steps_1, offs);
|
||||||
indices.emplace_back(last, offs + last, offs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pillar(const Junction& junc, const Vec3d& endp):
|
Pillar(const Junction& junc, const Vec3d& endp):
|
||||||
@ -390,19 +392,22 @@ struct Pillar {
|
|||||||
void add_base(double height = 3, double radius = 2) {
|
void add_base(double height = 3, double radius = 2) {
|
||||||
if(height <= 0) return;
|
if(height <= 0) return;
|
||||||
|
|
||||||
|
assert(steps > 0);
|
||||||
|
auto last = int(steps - 1);
|
||||||
|
|
||||||
if(radius < r ) radius = r;
|
if(radius < r ) radius = r;
|
||||||
|
|
||||||
double a = 2*PI/steps;
|
double a = 2*PI/steps;
|
||||||
double z = endpoint(2) + height;
|
double z = endpoint(2) + height;
|
||||||
|
|
||||||
for(int i = 0; i < steps; ++i) {
|
for(size_t i = 0; i < steps; ++i) {
|
||||||
double phi = i*a;
|
double phi = i*a;
|
||||||
double x = endpoint(0) + r*std::cos(phi);
|
double x = endpoint(0) + r*std::cos(phi);
|
||||||
double y = endpoint(1) + r*std::sin(phi);
|
double y = endpoint(1) + r*std::sin(phi);
|
||||||
base.points.emplace_back(x, y, z);
|
base.points.emplace_back(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < steps; ++i) {
|
for(size_t i = 0; i < steps; ++i) {
|
||||||
double phi = i*a;
|
double phi = i*a;
|
||||||
double x = endpoint(0) + radius*std::cos(phi);
|
double x = endpoint(0) + radius*std::cos(phi);
|
||||||
double y = endpoint(1) + radius*std::sin(phi);
|
double y = endpoint(1) + radius*std::sin(phi);
|
||||||
@ -417,14 +422,13 @@ struct Pillar {
|
|||||||
auto hcenter = int(base.points.size() - 1);
|
auto hcenter = int(base.points.size() - 1);
|
||||||
auto lcenter = int(base.points.size() - 2);
|
auto lcenter = int(base.points.size() - 2);
|
||||||
auto offs = int(steps);
|
auto offs = int(steps);
|
||||||
for(int i = 0; i < steps - 1; ++i) {
|
for(int i = 0; i < last; ++i) {
|
||||||
indices.emplace_back(i, i + offs, offs + i + 1);
|
indices.emplace_back(i, i + offs, offs + i + 1);
|
||||||
indices.emplace_back(i, offs + i + 1, i + 1);
|
indices.emplace_back(i, offs + i + 1, i + 1);
|
||||||
indices.emplace_back(i, i + 1, hcenter);
|
indices.emplace_back(i, i + 1, hcenter);
|
||||||
indices.emplace_back(lcenter, offs + i + 1, offs + i);
|
indices.emplace_back(lcenter, offs + i + 1, offs + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto last = int(steps - 1);
|
|
||||||
indices.emplace_back(0, last, offs);
|
indices.emplace_back(0, last, offs);
|
||||||
indices.emplace_back(last, offs + last, offs);
|
indices.emplace_back(last, offs + last, offs);
|
||||||
indices.emplace_back(hcenter, last, 0);
|
indices.emplace_back(hcenter, last, 0);
|
||||||
@ -462,8 +466,6 @@ struct Bridge {
|
|||||||
Bridge(const Junction& j1, const Junction& j2, double r_mm = 0.8):
|
Bridge(const Junction& j1, const Junction& j2, double r_mm = 0.8):
|
||||||
Bridge(j1.pos, j2.pos, r_mm, j1.steps) {}
|
Bridge(j1.pos, j2.pos, r_mm, j1.steps) {}
|
||||||
|
|
||||||
Bridge(const Junction& j, const Pillar& cl) {}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A bridge that spans from model surface to model surface with small connecting
|
// A bridge that spans from model surface to model surface with small connecting
|
||||||
@ -537,12 +539,12 @@ EigenMesh3D to_eigenmesh(const Contour3D& cntr) {
|
|||||||
auto& V = emesh.V;
|
auto& V = emesh.V;
|
||||||
auto& F = emesh.F;
|
auto& F = emesh.F;
|
||||||
|
|
||||||
V.resize(cntr.points.size(), 3);
|
V.resize(Eigen::Index(cntr.points.size()), 3);
|
||||||
F.resize(cntr.indices.size(), 3);
|
F.resize(Eigen::Index(cntr.indices.size()), 3);
|
||||||
|
|
||||||
for (int i = 0; i < V.rows(); ++i) {
|
for (int i = 0; i < V.rows(); ++i) {
|
||||||
V.row(i) = cntr.points[i];
|
V.row(i) = cntr.points[size_t(i)];
|
||||||
F.row(i) = cntr.indices[i];
|
F.row(i) = cntr.indices[size_t(i)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return emesh;
|
return emesh;
|
||||||
@ -569,18 +571,23 @@ EigenMesh3D to_eigenmesh(const TriangleMesh& tmesh) {
|
|||||||
|
|
||||||
V.resize(3*stl.stats.number_of_facets, 3);
|
V.resize(3*stl.stats.number_of_facets, 3);
|
||||||
F.resize(stl.stats.number_of_facets, 3);
|
F.resize(stl.stats.number_of_facets, 3);
|
||||||
for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) {
|
for (unsigned int i = 0; i < stl.stats.number_of_facets; ++i) {
|
||||||
const stl_facet* facet = stl.facet_start+i;
|
const stl_facet* facet = stl.facet_start+i;
|
||||||
V(3*i+0, 0) = facet->vertex[0](0); V(3*i+0, 1) =
|
V(3*i+0, 0) = double(facet->vertex[0](0));
|
||||||
facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2);
|
V(3*i+0, 1) = double(facet->vertex[0](1));
|
||||||
V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) =
|
V(3*i+0, 2) = double(facet->vertex[0](2));
|
||||||
facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2);
|
|
||||||
V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) =
|
|
||||||
facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2);
|
|
||||||
|
|
||||||
F(i, 0) = 3*i+0;
|
V(3*i+1, 0) = double(facet->vertex[1](0));
|
||||||
F(i, 1) = 3*i+1;
|
V(3*i+1, 1) = double(facet->vertex[1](1));
|
||||||
F(i, 2) = 3*i+2;
|
V(3*i+1, 2) = double(facet->vertex[1](2));
|
||||||
|
|
||||||
|
V(3*i+2, 0) = double(facet->vertex[2](0));
|
||||||
|
V(3*i+2, 1) = double(facet->vertex[2](1));
|
||||||
|
V(3*i+2, 2) = double(facet->vertex[2](2));
|
||||||
|
|
||||||
|
F(i, 0) = int(3*i+0);
|
||||||
|
F(i, 1) = int(3*i+1);
|
||||||
|
F(i, 2) = int(3*i+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return outmesh;
|
return outmesh;
|
||||||
@ -630,7 +637,7 @@ class SLASupportTree::Impl {
|
|||||||
Controller m_ctl;
|
Controller m_ctl;
|
||||||
|
|
||||||
Pad m_pad;
|
Pad m_pad;
|
||||||
mutable TriangleMesh meshcache; mutable bool meshcache_valid;
|
mutable TriangleMesh meshcache; mutable bool meshcache_valid = false;
|
||||||
mutable double model_height = 0; // the full height of the model
|
mutable double model_height = 0; // the full height of the model
|
||||||
public:
|
public:
|
||||||
double ground_level = 0;
|
double ground_level = 0;
|
||||||
@ -649,7 +656,7 @@ public:
|
|||||||
|
|
||||||
template<class...Args> Pillar& add_pillar(long headid, Args&&... args) {
|
template<class...Args> Pillar& add_pillar(long headid, Args&&... args) {
|
||||||
assert(headid >= 0 && headid < m_heads.size());
|
assert(headid >= 0 && headid < m_heads.size());
|
||||||
Head& head = m_heads[headid];
|
Head& head = m_heads[size_t(headid)];
|
||||||
m_pillars.emplace_back(head, std::forward<Args>(args)...);
|
m_pillars.emplace_back(head, std::forward<Args>(args)...);
|
||||||
Pillar& pillar = m_pillars.back();
|
Pillar& pillar = m_pillars.back();
|
||||||
pillar.id = long(m_pillars.size() - 1);
|
pillar.id = long(m_pillars.size() - 1);
|
||||||
@ -662,17 +669,17 @@ public:
|
|||||||
|
|
||||||
const Head& pillar_head(long pillar_id) const {
|
const Head& pillar_head(long pillar_id) const {
|
||||||
assert(pillar_id >= 0 && pillar_id < m_pillars.size());
|
assert(pillar_id >= 0 && pillar_id < m_pillars.size());
|
||||||
const Pillar& p = m_pillars[pillar_id];
|
const Pillar& p = m_pillars[size_t(pillar_id)];
|
||||||
assert(p.starts_from_head && p.start_junction_id >= 0 &&
|
assert(p.starts_from_head && p.start_junction_id >= 0 &&
|
||||||
p.start_junction_id < m_heads.size() );
|
p.start_junction_id < m_heads.size() );
|
||||||
return m_heads[p.start_junction_id];
|
return m_heads[size_t(p.start_junction_id)];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Pillar& head_pillar(long headid) const {
|
const Pillar& head_pillar(long headid) const {
|
||||||
assert(headid >= 0 && headid < m_heads.size());
|
assert(headid >= 0 && headid < m_heads.size());
|
||||||
const Head& h = m_heads[headid];
|
const Head& h = m_heads[size_t(headid)];
|
||||||
assert(h.pillar_id >= 0 && h.pillar_id < m_pillars.size());
|
assert(h.pillar_id >= 0 && h.pillar_id < m_pillars.size());
|
||||||
return m_pillars[h.pillar_id];
|
return m_pillars[size_t(h.pillar_id)];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class...Args> const Junction& add_junction(Args&&... args) {
|
template<class...Args> const Junction& add_junction(Args&&... args) {
|
||||||
@ -882,8 +889,8 @@ ClusterEl pts_convex_hull(const ClusterEl& inpts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the leftmost (bottom) point
|
// Find the leftmost (bottom) point
|
||||||
int l = 0;
|
size_t l = 0;
|
||||||
for (int i = 1; i < n; i++) {
|
for (size_t i = 1; i < n; i++) {
|
||||||
if(std::abs(points[i](X) - points[l](X)) < ERR) {
|
if(std::abs(points[i](X) - points[l](X)) < ERR) {
|
||||||
if(points[i](Y) < points[l](Y)) l = i;
|
if(points[i](Y) < points[l](Y)) l = i;
|
||||||
}
|
}
|
||||||
@ -894,7 +901,6 @@ ClusterEl pts_convex_hull(const ClusterEl& inpts,
|
|||||||
// fill the output with the spatially ordered set of points.
|
// fill the output with the spatially ordered set of points.
|
||||||
|
|
||||||
// find the direction
|
// find the direction
|
||||||
Vec2d dir = (points[l] - points[(l+1)%n]).normalized();
|
|
||||||
hull = inpts;
|
hull = inpts;
|
||||||
auto& lp = points[l];
|
auto& lp = points[l];
|
||||||
std::sort(hull.begin(), hull.end(),
|
std::sort(hull.begin(), hull.end(),
|
||||||
@ -912,7 +918,7 @@ ClusterEl pts_convex_hull(const ClusterEl& inpts,
|
|||||||
// Start from leftmost point, keep moving counterclockwise
|
// Start from leftmost point, keep moving counterclockwise
|
||||||
// until reach the start point again. This loop runs O(h)
|
// until reach the start point again. This loop runs O(h)
|
||||||
// times where h is number of points in result or output.
|
// times where h is number of points in result or output.
|
||||||
int p = l;
|
size_t p = l;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Add current point to result
|
// Add current point to result
|
||||||
@ -923,8 +929,8 @@ ClusterEl pts_convex_hull(const ClusterEl& inpts,
|
|||||||
// is to keep track of last visited most counterclock-
|
// is to keep track of last visited most counterclock-
|
||||||
// wise point in q. If any point 'i' is more counterclock-
|
// wise point in q. If any point 'i' is more counterclock-
|
||||||
// wise than q, then update q.
|
// wise than q, then update q.
|
||||||
int q = (p+1)%n;
|
size_t q = (p + 1) % n;
|
||||||
for (int i = 0; i < n; i++)
|
for (size_t i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
// If i is more counterclockwise than current q, then
|
// If i is more counterclockwise than current q, then
|
||||||
// update q
|
// update q
|
||||||
@ -1006,7 +1012,10 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
// std::cout << "p " << pn << " " << points.row(pn) << std::endl;
|
// std::cout << "p " << pn << " " << points.row(pn) << std::endl;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
auto filterfn = [] (
|
|
||||||
|
auto& tifcl = ctl.cancelfn;
|
||||||
|
|
||||||
|
auto filterfn = [tifcl] (
|
||||||
const SupportConfig& cfg,
|
const SupportConfig& cfg,
|
||||||
const PointSet& points,
|
const PointSet& points,
|
||||||
const EigenMesh3D& mesh,
|
const EigenMesh3D& mesh,
|
||||||
@ -1016,26 +1025,29 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
PointSet& headless_pos,
|
PointSet& headless_pos,
|
||||||
PointSet& headless_norm)
|
PointSet& headless_norm)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* ******************************************************** */
|
/* ******************************************************** */
|
||||||
/* Filtering step */
|
/* Filtering step */
|
||||||
/* ******************************************************** */
|
/* ******************************************************** */
|
||||||
|
|
||||||
// Get the points that are too close to each other and keep only the
|
// Get the points that are too close to each other and keep only the
|
||||||
// first one
|
// first one
|
||||||
auto aliases = cluster(points,
|
auto aliases =
|
||||||
[cfg](const SpatElement& p,
|
cluster(points,
|
||||||
const SpatElement& se){
|
[tifcl](const SpatElement& p, const SpatElement& se)
|
||||||
|
{
|
||||||
|
tifcl();
|
||||||
return distance(p.first, se.first) < D_SP;
|
return distance(p.first, se.first) < D_SP;
|
||||||
}, 2);
|
}, 2);
|
||||||
|
|
||||||
filt_pts.resize(aliases.size(), 3);
|
filt_pts.resize(Eigen::Index(aliases.size()), 3);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(auto& a : aliases) {
|
for(auto& a : aliases) {
|
||||||
// Here we keep only the front point of the cluster. TODO: centroid
|
// Here we keep only the front point of the cluster.
|
||||||
filt_pts.row(count++) = points.row(a.front());
|
filt_pts.row(count++) = points.row(a.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tifcl();
|
||||||
|
|
||||||
// calculate the normals to the triangles belonging to filtered points
|
// calculate the normals to the triangles belonging to filtered points
|
||||||
auto nmls = sla::normals(filt_pts, mesh);
|
auto nmls = sla::normals(filt_pts, mesh);
|
||||||
|
|
||||||
@ -1051,6 +1063,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
|
|
||||||
int pcount = 0, hlcount = 0;
|
int pcount = 0, hlcount = 0;
|
||||||
for(int i = 0; i < count; i++) {
|
for(int i = 0; i < count; i++) {
|
||||||
|
tifcl();
|
||||||
auto n = nmls.row(i);
|
auto n = nmls.row(i);
|
||||||
|
|
||||||
// for all normals we generate the spherical coordinates and
|
// for all normals we generate the spherical coordinates and
|
||||||
@ -1110,7 +1123,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Function to write the pinheads into the result
|
// Function to write the pinheads into the result
|
||||||
auto pinheadfn = [] (
|
auto pinheadfn = [tifcl] (
|
||||||
const SupportConfig& cfg,
|
const SupportConfig& cfg,
|
||||||
PointSet& head_pos,
|
PointSet& head_pos,
|
||||||
PointSet& nmls,
|
PointSet& nmls,
|
||||||
@ -1123,6 +1136,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
/* ******************************************************** */
|
/* ******************************************************** */
|
||||||
|
|
||||||
for (int i = 0; i < head_pos.rows(); ++i) {
|
for (int i = 0; i < head_pos.rows(); ++i) {
|
||||||
|
tifcl();
|
||||||
result.add_head(
|
result.add_head(
|
||||||
cfg.head_back_radius_mm,
|
cfg.head_back_radius_mm,
|
||||||
cfg.head_front_radius_mm,
|
cfg.head_front_radius_mm,
|
||||||
@ -1136,7 +1150,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
|
|
||||||
// &filtered_points, &head_positions, &result, &mesh,
|
// &filtered_points, &head_positions, &result, &mesh,
|
||||||
// &gndidx, &gndheight, &nogndidx, cfg
|
// &gndidx, &gndheight, &nogndidx, cfg
|
||||||
auto classifyfn = [] (
|
auto classifyfn = [tifcl] (
|
||||||
const SupportConfig& cfg,
|
const SupportConfig& cfg,
|
||||||
const EigenMesh3D& mesh,
|
const EigenMesh3D& mesh,
|
||||||
PointSet& head_pos,
|
PointSet& head_pos,
|
||||||
@ -1152,11 +1166,12 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
/* ******************************************************** */
|
/* ******************************************************** */
|
||||||
|
|
||||||
// We should first get the heads that reach the ground directly
|
// We should first get the heads that reach the ground directly
|
||||||
gndheight.reserve(head_pos.rows());
|
gndheight.reserve(size_t(head_pos.rows()));
|
||||||
gndidx.reserve(head_pos.rows());
|
gndidx.reserve(size_t(head_pos.rows()));
|
||||||
nogndidx.reserve(head_pos.rows());
|
nogndidx.reserve(size_t(head_pos.rows()));
|
||||||
|
|
||||||
for(unsigned i = 0; i < head_pos.rows(); i++) {
|
for(unsigned i = 0; i < head_pos.rows(); i++) {
|
||||||
|
tifcl();
|
||||||
auto& head = result.heads()[i];
|
auto& head = result.heads()[i];
|
||||||
|
|
||||||
Vec3d dir(0, 0, -1);
|
Vec3d dir(0, 0, -1);
|
||||||
@ -1173,18 +1188,22 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
PointSet gnd(gndidx.size(), 3);
|
PointSet gnd(gndidx.size(), 3);
|
||||||
|
|
||||||
for(size_t i = 0; i < gndidx.size(); i++)
|
for(size_t i = 0; i < gndidx.size(); i++)
|
||||||
gnd.row(i) = head_pos.row(gndidx[i]);
|
gnd.row(long(i)) = head_pos.row(gndidx[i]);
|
||||||
|
|
||||||
// We want to search for clusters of points that are far enough from
|
// We want to search for clusters of points that are far enough from
|
||||||
// each other in the XY plane to not cross their pillar bases
|
// each other in the XY plane to not cross their pillar bases
|
||||||
// These clusters of support points will join in one pillar, possibly in
|
// These clusters of support points will join in one pillar, possibly in
|
||||||
// their centroid support point.
|
// their centroid support point.
|
||||||
auto d_base = 2*cfg.base_radius_mm;
|
auto d_base = 2*cfg.base_radius_mm;
|
||||||
ground_clusters = cluster(gnd,
|
ground_clusters =
|
||||||
[d_base, &cfg](const SpatElement& p, const SpatElement& s){
|
cluster(
|
||||||
return distance(Vec2d(p.first(X), p.first(Y)),
|
gnd,
|
||||||
Vec2d(s.first(X), s.first(Y))) < d_base;
|
[d_base, tifcl](const SpatElement& p, const SpatElement& s)
|
||||||
}, 3); // max 3 heads to connect to one centroid
|
{
|
||||||
|
tifcl();
|
||||||
|
return distance(Vec2d(p.first(X), p.first(Y)),
|
||||||
|
Vec2d(s.first(X), s.first(Y))) < d_base;
|
||||||
|
}, 3); // max 3 heads to connect to one centroid
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function for interconnecting two pillars with zig-zag bridges
|
// Helper function for interconnecting two pillars with zig-zag bridges
|
||||||
@ -1197,9 +1216,6 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
const Head& phead = result.pillar_head(pillar.id);
|
const Head& phead = result.pillar_head(pillar.id);
|
||||||
const Head& nextphead = result.pillar_head(nextpillar.id);
|
const Head& nextphead = result.pillar_head(nextpillar.id);
|
||||||
|
|
||||||
// double d = 2*pillar.r;
|
|
||||||
// const Vec3d& pp = pillar.endpoint.cwiseProduct(Vec3d{1, 1, 0});
|
|
||||||
|
|
||||||
Vec3d sj = phead.junction_point();
|
Vec3d sj = phead.junction_point();
|
||||||
sj(Z) = std::min(sj(Z), nextphead.junction_point()(Z));
|
sj(Z) = std::min(sj(Z), nextphead.junction_point()(Z));
|
||||||
Vec3d ej = nextpillar.endpoint;
|
Vec3d ej = nextpillar.endpoint;
|
||||||
@ -1244,7 +1260,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto routing_ground_fn = [gnd_head_pt, interconnect](
|
auto routing_ground_fn = [gnd_head_pt, interconnect, tifcl](
|
||||||
const SupportConfig& cfg,
|
const SupportConfig& cfg,
|
||||||
const ClusteredPoints& gnd_clusters,
|
const ClusteredPoints& gnd_clusters,
|
||||||
const IndexSet& gndidx,
|
const IndexSet& gndidx,
|
||||||
@ -1260,22 +1276,27 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
cl_centroids.reserve(gnd_clusters.size());
|
cl_centroids.reserve(gnd_clusters.size());
|
||||||
|
|
||||||
SpatIndex pheadindex; // spatial index for the junctions
|
SpatIndex pheadindex; // spatial index for the junctions
|
||||||
for(auto cl : gnd_clusters) {
|
for(auto& cl : gnd_clusters) { tifcl();
|
||||||
// place all the centroid head positions into the index. We will
|
// place all the centroid head positions into the index. We will
|
||||||
// query for alternative pillar positions. If a sidehead cannot
|
// query for alternative pillar positions. If a sidehead cannot
|
||||||
// connect to the cluster centroid, we have to search for another
|
// connect to the cluster centroid, we have to search for another
|
||||||
// head with a full pillar. Also when there are two elements in the
|
// head with a full pillar. Also when there are two elements in the
|
||||||
// cluster, the centroid is arbitrary and the sidehead is allowed to
|
// cluster, the centroid is arbitrary and the sidehead is allowed to
|
||||||
// connect to a nearby pillar to increase structural stability.
|
// connect to a nearby pillar to increase structural stability.
|
||||||
|
if(cl.empty()) continue;
|
||||||
|
|
||||||
// get the current cluster centroid
|
// get the current cluster centroid
|
||||||
unsigned cid = cluster_centroid(cl, gnd_head_pt,
|
long lcid = cluster_centroid(cl, gnd_head_pt,
|
||||||
[](const Vec3d& p1, const Vec3d& p2)
|
[tifcl](const Vec3d& p1, const Vec3d& p2)
|
||||||
{
|
{
|
||||||
|
tifcl();
|
||||||
return distance(Vec2d(p1(X), p1(Y)), Vec2d(p2(X), p2(Y)));
|
return distance(Vec2d(p1(X), p1(Y)), Vec2d(p2(X), p2(Y)));
|
||||||
});
|
});
|
||||||
|
|
||||||
cl_centroids.push_back(cid);
|
assert(lcid > 0);
|
||||||
|
auto cid = unsigned(lcid);
|
||||||
|
|
||||||
|
cl_centroids.push_back(unsigned(cid));
|
||||||
|
|
||||||
unsigned hid = gndidx[cl[cid]]; // Head index
|
unsigned hid = gndidx[cl[cid]]; // Head index
|
||||||
Head& h = result.head(hid);
|
Head& h = result.head(hid);
|
||||||
@ -1288,12 +1309,13 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
// now we will go through the clusters ones again and connect the
|
// now we will go through the clusters ones again and connect the
|
||||||
// sidepoints with the cluster centroid (which is a ground pillar)
|
// sidepoints with the cluster centroid (which is a ground pillar)
|
||||||
// or a nearby pillar if the centroid is unreachable.
|
// or a nearby pillar if the centroid is unreachable.
|
||||||
long ci = 0;
|
size_t ci = 0;
|
||||||
for(auto cl : gnd_clusters) {
|
for(auto cl : gnd_clusters) { tifcl();
|
||||||
|
|
||||||
auto cidx = cl_centroids[ci];
|
auto cidx = cl_centroids[ci];
|
||||||
cl_centroids[ci++] = cl[cidx];
|
cl_centroids[ci++] = cl[cidx];
|
||||||
|
|
||||||
long index_to_heads = gndidx[cl[cidx]];
|
size_t index_to_heads = gndidx[cl[cidx]];
|
||||||
auto& head = result.head(index_to_heads);
|
auto& head = result.head(index_to_heads);
|
||||||
|
|
||||||
Vec3d startpoint = head.junction_point();
|
Vec3d startpoint = head.junction_point();
|
||||||
@ -1301,7 +1323,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
|
|
||||||
// Create the central pillar of the cluster with its base on the
|
// Create the central pillar of the cluster with its base on the
|
||||||
// ground
|
// ground
|
||||||
result.add_pillar(index_to_heads, endpoint, pradius)
|
result.add_pillar(long(index_to_heads), endpoint, pradius)
|
||||||
.add_base(cfg.base_height_mm, cfg.base_radius_mm);
|
.add_base(cfg.base_height_mm, cfg.base_radius_mm);
|
||||||
|
|
||||||
// Process side point in current cluster
|
// Process side point in current cluster
|
||||||
@ -1352,12 +1374,11 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
return nearest_id;
|
return nearest_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
for(auto c : cl) {
|
for(auto c : cl) { tifcl();
|
||||||
auto& sidehead = result.head(gndidx[c]);
|
auto& sidehead = result.head(gndidx[c]);
|
||||||
sidehead.transform();
|
sidehead.transform();
|
||||||
|
|
||||||
Vec3d jsh = sidehead.junction_point();
|
Vec3d jsh = sidehead.junction_point();
|
||||||
// Vec3d jp2d = {jsh(X), jsh(Y), gndlvl};
|
|
||||||
SpatIndex spindex = pheadindex;
|
SpatIndex spindex = pheadindex;
|
||||||
long nearest_id = search_nearest(spindex, jsh);
|
long nearest_id = search_nearest(spindex, jsh);
|
||||||
|
|
||||||
@ -1374,7 +1395,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
} else {
|
} else {
|
||||||
// Creating the bridge to the nearest pillar
|
// Creating the bridge to the nearest pillar
|
||||||
|
|
||||||
const Head& nearhead = result.heads()[nearest_id];
|
const Head& nearhead = result.heads()[size_t(nearest_id)];
|
||||||
Vec3d jp = jsh;
|
Vec3d jp = jsh;
|
||||||
Vec3d jh = nearhead.junction_point();
|
Vec3d jh = nearhead.junction_point();
|
||||||
|
|
||||||
@ -1419,6 +1440,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
ClusterEl ring;
|
ClusterEl ring;
|
||||||
|
|
||||||
while(!rem.empty()) { // loop until all the points belong to some ring
|
while(!rem.empty()) { // loop until all the points belong to some ring
|
||||||
|
tifcl();
|
||||||
std::sort(rem.begin(), rem.end());
|
std::sort(rem.begin(), rem.end());
|
||||||
|
|
||||||
auto newring = pts_convex_hull(rem,
|
auto newring = pts_convex_hull(rem,
|
||||||
@ -1432,7 +1454,8 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
SpatIndex innerring;
|
SpatIndex innerring;
|
||||||
for(unsigned i : newring) {
|
for(unsigned i : newring) {
|
||||||
const Pillar& pill = result.head_pillar(gndidx[i]);
|
const Pillar& pill = result.head_pillar(gndidx[i]);
|
||||||
innerring.insert(pill.endpoint, pill.id);
|
assert(pill.id > 0);
|
||||||
|
innerring.insert(pill.endpoint, unsigned(pill.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// For all pillars in the outer ring find the closest in the
|
// For all pillars in the outer ring find the closest in the
|
||||||
@ -1478,14 +1501,14 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto routing_nongnd_fn = [](
|
auto routing_nongnd_fn = [tifcl](
|
||||||
const SupportConfig& cfg,
|
const SupportConfig& cfg,
|
||||||
const std::vector<double>& gndheight,
|
const std::vector<double>& gndheight,
|
||||||
const IndexSet& nogndidx,
|
const IndexSet& nogndidx,
|
||||||
Result& result)
|
Result& result)
|
||||||
{
|
{
|
||||||
// TODO: connect these to the ground pillars if possible
|
// TODO: connect these to the ground pillars if possible
|
||||||
for(auto idx : nogndidx) {
|
for(auto idx : nogndidx) { tifcl();
|
||||||
auto& head = result.head(idx);
|
auto& head = result.head(idx);
|
||||||
head.transform();
|
head.transform();
|
||||||
|
|
||||||
@ -1510,7 +1533,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto process_headless = [](
|
auto process_headless = [tifcl](
|
||||||
const SupportConfig& cfg,
|
const SupportConfig& cfg,
|
||||||
const PointSet& headless_pts,
|
const PointSet& headless_pts,
|
||||||
const PointSet& headless_norm,
|
const PointSet& headless_norm,
|
||||||
@ -1525,7 +1548,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
|
|
||||||
// We will sink the pins into the model surface for a distance of 1/3 of
|
// We will sink the pins into the model surface for a distance of 1/3 of
|
||||||
// HWIDTH_MM
|
// HWIDTH_MM
|
||||||
for(int i = 0; i < headless_pts.rows(); i++) {
|
for(int i = 0; i < headless_pts.rows(); i++) { tifcl();
|
||||||
Vec3d sp = headless_pts.row(i);
|
Vec3d sp = headless_pts.row(i);
|
||||||
|
|
||||||
Vec3d n = headless_norm.row(i);
|
Vec3d n = headless_norm.row(i);
|
||||||
@ -1634,6 +1657,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
case HALT: pc = pc_prev; break;
|
case HALT: pc = pc_prev; break;
|
||||||
case DONE:
|
case DONE:
|
||||||
case ABORT: break;
|
case ABORT: break;
|
||||||
|
default: ;
|
||||||
}
|
}
|
||||||
ctl.statuscb(stepstate[pc], stepstr[pc]);
|
ctl.statuscb(stepstate[pc], stepstr[pc]);
|
||||||
};
|
};
|
||||||
@ -1724,5 +1748,8 @@ SLASupportTree &SLASupportTree::operator=(const SLASupportTree &c)
|
|||||||
|
|
||||||
SLASupportTree::~SLASupportTree() {}
|
SLASupportTree::~SLASupportTree() {}
|
||||||
|
|
||||||
|
SLASupportsStoppedException::SLASupportsStoppedException():
|
||||||
|
std::runtime_error("") {}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ PointSet to_point_set(const std::vector<Vec3d>&);
|
|||||||
class SLASupportsStoppedException: public std::runtime_error {
|
class SLASupportsStoppedException: public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
using std::runtime_error::runtime_error;
|
using std::runtime_error::runtime_error;
|
||||||
SLASupportsStoppedException(): std::runtime_error("") {}
|
SLASupportsStoppedException();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The class containing mesh data for the generated supports.
|
/// The class containing mesh data for the generated supports.
|
||||||
|
@ -89,8 +89,6 @@ PointSet normals(const PointSet& points, const EigenMesh3D& mesh) {
|
|||||||
#ifdef IGL_COMPATIBLE
|
#ifdef IGL_COMPATIBLE
|
||||||
Eigen::VectorXd dists;
|
Eigen::VectorXd dists;
|
||||||
Eigen::VectorXi I;
|
Eigen::VectorXi I;
|
||||||
// Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::DontAlign> dists;
|
|
||||||
// Eigen::Matrix<int, Eigen::Dynamic, 1, Eigen::DontAlign> I;
|
|
||||||
PointSet C;
|
PointSet C;
|
||||||
|
|
||||||
igl::point_mesh_squared_distance( points, mesh.V, mesh.F, dists, I, C);
|
igl::point_mesh_squared_distance( points, mesh.V, mesh.F, dists, I, C);
|
||||||
@ -122,7 +120,7 @@ double ray_mesh_intersect(const Vec3d& s,
|
|||||||
igl::Hit hit;
|
igl::Hit hit;
|
||||||
hit.t = std::numeric_limits<float>::infinity();
|
hit.t = std::numeric_limits<float>::infinity();
|
||||||
igl::ray_mesh_intersect(s, dir, m.V, m.F, hit);
|
igl::ray_mesh_intersect(s, dir, m.V, m.F, hit);
|
||||||
return hit.t;
|
return double(hit.t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clustering a set of points by the given criteria
|
// Clustering a set of points by the given criteria
|
||||||
@ -208,7 +206,7 @@ Segments model_boundary(const EigenMesh3D& emesh, double offs)
|
|||||||
{
|
{
|
||||||
Segments ret;
|
Segments ret;
|
||||||
Polygons pp;
|
Polygons pp;
|
||||||
pp.reserve(emesh.F.rows());
|
pp.reserve(size_t(emesh.F.rows()));
|
||||||
|
|
||||||
for (int i = 0; i < emesh.F.rows(); i++) {
|
for (int i = 0; i < emesh.F.rows(); i++) {
|
||||||
auto trindex = emesh.F.row(i);
|
auto trindex = emesh.F.row(i);
|
||||||
|
@ -469,7 +469,7 @@ void SLAPrint::process()
|
|||||||
for(float h = minZ + ilh; h < maxZ; h += flh)
|
for(float h = minZ + ilh; h < maxZ; h += flh)
|
||||||
if(h >= gnd) heights.emplace_back(h);
|
if(h >= gnd) heights.emplace_back(h);
|
||||||
|
|
||||||
auto& layers = po.m_model_slices;
|
auto& layers = po.m_model_slices; layers.clear();
|
||||||
slicer.slice(heights, &layers, [this](){ throw_if_canceled(); });
|
slicer.slice(heights, &layers, [this](){ throw_if_canceled(); });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -446,6 +446,7 @@ const std::vector<std::string>& Preset::sla_printer_options()
|
|||||||
"printer_technology",
|
"printer_technology",
|
||||||
"bed_shape", "max_print_height",
|
"bed_shape", "max_print_height",
|
||||||
"display_width", "display_height", "display_pixels_x", "display_pixels_y",
|
"display_width", "display_height", "display_pixels_x", "display_pixels_y",
|
||||||
|
"display_flip_xy",
|
||||||
"printer_correction",
|
"printer_correction",
|
||||||
"printer_notes",
|
"printer_notes",
|
||||||
"inherits"
|
"inherits"
|
||||||
|
@ -1883,6 +1883,7 @@ void TabPrinter::build_sla()
|
|||||||
line.append_option(option);
|
line.append_option(option);
|
||||||
line.append_option(optgroup->get_option("display_pixels_y"));
|
line.append_option(optgroup->get_option("display_pixels_y"));
|
||||||
optgroup->append_line(line);
|
optgroup->append_line(line);
|
||||||
|
optgroup->append_single_option_line("display_flip_xy");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(_(L("Corrections")));
|
optgroup = page->new_optgroup(_(L("Corrections")));
|
||||||
line = Line{ m_config->def()->get("printer_correction")->full_label, "" };
|
line = Line{ m_config->def()->get("printer_correction")->full_label, "" };
|
||||||
|
Loading…
Reference in New Issue
Block a user