SLA supports - first attempt at supporting islands
This commit is contained in:
parent
6cc8ae3729
commit
27ad859d4d
6 changed files with 152 additions and 34 deletions
|
@ -3,12 +3,15 @@
|
||||||
|
|
||||||
#include "SLAAutoSupports.hpp"
|
#include "SLAAutoSupports.hpp"
|
||||||
#include "Model.hpp"
|
#include "Model.hpp"
|
||||||
|
#include "ExPolygon.hpp"
|
||||||
|
#include "SVG.hpp"
|
||||||
|
#include "Point.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
namespace SLAAutoSupports {
|
||||||
SLAAutoSupports::SLAAutoSupports(ModelObject& mo, const SLAAutoSupports::Config& c)
|
SLAAutoSupports::SLAAutoSupports(ModelObject& mo, const SLAAutoSupports::Config& c)
|
||||||
: m_model_object(mo), mesh(), m_config(c)
|
: m_model_object(mo), mesh(), m_config(c)
|
||||||
{}
|
{}
|
||||||
|
@ -152,4 +155,90 @@ float SLAAutoSupports::get_required_density(float angle) const
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void output_expolygons(const ExPolygons& expolys, std::string filename)
|
||||||
|
{
|
||||||
|
BoundingBox bb(Point(-30000000, -30000000), Point(30000000, 30000000));
|
||||||
|
Slic3r::SVG svg_cummulative(filename, bb);
|
||||||
|
for (size_t i = 0; i < expolys.size(); ++ i) {
|
||||||
|
/*Slic3r::SVG svg("single"+std::to_string(i)+".svg", bb);
|
||||||
|
svg.draw(expolys[i]);
|
||||||
|
svg.draw_outline(expolys[i].contour, "black", scale_(0.05));
|
||||||
|
svg.draw_outline(expolys[i].holes, "blue", scale_(0.05));
|
||||||
|
svg.Close();*/
|
||||||
|
|
||||||
|
svg_cummulative.draw(expolys[i]);
|
||||||
|
svg_cummulative.draw_outline(expolys[i].contour, "black", scale_(0.05));
|
||||||
|
svg_cummulative.draw_outline(expolys[i].holes, "blue", scale_(0.05));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Vec3d> find_islands(const std::vector<ExPolygons>& slices, const std::vector<float>& heights)
|
||||||
|
{
|
||||||
|
std::vector<Vec3d> support_points_out;
|
||||||
|
|
||||||
|
struct PointAccessor {
|
||||||
|
const Point* operator()(const Point &pt) const { return &pt; }
|
||||||
|
};
|
||||||
|
typedef ClosestPointInRadiusLookup<Point, PointAccessor> ClosestPointLookupType;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i<slices.size(); ++i) {
|
||||||
|
const ExPolygons& expolys_top = slices[i];
|
||||||
|
const ExPolygons& expolys_bottom = (i == 0 ? ExPolygons() : slices[i-1]);
|
||||||
|
|
||||||
|
std::string layer_num_str = std::string((i<10 ? "0" : "")) + std::string((i<100 ? "0" : "")) + std::to_string(i);
|
||||||
|
output_expolygons(expolys_top, "top" + layer_num_str + ".svg");
|
||||||
|
ExPolygons diff = diff_ex(expolys_top, expolys_bottom);
|
||||||
|
ExPolygons islands;
|
||||||
|
|
||||||
|
output_expolygons(diff, "diff" + layer_num_str + ".svg");
|
||||||
|
|
||||||
|
ClosestPointLookupType cpl(SCALED_EPSILON);
|
||||||
|
for (const ExPolygon& expol : expolys_top) {
|
||||||
|
for (const Point& p : expol.contour.points)
|
||||||
|
cpl.insert(p);
|
||||||
|
for (const Polygon& hole : expol.holes)
|
||||||
|
for (const Point& p : hole.points)
|
||||||
|
cpl.insert(p);
|
||||||
|
// the lookup structure now contains all points from the top slice
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ExPolygon& polygon : diff) {
|
||||||
|
// we want to check all boundary points of the diff polygon
|
||||||
|
bool island = true;
|
||||||
|
for (const Point& p : polygon.contour.points) {
|
||||||
|
if (cpl.find(p).second != 0) { // the point belongs to the bottom slice - this cannot be an island
|
||||||
|
island = false;
|
||||||
|
goto NO_ISLAND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const Polygon& hole : polygon.holes)
|
||||||
|
for (const Point& p : hole.points)
|
||||||
|
if (cpl.find(p).second != 0) {
|
||||||
|
island = false;
|
||||||
|
goto NO_ISLAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (island) { // all points of the diff polygon are from the top slice
|
||||||
|
islands.push_back(polygon);
|
||||||
|
}
|
||||||
|
NO_ISLAND: ;// continue with next ExPolygon
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!islands.empty())
|
||||||
|
output_expolygons(islands, "islands" + layer_num_str + ".svg");
|
||||||
|
for (const ExPolygon& island : islands) {
|
||||||
|
Point centroid = island.contour.centroid();
|
||||||
|
Vec3d centroid_d(centroid(0), centroid(1), scale_(i!=0 ? heights[i-1] : heights[0]-(heights[1]-heights[0]))) ;
|
||||||
|
support_points_out.push_back(unscale(centroid_d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return support_points_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SLAAutoSupports
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
|
@ -10,7 +10,7 @@ namespace Slic3r {
|
||||||
|
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
|
|
||||||
|
namespace SLAAutoSupports {
|
||||||
|
|
||||||
|
|
||||||
class SLAAutoSupports {
|
class SLAAutoSupports {
|
||||||
|
@ -35,7 +35,9 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Vec3d> find_islands(const std::vector<ExPolygons>& slices, const std::vector<float>& heights);
|
||||||
|
|
||||||
|
} // namespace SLAAutoSupports
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "SLAPrint.hpp"
|
#include "SLAPrint.hpp"
|
||||||
#include "SLA/SLASupportTree.hpp"
|
#include "SLA/SLASupportTree.hpp"
|
||||||
#include "SLA/SLABasePool.hpp"
|
#include "SLA/SLABasePool.hpp"
|
||||||
|
#include "SLA/SLAAutoSupports.hpp"
|
||||||
#include "MTUtils.hpp"
|
#include "MTUtils.hpp"
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
@ -36,8 +37,7 @@ namespace {
|
||||||
const std::array<unsigned, slaposCount> OBJ_STEP_LEVELS =
|
const std::array<unsigned, slaposCount> OBJ_STEP_LEVELS =
|
||||||
{
|
{
|
||||||
10, // slaposObjectSlice,
|
10, // slaposObjectSlice,
|
||||||
10, // slaposSupportIslands,
|
30, // slaposSupportPoints,
|
||||||
20, // slaposSupportPoints,
|
|
||||||
25, // slaposSupportTree,
|
25, // slaposSupportTree,
|
||||||
25, // slaposBasePool,
|
25, // slaposBasePool,
|
||||||
5, // slaposSliceSupports,
|
5, // slaposSliceSupports,
|
||||||
|
@ -47,8 +47,7 @@ const std::array<unsigned, slaposCount> OBJ_STEP_LEVELS =
|
||||||
const std::array<std::string, slaposCount> OBJ_STEP_LABELS =
|
const std::array<std::string, slaposCount> OBJ_STEP_LABELS =
|
||||||
{
|
{
|
||||||
L("Slicing model"), // slaposObjectSlice,
|
L("Slicing model"), // slaposObjectSlice,
|
||||||
L("Generating islands"), // slaposSupportIslands,
|
L("Generating support points"), // slaposSupportPoints,
|
||||||
L("Scanning model structure"), // slaposSupportPoints,
|
|
||||||
L("Generating support tree"), // slaposSupportTree,
|
L("Generating support tree"), // slaposSupportTree,
|
||||||
L("Generating base pool"), // slaposBasePool,
|
L("Generating base pool"), // slaposBasePool,
|
||||||
L("Slicing supports"), // slaposSliceSupports,
|
L("Slicing supports"), // slaposSliceSupports,
|
||||||
|
@ -420,6 +419,24 @@ void swapXY(ExPolygon& expoly) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<float> SLAPrint::calculate_heights(const BoundingBoxf3& bb3d, float elevation, float initial_layer_height, float layer_height) const
|
||||||
|
{
|
||||||
|
std::vector<float> heights;
|
||||||
|
float minZ = float(bb3d.min(Z)) - float(elevation);
|
||||||
|
float maxZ = float(bb3d.max(Z)) ;
|
||||||
|
auto flh = float(layer_height);
|
||||||
|
auto gnd = float(bb3d.min(Z));
|
||||||
|
|
||||||
|
// The first layer (the one before the initial height) is added only
|
||||||
|
// if there is no pad and no elevation value
|
||||||
|
if(minZ >= gnd) heights.emplace_back(minZ);
|
||||||
|
|
||||||
|
for(float h = minZ + initial_layer_height; h < maxZ; h += flh)
|
||||||
|
if(h >= gnd) heights.emplace_back(h);
|
||||||
|
return heights;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SLAPrint::process()
|
void SLAPrint::process()
|
||||||
{
|
{
|
||||||
using namespace sla;
|
using namespace sla;
|
||||||
|
@ -455,24 +472,9 @@ void SLAPrint::process()
|
||||||
|
|
||||||
TriangleMesh mesh = po.transformed_mesh();
|
TriangleMesh mesh = po.transformed_mesh();
|
||||||
TriangleMeshSlicer slicer(&mesh);
|
TriangleMeshSlicer slicer(&mesh);
|
||||||
auto bb3d = mesh.bounding_box();
|
|
||||||
|
|
||||||
double elevation = po.get_elevation();
|
|
||||||
|
|
||||||
float minZ = float(bb3d.min(Z)) - float(elevation);
|
|
||||||
float maxZ = float(bb3d.max(Z)) ;
|
|
||||||
auto flh = float(lh);
|
|
||||||
auto gnd = float(bb3d.min(Z));
|
|
||||||
|
|
||||||
// The 1D grid heights
|
// The 1D grid heights
|
||||||
std::vector<float> heights;
|
std::vector<float> heights = calculate_heights(mesh.bounding_box(), po.get_elevation(), ilh, lh);
|
||||||
|
|
||||||
// The first layer (the one before the initial height) is added only
|
|
||||||
// if there is no pad and no elevation value
|
|
||||||
if(minZ >= gnd) heights.emplace_back(minZ);
|
|
||||||
|
|
||||||
for(float h = minZ + ilh; h < maxZ; h += flh)
|
|
||||||
if(h >= gnd) heights.emplace_back(h);
|
|
||||||
|
|
||||||
auto& layers = po.m_model_slices; layers.clear();
|
auto& layers = po.m_model_slices; layers.clear();
|
||||||
slicer.slice(heights, &layers, [this](){ throw_if_canceled(); });
|
slicer.slice(heights, &layers, [this](){ throw_if_canceled(); });
|
||||||
|
@ -480,8 +482,8 @@ void SLAPrint::process()
|
||||||
|
|
||||||
// this procedure simply converts the points and copies them into
|
// this procedure simply converts the points and copies them into
|
||||||
// the support data cache
|
// the support data cache
|
||||||
auto support_points = [](SLAPrintObject& po) {
|
/*auto support_points = [](SLAPrintObject& po) {
|
||||||
ModelObject& mo = *po.m_model_object;
|
const ModelObject& mo = *po.m_model_object;
|
||||||
po.m_supportdata.reset(new SLAPrintObject::SupportData());
|
po.m_supportdata.reset(new SLAPrintObject::SupportData());
|
||||||
|
|
||||||
if(!mo.sla_support_points.empty()) {
|
if(!mo.sla_support_points.empty()) {
|
||||||
|
@ -497,6 +499,36 @@ void SLAPrint::process()
|
||||||
" Hint: create some support points or disable support "
|
" Hint: create some support points or disable support "
|
||||||
"creation."));
|
"creation."));
|
||||||
}
|
}
|
||||||
|
};*/
|
||||||
|
|
||||||
|
// In this step we check the slices, identify island and cover them with
|
||||||
|
// support points. Then we sprinkle the rest of the mesh.
|
||||||
|
auto support_points = [this, ilh](SLAPrintObject& po) {
|
||||||
|
// find islands to support
|
||||||
|
double lh = po.m_config.layer_height.getFloat();
|
||||||
|
std::vector<float> heights = calculate_heights(po.transformed_mesh().bounding_box(), po.get_elevation(), ilh, lh);
|
||||||
|
//SLAAutoSupports auto_supports(po.get_model_slices(), heights, *po.m_model_object);
|
||||||
|
std::vector<Vec3d> points = SLAAutoSupports::find_islands(po.get_model_slices(), heights);
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
|
||||||
|
// create mesh in igl format
|
||||||
|
|
||||||
|
// cover the islands with points, use igl to get precise z coordinate
|
||||||
|
|
||||||
|
// sprinkle the mesh with points (SLAAutoSupports::generate())
|
||||||
|
|
||||||
|
|
||||||
|
/*for (const auto& p: points)
|
||||||
|
std::cout << p(0) << " " << p(1) << " " << p(2) << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
*/
|
||||||
|
//for (auto& p: points)
|
||||||
|
// p = po.trafo().inverse() * p;
|
||||||
|
|
||||||
|
po.m_supportdata.reset(new SLAPrintObject::SupportData());
|
||||||
|
po.m_supportdata->emesh = sla::to_eigenmesh(po.transformed_mesh());
|
||||||
|
po.m_supportdata->support_points = sla::to_point_set(points);
|
||||||
};
|
};
|
||||||
|
|
||||||
// In this step we create the supports
|
// In this step we create the supports
|
||||||
|
@ -803,8 +835,7 @@ void SLAPrint::process()
|
||||||
|
|
||||||
// This is the actual order of steps done on each PrintObject
|
// This is the actual order of steps done on each PrintObject
|
||||||
std::array<SLAPrintObjectStep, slaposCount> objectsteps = {
|
std::array<SLAPrintObjectStep, slaposCount> objectsteps = {
|
||||||
slaposObjectSlice, // Support Islands will need this step
|
slaposObjectSlice, // SupportPoints will need this step
|
||||||
slaposSupportIslands,
|
|
||||||
slaposSupportPoints,
|
slaposSupportPoints,
|
||||||
slaposSupportTree,
|
slaposSupportTree,
|
||||||
slaposBasePool,
|
slaposBasePool,
|
||||||
|
@ -815,7 +846,6 @@ void SLAPrint::process()
|
||||||
std::array<slaposFn, slaposCount> pobj_program =
|
std::array<slaposFn, slaposCount> pobj_program =
|
||||||
{
|
{
|
||||||
slice_model,
|
slice_model,
|
||||||
[](SLAPrintObject&){}, // slaposSupportIslands now empty
|
|
||||||
support_points,
|
support_points,
|
||||||
support_tree,
|
support_tree,
|
||||||
base_pool,
|
base_pool,
|
||||||
|
@ -1014,9 +1044,6 @@ bool SLAPrintObject::invalidate_step(SLAPrintObjectStep step)
|
||||||
// propagate to dependent steps
|
// propagate to dependent steps
|
||||||
if (step == slaposObjectSlice) {
|
if (step == slaposObjectSlice) {
|
||||||
invalidated |= this->invalidate_all_steps();
|
invalidated |= this->invalidate_all_steps();
|
||||||
} else if (step == slaposSupportIslands) {
|
|
||||||
invalidated |= this->invalidate_steps({ slaposSupportPoints, slaposSupportTree, slaposBasePool, slaposSliceSupports, slaposIndexSlices });
|
|
||||||
invalidated |= m_print->invalidate_step(slapsRasterize);
|
|
||||||
} else if (step == slaposSupportPoints) {
|
} else if (step == slaposSupportPoints) {
|
||||||
invalidated |= this->invalidate_steps({ slaposSupportTree, slaposBasePool, slaposSliceSupports, slaposIndexSlices });
|
invalidated |= this->invalidate_steps({ slaposSupportTree, slaposBasePool, slaposSliceSupports, slaposIndexSlices });
|
||||||
invalidated |= m_print->invalidate_step(slapsRasterize);
|
invalidated |= m_print->invalidate_step(slapsRasterize);
|
||||||
|
|
|
@ -18,7 +18,6 @@ enum SLAPrintStep : unsigned int {
|
||||||
|
|
||||||
enum SLAPrintObjectStep : unsigned int {
|
enum SLAPrintObjectStep : unsigned int {
|
||||||
slaposObjectSlice,
|
slaposObjectSlice,
|
||||||
slaposSupportIslands,
|
|
||||||
slaposSupportPoints,
|
slaposSupportPoints,
|
||||||
slaposSupportTree,
|
slaposSupportTree,
|
||||||
slaposBasePool,
|
slaposBasePool,
|
||||||
|
@ -226,6 +225,8 @@ private:
|
||||||
lref(std::cref(lyr)), copies(std::cref(cp)) {}
|
lref(std::cref(lyr)), copies(std::cref(cp)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::vector<float> calculate_heights(const BoundingBoxf3& bb, float elevation, float initial_layer_height, float layer_height) const;
|
||||||
|
|
||||||
// One level may contain multiple slices from multiple objects and their
|
// One level may contain multiple slices from multiple objects and their
|
||||||
// supports
|
// supports
|
||||||
using LayerRefs = std::vector<LayerRef>;
|
using LayerRefs = std::vector<LayerRef>;
|
||||||
|
|
|
@ -2189,12 +2189,12 @@ void GLGizmoSlaSupports::on_render_input_window(float x, float y, const GLCanvas
|
||||||
|
|
||||||
if (generate) {
|
if (generate) {
|
||||||
const DynamicPrintConfig& cfg = *wxGetApp().get_tab(Preset::TYPE_SLA_PRINT)->get_config();
|
const DynamicPrintConfig& cfg = *wxGetApp().get_tab(Preset::TYPE_SLA_PRINT)->get_config();
|
||||||
SLAAutoSupports::Config config;
|
SLAAutoSupports::SLAAutoSupports::Config config;
|
||||||
config.density_at_horizontal = cfg.opt_int("support_density_at_horizontal") / 10000.f;
|
config.density_at_horizontal = cfg.opt_int("support_density_at_horizontal") / 10000.f;
|
||||||
config.density_at_45 = cfg.opt_int("support_density_at_45") / 10000.f;
|
config.density_at_45 = cfg.opt_int("support_density_at_45") / 10000.f;
|
||||||
config.minimal_z = cfg.opt_float("support_minimal_z");
|
config.minimal_z = cfg.opt_float("support_minimal_z");
|
||||||
|
|
||||||
SLAAutoSupports sas(*m_model_object, config);
|
SLAAutoSupports::SLAAutoSupports sas(*m_model_object, config);
|
||||||
sas.generate();
|
sas.generate();
|
||||||
m_grabbers.clear();
|
m_grabbers.clear();
|
||||||
for (const Vec3f& point : m_model_object->sla_support_points) {
|
for (const Vec3f& point : m_model_object->sla_support_points) {
|
||||||
|
|
|
@ -436,7 +436,6 @@ protected:
|
||||||
class GLGizmoSlaSupports : public GLGizmoBase
|
class GLGizmoSlaSupports : public GLGizmoBase
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SLAAutoSupports* m_sas = nullptr;
|
|
||||||
ModelObject* m_model_object = nullptr;
|
ModelObject* m_model_object = nullptr;
|
||||||
#if ENABLE_SLA_SUPPORT_GIZMO_MOD
|
#if ENABLE_SLA_SUPPORT_GIZMO_MOD
|
||||||
ModelObject* m_old_model_object = nullptr;
|
ModelObject* m_old_model_object = nullptr;
|
||||||
|
|
Loading…
Add table
Reference in a new issue