Merge remote-tracking branch 'origin/master' into ys_color_print_extension

This commit is contained in:
YuSanka 2019-10-16 10:31:29 +02:00
commit 4fa2567ea2
58 changed files with 3729 additions and 5967 deletions

View file

@ -204,7 +204,7 @@ if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
add_precompiled_header(libslic3r pchheader.hpp FORCEINCLUDE)
endif ()
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB)
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB -DTBB_USE_CAPTURED_EXCEPTION=0)
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBNEST2D_INCLUDES} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(libslic3r
libnest2d
@ -221,7 +221,7 @@ target_link_libraries(libslic3r
poly2tri
qhull
semver
tbb
TBB::tbb
${CMAKE_DL_LIBS}
)

View file

@ -1,7 +1,7 @@
#ifndef slic3r_CoolingBuffer_hpp_
#define slic3r_CoolingBuffer_hpp_
#include "libslic3r.h"
#include "../libslic3r.h"
#include <map>
#include <string>

View file

@ -29,6 +29,8 @@ public:
float value(Axis axis) const { return m_axis[axis]; }
bool has(char axis) const;
bool has_value(char axis, float &value) const;
float new_X(const GCodeReader &reader) const { return this->has(X) ? this->x() : reader.x(); }
float new_Y(const GCodeReader &reader) const { return this->has(Y) ? this->y() : reader.y(); }
float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); }
float new_E(const GCodeReader &reader) const { return this->has(E) ? this->e() : reader.e(); }
float new_F(const GCodeReader &reader) const { return this->has(F) ? this->f() : reader.f(); }

View file

