More SLA support points improvements

- unselected objects are hidden when SLA gizmo is active
- support volumes are hidden when editing mode is active
- 3mf support points format versioning
This commit is contained in:
Lukas Matena 2019-02-01 16:12:00 +01:00
parent 21026ec9a8
commit f568f93f08
11 changed files with 248 additions and 97 deletions

View file

@ -776,10 +776,19 @@ namespace Slic3r {
std::vector<std::string> objects;
boost::split(objects, buffer, boost::is_any_of("\n"), boost::token_compress_off);
// Info on format versioning - see 3mf.hpp
int version = 0;
if (!objects.empty() && objects[0].find("support_points_format_version=") != std::string::npos) {
objects[0].erase(objects[0].begin(), objects[0].begin() + 30); // removes the string
version = std::stoi(objects[0]);
objects.erase(objects.begin()); // pop the header
}
for (const std::string& object : objects)
{
std::vector<std::string> object_data;
boost::split(object_data, object, boost::is_any_of("|"), boost::token_compress_off);
if (object_data.size() != 2)
{
add_error("Error while reading object data");
@ -813,12 +822,22 @@ namespace Slic3r {
std::vector<sla::SupportPoint> sla_support_points;
for (unsigned int i=0; i<object_data_points.size(); i+=5)
if (version == 0) {
for (unsigned int i=0; i<object_data_points.size(); i+=3)
sla_support_points.emplace_back(std::atof(object_data_points[i+0].c_str()),
std::atof(object_data_points[i+1].c_str()),
std::atof(object_data_points[i+2].c_str()),
0.4f,
false);
}
if (version == 1) {
for (unsigned int i=0; i<object_data_points.size(); i+=5)
sla_support_points.emplace_back(std::atof(object_data_points[i+0].c_str()),
std::atof(object_data_points[i+1].c_str()),
std::atof(object_data_points[i+2].c_str()),
std::atof(object_data_points[i+3].c_str()),
std::atof(object_data_points[i+4].c_str()));
}
if (!sla_support_points.empty())
m_sla_support_points.insert(IdToSlaSupportPointsMap::value_type(object_id, sla_support_points));
@ -1983,6 +2002,9 @@ namespace Slic3r {
if (!out.empty())
{
// Adds version header at the beginning:
out = std::string("support_points_format_version=") + std::to_string(support_points_format_version) + std::string("\n") + out;
if (!mz_zip_writer_add_mem(&archive, SLA_SUPPORT_POINTS_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
{
add_error("Unable to add sla support points file to archive");

View file

@ -3,6 +3,23 @@
namespace Slic3r {
/* The format for saving the SLA points was changing in the past. This enum holds the latest version that is being currently used.
* Examples of the Slic3r_PE_sla_support_points.txt for historically used versions:
* version 0 : object_id=1|-12.055421 -2.658771 10.000000
object_id=2|-14.051745 -3.570338 5.000000
// no header and x,y,z positions of the points)
* version 1 : ThreeMF_support_points_version=1
object_id=1|-12.055421 -2.658771 10.000000 0.4 0.0
object_id=2|-14.051745 -3.570338 5.000000 0.6 1.0
// introduced header with version number; x,y,z,head_size,is_new_island)
*/
enum {
support_points_format_version = 1
};
class Model;
class DynamicPrintConfig;

View file

@ -12,7 +12,7 @@
#include <utility>
#include <vector>
#include "Geometry.hpp"
#include <libslic3r/SLA/SLASupportTree.hpp>
#include <libslic3r/SLA/SLACommon.hpp>
namespace Slic3r {

View file

@ -52,20 +52,7 @@ SLAAutoSupports::SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3
const Config& config, std::function<void(void)> throw_on_cancel)
: m_config(config), m_V(emesh.V), m_F(emesh.F), m_throw_on_cancel(throw_on_cancel)
{
// Find all separate islands that will need support. The coord_t number denotes height
// of a point just below the mesh (so that we can later project the point precisely
// on the mesh by raycasting (done by igl) and not risking we will place the point inside).
/*std::vector<std::pair<ExPolygon, coord_t>> islands = */
process(slices, heights);
// Uniformly cover each of the islands with support points.
/*for (const auto& island : islands) {
std::vector<Vec3d> points = uniformly_cover(island);
m_throw_on_cancel();
project_upward_onto_mesh(points);
m_output.insert(m_output.end(), points.begin(), points.end());
m_throw_on_cancel();
}*/
project_onto_mesh(m_output);
}
@ -104,10 +91,14 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
const ExPolygons& expolys_top = slices[i];
const float height = (i>2 ? heights[i-3] : heights[0]-(heights[1]-heights[0]));
const float layer_height = (i!=0 ? heights[i]-heights[i-1] : heights[0]);
const float safe_angle = 5.f * (M_PI/180.f); // smaller number - less supports
const float offset = scale_((i!=0 ? heights[i]-heights[i-1] : heights[0]) / std::tan(safe_angle));
const float pixel_area = 0.047f * 0.047f; // FIXME: calculate actual pixel area from printer config
const float offset = scale_(layer_height / std::tan(safe_angle));
// FIXME: calculate actual pixel area from printer config:
//const float pixel_area = pow(wxGetApp().preset_bundle->project_config.option<ConfigOptionFloat>("display_width") / wxGetApp().preset_bundle->project_config.option<ConfigOptionInt>("display_pixels_x"), 2.f); //
const float pixel_area = pow(0.047f, 2.f);
// Check all ExPolygons on this slice and check whether they are new or belonging to something below.
for (const ExPolygon& polygon : expolys_top) {
@ -119,12 +110,11 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
const ExPolygon* bottom = s.polygon;
if (polygon.overlaps(*bottom) || bottom->overlaps(polygon)) {
m_structures_new.back().structures_below.push_back(&s);
coord_t centroids_dist = (bottom->contour.centroid() - polygon.contour.centroid()).norm();
if (centroids_dist != 0) {
float mult = std::min(1.f, 1.f - std::min(1.f, 500.f * (float)(centroids_dist * centroids_dist) / (float)bottom->area()));
s.supports_force *= mult;
}
//s.supports_force *= std::min(1.f, ((float)polygon.area()/(float)bottom->area()));
float mult = std::min(1.f, 1.f - std::min(1.f, (1600.f * layer_height) * (float)(centroids_dist * centroids_dist) / (float)bottom->area()));
s.supports_force *= mult;
s.supports_force *= std::min(1.f, 20.f * ((float)bottom->area() / (float)polygon.area()));
}
}
}
@ -176,7 +166,7 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
}
e = diff_ex(ExPolygons{*s.polygon}, e);
s.supports_force /= std::max(1., (e_area / (s.polygon->area()*SCALING_FACTOR*SCALING_FACTOR)));
s.supports_force /= std::max(1., (layer_height / 0.3f) * (e_area / (s.polygon->area()*SCALING_FACTOR*SCALING_FACTOR)));

View file

@ -3,7 +3,7 @@
#include <libslic3r/Point.hpp>
#include <libslic3r/TriangleMesh.hpp>
#include <libslic3r/SLA/SLASupportTree.hpp>
#include <libslic3r/SLA/SLACommon.hpp>
// #define SLA_AUTOSUPPORTS_DEBUG

View file

@ -0,0 +1,48 @@
#ifndef SLACOMMON_HPP
#define SLACOMMON_HPP
#include <Eigen/Geometry>
namespace Slic3r {
// Typedef from Point.hpp
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> Vec3f;
namespace sla {
struct SupportPoint {
Vec3f pos;
float head_front_radius;
bool is_new_island;
SupportPoint() :
pos(Vec3f::Zero()), head_front_radius(0.f), is_new_island(false) {}
SupportPoint(float pos_x, float pos_y, float pos_z, float head_radius, bool new_island) :
pos(pos_x, pos_y, pos_z), head_front_radius(head_radius), is_new_island(new_island) {}
SupportPoint(Vec3f position, float head_radius, bool new_island) :
pos(position), head_front_radius(head_radius), is_new_island(new_island) {}
SupportPoint(Eigen::Matrix<float, 5, 1, Eigen::DontAlign> data) :
pos(data(0), data(1), data(2)), head_front_radius(data(3)), is_new_island(data(4)) {}
bool operator==(const SupportPoint& sp) const { return (pos==sp.pos) && head_front_radius==sp.head_front_radius && is_new_island==sp.is_new_island; }
};
/// An index-triangle structure for libIGL functions. Also serves as an
/// alternative (raw) input format for the SLASupportTree
struct EigenMesh3D {
Eigen::MatrixXd V;
Eigen::MatrixXi F;
double ground_level = 0;
};
} // namespace sla
} // namespace Slic3r
#endif // SLASUPPORTTREE_HPP

View file

@ -7,6 +7,9 @@
#include <memory>
#include <Eigen/Geometry>
#include "SLACommon.hpp"
namespace Slic3r {
// Needed types from Point.hpp
@ -34,26 +37,6 @@ enum class PillarConnectionMode {
dynamic
};
struct SupportPoint {
Vec3f pos;
float head_front_radius;
bool is_new_island;
SupportPoint() :
pos(Vec3f::Zero()), head_front_radius(0.f), is_new_island(false) {}
SupportPoint(float pos_x, float pos_y, float pos_z, float head_radius, bool new_island) :
pos(pos_x, pos_y, pos_z), head_front_radius(head_radius), is_new_island(new_island) {}
SupportPoint(Vec3f position, float head_radius, bool new_island) :
pos(position), head_front_radius(head_radius), is_new_island(new_island) {}
SupportPoint(Eigen::Matrix<float, 5, 1, Eigen::DontAlign> data) :
pos(data(0), data(1), data(2)), head_front_radius(data(3)), is_new_island(data(4)) {}
bool operator==(const SupportPoint& sp) const { return (pos==sp.pos) && head_front_radius==sp.head_front_radius && is_new_island==sp.is_new_island; }
};
struct SupportConfig {
// Radius in mm of the pointing side of the head.
double head_front_radius_mm = 0.2;
@ -122,14 +105,6 @@ struct Controller {
std::function<void(void)> cancelfn = [](){};
};
/// An index-triangle structure for libIGL functions. Also serves as an
/// alternative (raw) input format for the SLASupportTree
struct EigenMesh3D {
Eigen::MatrixXd V;
Eigen::MatrixXi F;
double ground_level = 0;
};
using PointSet = Eigen::MatrixXd;
EigenMesh3D to_eigenmesh(const TriangleMesh& m);