PrusaSlicer-NonPlainar/src/libslic3r/SLA/SupportTree.cpp
2022-07-29 13:05:39 +02:00

137 lines
4.1 KiB
C++

/**
* In this file we will implement the automatic SLA support tree generation.
*
*/
#include <numeric>
#include <libslic3r/SLA/SupportTree.hpp>
#include <libslic3r/SLA/SpatIndex.hpp>
#include <libslic3r/SLA/SupportTreeBuilder.hpp>
#include <libslic3r/SLA/DefaultSupportTree.hpp>
#include <libslic3r/SLA/BranchingTreeSLA.hpp>
#include <libslic3r/MTUtils.hpp>
#include <libslic3r/ClipperUtils.hpp>
#include <libslic3r/Model.hpp>
#include <libslic3r/TriangleMeshSlicer.hpp>
#include <boost/log/trivial.hpp>
#include <libslic3r/I18N.hpp>
//! macro used to mark string used at localization,
//! return same string
#define L(s) Slic3r::I18N::translate(s)
namespace Slic3r { namespace sla {
indexed_triangle_set create_support_tree(const SupportableMesh &sm,
const JobController &ctl)
{
auto builder = make_unique<SupportTreeBuilder>(ctl);
if (sm.cfg.enabled) {
switch (sm.cfg.tree_type) {
case SupportTreeType::Default: {
create_default_tree(*builder, sm);
break;
}
case SupportTreeType::Branching: {
create_branching_tree(*builder, sm);
break;
}
default:;
}
builder->merge_and_cleanup(); // clean metadata, leave only the meshes.
}
indexed_triangle_set out = builder->retrieve_mesh(MeshType::Support);
return out;
}
indexed_triangle_set create_pad(const SupportableMesh &sm,
const indexed_triangle_set &support_mesh,
const JobController &ctl)
{
ExPolygons model_contours; // This will store the base plate of the pad.
double pad_h = sm.pad_cfg.full_height();
float zstart = ground_level(sm);
float zend = zstart + float(pad_h + EPSILON);
auto heights = grid(zstart, zend, 0.1f);
if (!sm.cfg.enabled || sm.pad_cfg.embed_object) {
// No support (thus no elevation) or zero elevation mode
// we sometimes call it "builtin pad" is enabled so we will
// get a sample from the bottom of the mesh and use it for pad
// creation.
sla::pad_blueprint(*sm.emesh.get_triangle_mesh(), model_contours,
heights, ctl.cancelfn);
}
ExPolygons sup_contours;
pad_blueprint(support_mesh, sup_contours, heights, ctl.cancelfn);
indexed_triangle_set out;
create_pad(sup_contours, model_contours, out, sm.pad_cfg);
Vec3f offs{.0f, .0f, zstart};
for (auto &p : out.vertices) p += offs;
its_merge_vertices(out);
return out;
}
std::vector<ExPolygons> slice(const indexed_triangle_set &sup_mesh,
const indexed_triangle_set &pad_mesh,
const std::vector<float> &grid,
float cr,
const JobController &ctl)
{
using Slices = std::vector<ExPolygons>;
auto slices = reserve_vector<Slices>(2);
if (!sup_mesh.empty()) {
slices.emplace_back();
slices.back() = slice_mesh_ex(sup_mesh, grid, cr, ctl.cancelfn);
}
if (!pad_mesh.empty()) {
slices.emplace_back();
auto bb = bounding_box(pad_mesh);
auto maxzit = std::upper_bound(grid.begin(), grid.end(), bb.max.z());
auto cap = grid.end() - maxzit;
auto padgrid = reserve_vector<float>(size_t(cap > 0 ? cap : 0));
std::copy(grid.begin(), maxzit, std::back_inserter(padgrid));
slices.back() = slice_mesh_ex(pad_mesh, padgrid, cr, ctl.cancelfn);
}
size_t len = grid.size();
for (const Slices &slv : slices)
len = std::min(len, slv.size());
// Either the support or the pad or both has to be non empty
if (slices.empty()) return {};
Slices &mrg = slices.front();
for (auto it = std::next(slices.begin()); it != slices.end(); ++it) {
for (size_t i = 0; i < len; ++i) {
Slices &slv = *it;
std::copy(slv[i].begin(), slv[i].end(), std::back_inserter(mrg[i]));
slv[i] = {}; // clear and delete
}
}
return mrg;
}
}} // namespace Slic3r::sla