@ -269,7 +269,7 @@ std::string GCodeWriter::set_speed(double F, const std::string &comment, const s
assert(F > 0.);
assert(F < 100000.);
std::ostringstream gcode;
gcode << "G1 F" << F;
gcode << "G1 F" << XYZF_NUM(F);
COMMENT(comment);
gcode << cooling_marker;
gcode << "\n";

View file

@ -9,6 +9,7 @@
#include <cmath>
#include <list>
#include <map>
#include <numeric>
#include <set>
#include <utility>
#include <stack>
@ -16,6 +17,7 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/log/trivial.hpp>
#ifdef SLIC3R_DEBUG
#include "SVG.hpp"
@ -335,6 +337,93 @@ double rad2deg_dir(double angle)
return rad2deg(angle);
}
Point circle_taubin_newton(const Points::const_iterator& input_begin, const Points::const_iterator& input_end, size_t cycles)
{
Vec2ds tmp;
tmp.reserve(std::distance(input_begin, input_end));
std::transform(input_begin, input_end, std::back_inserter(tmp), [] (const Point& in) { return unscale(in); } );
Vec2d center = circle_taubin_newton(tmp.cbegin(), tmp.end(), cycles);
return Point::new_scale(center.x(), center.y());
}
/// Adapted from work in "Circular and Linear Regression: Fitting circles and lines by least squares", pg 126
/// Returns a point corresponding to the center of a circle for which all of the points from input_begin to input_end
/// lie on.
Vec2d circle_taubin_newton(const Vec2ds::const_iterator& input_begin, const Vec2ds::const_iterator& input_end, size_t cycles)
{
// calculate the centroid of the data set
const Vec2d sum = std::accumulate(input_begin, input_end, Vec2d(0,0));
const size_t n = std::distance(input_begin, input_end);
const double n_flt = static_cast<double>(n);
const Vec2d centroid { sum / n_flt };
// Compute the normalized moments of the data set.
double Mxx = 0, Myy = 0, Mxy = 0, Mxz = 0, Myz = 0, Mzz = 0;
for (auto it = input_begin; it < input_end; ++it) {
// center/normalize the data.
double Xi {it->x() - centroid.x()};
double Yi {it->y() - centroid.y()};
double Zi {Xi*Xi + Yi*Yi};
Mxy += (Xi*Yi);
Mxx += (Xi*Xi);
Myy += (Yi*Yi);
Mxz += (Xi*Zi);
Myz += (Yi*Zi);
Mzz += (Zi*Zi);
}
// divide by number of points to get the moments
Mxx /= n_flt;
Myy /= n_flt;
Mxy /= n_flt;
Mxz /= n_flt;
Myz /= n_flt;
Mzz /= n_flt;
// Compute the coefficients of the characteristic polynomial for the circle
// eq 5.60
const double Mz {Mxx + Myy}; // xx + yy = z
const double Cov_xy {Mxx*Myy - Mxy*Mxy}; // this shows up a couple times so cache it here.
const double C3 {4.0*Mz};
const double C2 {-3.0*(Mz*Mz) - Mzz};
const double C1 {Mz*(Mzz - (Mz*Mz)) + 4.0*Mz*Cov_xy - (Mxz*Mxz) - (Myz*Myz)};
const double C0 {(Mxz*Mxz)*Myy + (Myz*Myz)*Mxx - 2.0*Mxz*Myz*Mxy - Cov_xy*(Mzz - (Mz*Mz))};
const double C22 = {C2 + C2};
const double C33 = {C3 + C3 + C3};
// solve the characteristic polynomial with Newton's method.
double xnew = 0.0;
double ynew = 1e20;
for (size_t i = 0; i < cycles; ++i) {
const double yold {ynew};
ynew = C0 + xnew * (C1 + xnew*(C2 + xnew * C3));
if (std::abs(ynew) > std::abs(yold)) {
BOOST_LOG_TRIVIAL(error) << "Geometry: Fit is going in the wrong direction.\n";
return Vec2d(std::nan(""), std::nan(""));
}
const double Dy {C1 + xnew*(C22 + xnew*C33)};
const double xold {xnew};
xnew = xold - (ynew / Dy);
if (std::abs((xnew-xold) / xnew) < 1e-12) i = cycles; // converged, we're done here
if (xnew < 0) {
// reset, we went negative
xnew = 0.0;
}
}
// compute the determinant and the circle's parameters now that we've solved.
double DET = xnew*xnew - xnew*Mz + Cov_xy;
Vec2d center(Mxz * (Myy - xnew) - Myz * Mxy, Myz * (Mxx - xnew) - Mxz*Mxy);
center /= (DET * 2.);
return center + centroid;
}
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
{
Polygons pp;

View file

@ -162,6 +162,15 @@ template<typename T> T angle_to_0_2PI(T angle)
return angle;
}
/// Find the center of the circle corresponding to the vector of Points as an arc.
Point circle_taubin_newton(const Points::const_iterator& input_start, const Points::const_iterator& input_end, size_t cycles = 20);
inline Point circle_taubin_newton(const Points& input, size_t cycles = 20) { return circle_taubin_newton(input.cbegin(), input.cend(), cycles); }
/// Find the center of the circle corresponding to the vector of Pointfs as an arc.
Vec2d circle_taubin_newton(const Vec2ds::const_iterator& input_start, const Vec2ds::const_iterator& input_end, size_t cycles = 20);
inline Vec2d circle_taubin_newton(const Vec2ds& input, size_t cycles = 20) { return circle_taubin_newton(input.cbegin(), input.cend(), cycles); }
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval);
double linint(double value, double oldmin, double oldmax, double newmin, double newmax);

View file

