mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-02 22:00:40 +08:00

Completely remove the concept of CompactBridge. Replace it with Heads having the same back radius as front radius. Try to apply the same rules for mini supports as in the route_to_model step. Increased accuracy of bridge_mesh_intersect shot from support points Refining mini support integration
119 lines
3.8 KiB
C++
119 lines
3.8 KiB
C++
/**
|
|
* In this file we will implement the automatic SLA support tree generation.
|
|
*
|
|
*/
|
|
|
|
#include <numeric>
|
|
#include <libslic3r/SLA/SupportTree.hpp>
|
|
#include <libslic3r/SLA/Common.hpp>
|
|
#include <libslic3r/SLA/SpatIndex.hpp>
|
|
#include <libslic3r/SLA/SupportTreeBuilder.hpp>
|
|
#include <libslic3r/SLA/SupportTreeBuildsteps.hpp>
|
|
|
|
#include <libslic3r/MTUtils.hpp>
|
|
#include <libslic3r/ClipperUtils.hpp>
|
|
#include <libslic3r/Model.hpp>
|
|
|
|
#include <libnest2d/optimizers/nlopt/genetic.hpp>
|
|
#include <libnest2d/optimizers/nlopt/subplex.hpp>
|
|
#include <boost/log/trivial.hpp>
|
|
#include <tbb/parallel_for.h>
|
|
#include <tbb/mutex.h>
|
|
#include <tbb/spin_mutex.h>
|
|
#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 {
|
|
|
|
// Compile time configuration value definitions:
|
|
|
|
// The max Z angle for a normal at which it will get completely ignored.
|
|
const double SupportConfig::normal_cutoff_angle = 150.0 * M_PI / 180.0;
|
|
|
|
// The shortest distance of any support structure from the model surface
|
|
const double SupportConfig::safety_distance_mm = 0.5;
|
|
|
|
const double SupportConfig::max_solo_pillar_height_mm = 15.0;
|
|
const double SupportConfig::max_dual_pillar_height_mm = 35.0;
|
|
const double SupportConfig::optimizer_rel_score_diff = 1e-6;
|
|
const unsigned SupportConfig::optimizer_max_iterations = 1000;
|
|
const unsigned SupportConfig::pillar_cascade_neighbors = 3;
|
|
|
|
void SupportTree::retrieve_full_mesh(TriangleMesh &outmesh) const {
|
|
outmesh.merge(retrieve_mesh(MeshType::Support));
|
|
outmesh.merge(retrieve_mesh(MeshType::Pad));
|
|
}
|
|
|
|
std::vector<ExPolygons> SupportTree::slice(
|
|
const std::vector<float> &grid, float cr) const
|
|
{
|
|
const TriangleMesh &sup_mesh = retrieve_mesh(MeshType::Support);
|
|
const TriangleMesh &pad_mesh = retrieve_mesh(MeshType::Pad);
|
|
|
|
using Slices = std::vector<ExPolygons>;
|
|
auto slices = reserve_vector<Slices>(2);
|
|
|
|
if (!sup_mesh.empty()) {
|
|
slices.emplace_back();
|
|
|
|
TriangleMeshSlicer sup_slicer(&sup_mesh);
|
|
sup_slicer.slice(grid, SlicingMode::Regular, cr, &slices.back(), ctl().cancelfn);
|
|
}
|
|
|
|
if (!pad_mesh.empty()) {
|
|
slices.emplace_back();
|
|
|
|
auto bb = pad_mesh.bounding_box();
|
|
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));
|
|
|
|
TriangleMeshSlicer pad_slicer(&pad_mesh);
|
|
pad_slicer.slice(padgrid, SlicingMode::Regular, cr, &slices.back(), 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;
|
|
}
|
|
|
|
SupportTree::UPtr SupportTree::create(const SupportableMesh &sm,
|
|
const JobController & ctl)
|
|
{
|
|
auto builder = make_unique<SupportTreeBuilder>();
|
|
builder->m_ctl = ctl;
|
|
|
|
if (sm.cfg.enabled) {
|
|
// Execute takes care about the ground_level
|
|
SupportTreeBuildsteps::execute(*builder, sm);
|
|
builder->merge_and_cleanup(); // clean metadata, leave only the meshes.
|
|
} else {
|
|
// If a pad gets added later, it will be in the right Z level
|
|
builder->ground_level = sm.emesh.ground_level();
|
|
}
|
|
|
|
return std::move(builder);
|
|
}
|
|
|
|
}} // namespace Slic3r::sla
|