@ -86,10 +86,7 @@ bool Line::intersection(const Line &l2, Point *intersection) const
const Line &l1 = *this;
const Vec2d v1 = (l1.b - l1.a).cast<double>();
const Vec2d v2 = (l2.b - l2.a).cast<double>();
const Vec2d v12 = (l1.a - l2.a).cast<double>();
double denom = cross2(v1, v2);
double nume_a = cross2(v2, v12);
double nume_b = cross2(v1, v12);
if (fabs(denom) < EPSILON)
#if 0
// Lines are collinear. Return true if they are coincident (overlappign).
@ -97,6 +94,9 @@ bool Line::intersection(const Line &l2, Point *intersection) const
#else
return false;
#endif
const Vec2d v12 = (l1.a - l2.a).cast<double>();
double nume_a = cross2(v2, v12);
double nume_b = cross2(v1, v12);
double t1 = nume_a / denom;
double t2 = nume_b / denom;
if (t1 >= 0 && t1 <= 1.0f && t2 >= 0 && t2 <= 1.0f) {

View file

@ -38,6 +38,7 @@ typedef std::vector<Point*> PointPtrs;
typedef std::vector<const Point*> PointConstPtrs;
typedef std::vector<Vec3crd> Points3;
typedef std::vector<Vec2d> Pointfs;
typedef std::vector<Vec2d> Vec2ds;
typedef std::vector<Vec3d> Pointf3s;
typedef Eigen::Matrix<float, 2, 2, Eigen::DontAlign> Matrix2f;
@ -87,12 +88,13 @@ class Point : public Vec2crd
public:
typedef coord_t coord_type;
Point() : Vec2crd() { (*this)(0) = 0; (*this)(1) = 0; }
Point(coord_t x, coord_t y) { (*this)(0) = x; (*this)(1) = y; }
Point(int64_t x, int64_t y) { (*this)(0) = coord_t(x); (*this)(1) = coord_t(y); } // for Clipper
Point(double x, double y) { (*this)(0) = coord_t(lrint(x)); (*this)(1) = coord_t(lrint(y)); }
Point() : Vec2crd(0, 0) {}
Point(coord_t x, coord_t y) : Vec2crd(x, y) {}
Point(int64_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {} // for Clipper
Point(double x, double y) : Vec2crd(coord_t(lrint(x)), coord_t(lrint(y))) {}
Point(const Point &rhs) { *this = rhs; }
// This constructor allows you to construct Point from Eigen expressions
explicit Point(const Vec2d& rhs) : Vec2crd(coord_t(lrint(rhs.x())), coord_t(lrint(rhs.y()))) {}
// This constructor allows you to construct Point from Eigen expressions
template<typename OtherDerived>
Point(const Eigen::MatrixBase<OtherDerived> &other) : Vec2crd(other) {}
static Point new_scale(coordf_t x, coordf_t y) { return Point(coord_t(scale_(x)), coord_t(scale_(y))); }
@ -126,6 +128,36 @@ public:
Point projection_onto(const Line &line) const;
};
inline bool is_approx(const Point &p1, const Point &p2, coord_t epsilon = coord_t(SCALED_EPSILON))
{
Point d = (p2 - p1).cwiseAbs();
return d.x() < epsilon && d.y() < epsilon;
}
inline bool is_approx(const Vec2f &p1, const Vec2f &p2, float epsilon = float(EPSILON))
{
Vec2f d = (p2 - p1).cwiseAbs();
return d.x() < epsilon && d.y() < epsilon;
}
inline bool is_approx(const Vec2d &p1, const Vec2d &p2, double epsilon = EPSILON)
{
Vec2d d = (p2 - p1).cwiseAbs();
return d.x() < epsilon && d.y() < epsilon;
}
inline bool is_approx(const Vec3f &p1, const Vec3f &p2, float epsilon = float(EPSILON))
{
Vec3f d = (p2 - p1).cwiseAbs();
return d.x() < epsilon && d.y() < epsilon && d.z() < epsilon;
}
inline bool is_approx(const Vec3d &p1, const Vec3d &p2, double epsilon = EPSILON)
{
Vec3d d = (p2 - p1).cwiseAbs();
return d.x() < epsilon && d.y() < epsilon && d.z() < epsilon;
}
namespace int128 {
// Exact orientation predicate,
// returns +1: CCW, 0: collinear, -1: CW.

View file

@ -15,7 +15,7 @@ Polyline Polygon::split_at_vertex(const Point &point) const
// find index of point
for (const Point &pt : this->points)
if (pt == point)
return this->split_at_index(&pt - &this->points.front());
return this->split_at_index(int(&pt - &this->points.front()));
throw std::invalid_argument("Point not found");
return Polyline();
}
@ -175,16 +175,16 @@ Point Polygon::centroid() const
Points Polygon::concave_points(double angle) const
{
Points points;
angle = 2*PI - angle;
angle = 2. * PI - angle + EPSILON;
// check whether first point forms a concave angle
if (this->points.front().ccw_angle(this->points.back(), *(this->points.begin()+1)) <= angle)
points.push_back(this->points.front());
// check whether points 1..(n-1) form concave angles
for (Points::const_iterator p = this->points.begin()+1; p != this->points.end()-1; ++p) {
if (p->ccw_angle(*(p-1), *(p+1)) <= angle) points.push_back(*p);
}
for (Points::const_iterator p = this->points.begin()+1; p != this->points.end()-1; ++ p)
if (p->ccw_angle(*(p-1), *(p+1)) <= angle)
points.push_back(*p);
// check whether last point forms a concave angle
if (this->points.back().ccw_angle(*(this->points.end()-2), this->points.front()) <= angle)
@ -198,7 +198,7 @@ Points Polygon::concave_points(double angle) const
Points Polygon::convex_points(double angle) const
{
Points points;
angle = 2*PI - angle;
angle = 2*PI - angle - EPSILON;
// check whether first point forms a convex angle
if (this->points.front().ccw_angle(this->points.back(), *(this->points.begin()+1)) >= angle)
@ -394,4 +394,45 @@ bool remove_small(Polygons &polys, double min_area)
return modified;
}
void remove_collinear(Polygon &poly)
{
if (poly.points.size() > 2) {
// copy points and append both 1 and last point in place to cover the boundaries
Points pp;
pp.reserve(poly.points.size()+2);
pp.push_back(poly.points.back());
pp.insert(pp.begin()+1, poly.points.begin(), poly.points.end());
pp.push_back(poly.points.front());
// delete old points vector. Will be re-filled in the loop
poly.points.clear();
size_t i = 0;
size_t k = 0;
while (i < pp.size()-2) {
k = i+1;
const Point &p1 = pp[i];
while (k < pp.size()-1) {
const Point &p2 = pp[k];
const Point &p3 = pp[k+1];
Line l(p1, p3);
if(l.distance_to(p2) < SCALED_EPSILON) {
k++;
} else {
if(i > 0) poly.points.push_back(p1); // implicitly removes the first point we appended above
i = k;
break;
}
}
if(k > pp.size()-2) break; // all remaining points are collinear and can be skipped
}
poly.points.push_back(pp[i]);
}
}
void remove_collinear(Polygons &polys)
{
for (Polygon &poly : polys)
remove_collinear(poly);
}
}

View file

@ -86,6 +86,8 @@ extern bool remove_sticks(Polygons &polys);
// Remove polygons with less than 3 edges.
extern bool remove_degenerate(Polygons &polys);
extern bool remove_small(Polygons &polys, double min_area);
extern void remove_collinear(Polygon &poly);
extern void remove_collinear(Polygons &polys);
// Append a vector of polygons at the end of another vector of polygons.
inline void polygons_append(Polygons &dst, const Polygons &src) { dst.insert(dst.end(), src.begin(), src.end()); }

View file

@ -29,7 +29,7 @@ PrintConfigDef::PrintConfigDef()
this->init_common_params();
assign_printer_technology_to_unknown(this->options, ptAny);
this->init_fff_params();
this->init_extruder_retract_keys();
this->init_extruder_option_keys();
assign_printer_technology_to_unknown(this->options, ptFFF);
this->init_sla_params();
assign_printer_technology_to_unknown(this->options, ptSLA);
@ -2270,8 +2270,17 @@ void PrintConfigDef::init_fff_params()
}
}
void PrintConfigDef::init_extruder_retract_keys()
void PrintConfigDef::init_extruder_option_keys()
{
// ConfigOptionFloats, ConfigOptionPercents, ConfigOptionBools, ConfigOptionStrings
m_extruder_option_keys = {
"nozzle_diameter", "min_layer_height", "max_layer_height", "extruder_offset",
"retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed",
"retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe",
"retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour",
"default_filament_profile"
};
m_extruder_retract_keys = {
"deretract_speed",
"retract_before_travel",
@ -2938,6 +2947,20 @@ void DynamicPrintConfig::normalize()
}
}
void DynamicPrintConfig::set_num_extruders(unsigned int num_extruders)
{
const auto &defaults = FullPrintConfig::defaults();
for (const std::string &key : print_config_def.extruder_option_keys()) {
if (key == "default_filament_profile")
continue;
auto *opt = this->option(key, false);
assert(opt != nullptr);
assert(opt->is_vector());
if (opt != nullptr && opt->is_vector())
static_cast<ConfigOptionVectorBase*>(opt)->resize(num_extruders, defaults.option(key));
}
}
std::string DynamicPrintConfig::validate()
{
// Full print config is initialized from the defaults.

View file

@ -193,6 +193,8 @@ public:
static void handle_legacy(t_config_option_key &opt_key, std::string &value);
// Array options growing with the number of extruders
const std::vector<std::string>& extruder_option_keys() const { return m_extruder_option_keys; }
// Options defining the extruder retract properties. These keys are sorted lexicographically.
// The extruder retract keys could be overidden by the same values defined at the Filament level
// (then the key is further prefixed with the "filament_" prefix).
@ -201,9 +203,10 @@ public:
private:
void init_common_params();
void init_fff_params();
void init_extruder_retract_keys();
void init_extruder_option_keys();
void init_sla_params();
std::vector<std::string> m_extruder_option_keys;
std::vector<std::string> m_extruder_retract_keys;
};
@ -231,6 +234,8 @@ public:
void normalize();
void set_num_extruders(unsigned int num_extruders);
// Validate the PrintConfig. Returns an empty string on success, otherwise an error message is returned.
std::string validate();

View file

@ -11,7 +11,7 @@
#include <map>
#endif
#include "libslic3r/Utils.hpp"
// #include "libslic3r/Utils.hpp"
namespace Slic3r {
namespace Utils {

View file

@ -593,6 +593,16 @@ TriangleMesh TriangleMesh::convex_hull_3d() const
return output_mesh;
}
std::vector<ExPolygons> TriangleMesh::slice(const std::vector<double> &z)
{
// convert doubles to floats
std::vector<float> z_f(z.begin(), z.end());
TriangleMeshSlicer mslicer(this);
std::vector<ExPolygons> layers;
mslicer.slice(z_f, 0.0004f, &layers, [](){});
return layers;
}
void TriangleMesh::require_shared_vertices()
{
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - start";
@ -1861,7 +1871,8 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
}
// Generate the vertex list for a cube solid of arbitrary size in X/Y/Z.
TriangleMesh make_cube(double x, double y, double z) {
TriangleMesh make_cube(double x, double y, double z)
{
Vec3d pv[8] = {
Vec3d(x, y, 0), Vec3d(x, 0, 0), Vec3d(0, 0, 0),
Vec3d(0, y, 0), Vec3d(x, y, z), Vec3d(0, y, z),
@ -1878,7 +1889,8 @@ TriangleMesh make_cube(double x, double y, double z) {
Pointf3s vertices(&pv[0], &pv[0]+8);
TriangleMesh mesh(vertices ,facets);
return mesh;
mesh.repair();
return mesh;
}
// Generate the mesh for a cylinder and return it, using
@ -1922,7 +1934,9 @@ TriangleMesh make_cylinder(double r, double h, double fa)
facets.emplace_back(Vec3crd(id, 2, 3));
facets.emplace_back(Vec3crd(id, id - 1, 2));
return TriangleMesh(std::move(vertices), std::move(facets));
TriangleMesh mesh(std::move(vertices), std::move(facets));
mesh.repair();
return mesh;
}
// Generates mesh for a sphere centered about the origin, using the generated angle
@ -1978,7 +1992,9 @@ TriangleMesh make_sphere(double radius, double fa)
k2 = k2_next;
}
}
return TriangleMesh(std::move(vertices), std::move(facets));
TriangleMesh mesh(std::move(vertices), std::move(facets));
mesh.repair();
return mesh;
}
}

View file

@ -58,8 +58,14 @@ public:
BoundingBoxf3 bounding_box() const;
// Returns the bbox of this TriangleMesh transformed by the given transformation
BoundingBoxf3 transformed_bounding_box(const Transform3d &trafo) const;
// Return the size of the mesh in coordinates.
Vec3d size() const { return stl.stats.size.cast<double>(); }
/// Return the center of the related bounding box.
Vec3d center() const { return this->bounding_box().center(); }
// Returns the convex hull of this TriangleMesh
TriangleMesh convex_hull_3d() const;
// Slice this mesh at the provided Z levels and return the vector
std::vector<ExPolygons> slice(const std::vector<double>& z);
void reset_repair_stats();
bool needed_repair() const;
void require_shared_vertices();