Merge remote-tracking branch 'origin/dev' into sla_base_pool

This commit is contained in:
tamasmeszaros 2018-08-27 09:53:52 +02:00
commit d749080261
388 changed files with 115166 additions and 3275 deletions

View file

@ -7,9 +7,9 @@
namespace Slic3r {
template BoundingBoxBase<Point>::BoundingBoxBase(const std::vector<Point> &points);
template BoundingBoxBase<Pointf>::BoundingBoxBase(const std::vector<Pointf> &points);
template BoundingBoxBase<Vec2d>::BoundingBoxBase(const std::vector<Vec2d> &points);
template BoundingBox3Base<Pointf3>::BoundingBox3Base(const std::vector<Pointf3> &points);
template BoundingBox3Base<Vec3d>::BoundingBox3Base(const std::vector<Vec3d> &points);
BoundingBox::BoundingBox(const Lines &lines)
{
@ -22,8 +22,7 @@ BoundingBox::BoundingBox(const Lines &lines)
*this = BoundingBox(points);
}
void
BoundingBox::polygon(Polygon* polygon) const
void BoundingBox::polygon(Polygon* polygon) const
{
polygon->points.clear();
polygon->points.resize(4);
@ -37,8 +36,7 @@ BoundingBox::polygon(Polygon* polygon) const
polygon->points[3](1) = this->max(1);
}
Polygon
BoundingBox::polygon() const
Polygon BoundingBox::polygon() const
{
Polygon p;
this->polygon(&p);
@ -72,24 +70,23 @@ BoundingBoxBase<PointClass>::scale(double factor)
this->max *= factor;
}
template void BoundingBoxBase<Point>::scale(double factor);
template void BoundingBoxBase<Pointf>::scale(double factor);
template void BoundingBoxBase<Pointf3>::scale(double factor);
template void BoundingBoxBase<Vec2d>::scale(double factor);
template void BoundingBoxBase<Vec3d>::scale(double factor);
template <class PointClass> void
BoundingBoxBase<PointClass>::merge(const PointClass &point)
{
if (this->defined) {
this->min(0) = std::min(point(0), this->min(0));
this->min(1) = std::min(point(1), this->min(1));
this->max(0) = std::max(point(0), this->max(0));
this->max(1) = std::max(point(1), this->max(1));
this->min = this->min.cwiseMin(point);
this->max = this->max.cwiseMax(point);
} else {
this->min = this->max = point;
this->min = point;
this->max = point;
this->defined = true;
}
}
template void BoundingBoxBase<Point>::merge(const Point &point);
template void BoundingBoxBase<Pointf>::merge(const Pointf &point);
template void BoundingBoxBase<Vec2d>::merge(const Vec2d &point);
template <class PointClass> void
BoundingBoxBase<PointClass>::merge(const std::vector<PointClass> &points)
@ -97,7 +94,7 @@ BoundingBoxBase<PointClass>::merge(const std::vector<PointClass> &points)
this->merge(BoundingBoxBase(points));
}
template void BoundingBoxBase<Point>::merge(const Points &points);
template void BoundingBoxBase<Pointf>::merge(const Pointfs &points);
template void BoundingBoxBase<Vec2d>::merge(const Pointfs &points);
template <class PointClass> void
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
@ -105,10 +102,8 @@ BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
assert(bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1));
if (bb.defined) {
if (this->defined) {
this->min(0) = std::min(bb.min(0), this->min(0));
this->min(1) = std::min(bb.min(1), this->min(1));
this->max(0) = std::max(bb.max(0), this->max(0));
this->max(1) = std::max(bb.max(1), this->max(1));
this->min = this->min.cwiseMin(bb.min);
this->max = this->max.cwiseMax(bb.max);
} else {
this->min = bb.min;
this->max = bb.max;
@ -117,25 +112,28 @@ BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
}
}
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
template void BoundingBoxBase<Pointf>::merge(const BoundingBoxBase<Pointf> &bb);
template void BoundingBoxBase<Vec2d>::merge(const BoundingBoxBase<Vec2d> &bb);
template <class PointClass> void
BoundingBox3Base<PointClass>::merge(const PointClass &point)
{
if (this->defined) {
this->min(2) = std::min(point(2), this->min(2));
this->max(2) = std::max(point(2), this->max(2));
this->min = this->min.cwiseMin(point);
this->max = this->max.cwiseMax(point);
} else {
this->min = point;
this->max = point;
this->defined = true;
}
BoundingBoxBase<PointClass>::merge(point);
}
template void BoundingBox3Base<Pointf3>::merge(const Pointf3 &point);
template void BoundingBox3Base<Vec3d>::merge(const Vec3d &point);
template <class PointClass> void
BoundingBox3Base<PointClass>::merge(const std::vector<PointClass> &points)
{
this->merge(BoundingBox3Base(points));
}
template void BoundingBox3Base<Pointf3>::merge(const Pointf3s &points);
template void BoundingBox3Base<Vec3d>::merge(const Pointf3s &points);
template <class PointClass> void
BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
@ -143,13 +141,16 @@ BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
assert(bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1) || bb.min(2) >= bb.max(2));
if (bb.defined) {
if (this->defined) {
this->min(2) = std::min(bb.min(2), this->min(2));
this->max(2) = std::max(bb.max(2), this->max(2));
this->min = this->min.cwiseMin(bb.min);
this->max = this->max.cwiseMax(bb.max);
} else {
this->min = bb.min;
this->max = bb.max;
this->defined = true;
}
BoundingBoxBase<PointClass>::merge(bb);
}
}
template void BoundingBox3Base<Pointf3>::merge(const BoundingBox3Base<Pointf3> &bb);
template void BoundingBox3Base<Vec3d>::merge(const BoundingBox3Base<Vec3d> &bb);
template <class PointClass> PointClass
BoundingBoxBase<PointClass>::size() const
@ -157,14 +158,14 @@ BoundingBoxBase<PointClass>::size() const
return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1));
}
template Point BoundingBoxBase<Point>::size() const;
template Pointf BoundingBoxBase<Pointf>::size() const;
template Vec2d BoundingBoxBase<Vec2d>::size() const;
template <class PointClass> PointClass
BoundingBox3Base<PointClass>::size() const
{
return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1), this->max(2) - this->min(2));
}
template Pointf3 BoundingBox3Base<Pointf3>::size() const;
template Vec3d BoundingBox3Base<Vec3d>::size() const;
template <class PointClass> double BoundingBoxBase<PointClass>::radius() const
{
@ -174,7 +175,7 @@ template <class PointClass> double BoundingBoxBase<PointClass>::radius() const
return 0.5 * sqrt(x*x+y*y);
}
template double BoundingBoxBase<Point>::radius() const;
template double BoundingBoxBase<Pointf>::radius() const;
template double BoundingBoxBase<Vec2d>::radius() const;
template <class PointClass> double BoundingBox3Base<PointClass>::radius() const
{
@ -183,7 +184,7 @@ template <class PointClass> double BoundingBox3Base<PointClass>::radius() const
double z = this->max(2) - this->min(2);
return 0.5 * sqrt(x*x+y*y+z*z);
}
template double BoundingBox3Base<Pointf3>::radius() const;
template double BoundingBox3Base<Vec3d>::radius() const;
template <class PointClass> void
BoundingBoxBase<PointClass>::offset(coordf_t delta)
@ -193,7 +194,7 @@ BoundingBoxBase<PointClass>::offset(coordf_t delta)
this->max += v;
}
template void BoundingBoxBase<Point>::offset(coordf_t delta);
template void BoundingBoxBase<Pointf>::offset(coordf_t delta);
template void BoundingBoxBase<Vec2d>::offset(coordf_t delta);
template <class PointClass> void
BoundingBox3Base<PointClass>::offset(coordf_t delta)
@ -202,29 +203,22 @@ BoundingBox3Base<PointClass>::offset(coordf_t delta)
this->min -= v;
this->max += v;
}
template void BoundingBox3Base<Pointf3>::offset(coordf_t delta);
template void BoundingBox3Base<Vec3d>::offset(coordf_t delta);
template <class PointClass> PointClass
BoundingBoxBase<PointClass>::center() const
{
return PointClass(
(this->max(0) + this->min(0))/2,
(this->max(1) + this->min(1))/2
);
return (this->min + this->max) / 2;
}
template Point BoundingBoxBase<Point>::center() const;
template Pointf BoundingBoxBase<Pointf>::center() const;
template Vec2d BoundingBoxBase<Vec2d>::center() const;
template <class PointClass> PointClass
BoundingBox3Base<PointClass>::center() const
{
return PointClass(
(this->max(0) + this->min(0))/2,
(this->max(1) + this->min(1))/2,
(this->max(2) + this->min(2))/2
);
return (this->min + this->max) / 2;
}
template Pointf3 BoundingBox3Base<Pointf3>::center() const;
template Vec3d BoundingBox3Base<Vec3d>::center() const;
template <class PointClass> coordf_t
BoundingBox3Base<PointClass>::max_size() const
@ -232,7 +226,7 @@ BoundingBox3Base<PointClass>::max_size() const
PointClass s = size();
return std::max(s(0), std::max(s(1), s(2)));
}
template coordf_t BoundingBox3Base<Pointf3>::max_size() const;
template coordf_t BoundingBox3Base<Vec3d>::max_size() const;
// Align a coordinate to a grid. The coordinate may be negative,
// the aligned value will never be bigger than the original one.
@ -255,39 +249,35 @@ void BoundingBox::align_to_grid(const coord_t cell_size)
}
}
BoundingBoxf3 BoundingBoxf3::transformed(const Transform3f& matrix) const
BoundingBoxf3 BoundingBoxf3::transformed(const Transform3d& matrix) const
{
Eigen::Matrix<float, 3, 8, Eigen::DontAlign> vertices;
typedef Eigen::Matrix<double, 3, 8, Eigen::DontAlign> Vertices;
vertices(0, 0) = (float)min(0); vertices(1, 0) = (float)min(1); vertices(2, 0) = (float)min(2);
vertices(0, 1) = (float)max(0); vertices(1, 1) = (float)min(1); vertices(2, 1) = (float)min(2);
vertices(0, 2) = (float)max(0); vertices(1, 2) = (float)max(1); vertices(2, 2) = (float)min(2);
vertices(0, 3) = (float)min(0); vertices(1, 3) = (float)max(1); vertices(2, 3) = (float)min(2);
vertices(0, 4) = (float)min(0); vertices(1, 4) = (float)min(1); vertices(2, 4) = (float)max(2);
vertices(0, 5) = (float)max(0); vertices(1, 5) = (float)min(1); vertices(2, 5) = (float)max(2);
vertices(0, 6) = (float)max(0); vertices(1, 6) = (float)max(1); vertices(2, 6) = (float)max(2);
vertices(0, 7) = (float)min(0); vertices(1, 7) = (float)max(1); vertices(2, 7) = (float)max(2);
Vertices src_vertices;
src_vertices(0, 0) = min(0); src_vertices(1, 0) = min(1); src_vertices(2, 0) = min(2);
src_vertices(0, 1) = max(0); src_vertices(1, 1) = min(1); src_vertices(2, 1) = min(2);
src_vertices(0, 2) = max(0); src_vertices(1, 2) = max(1); src_vertices(2, 2) = min(2);
src_vertices(0, 3) = min(0); src_vertices(1, 3) = max(1); src_vertices(2, 3) = min(2);
src_vertices(0, 4) = min(0); src_vertices(1, 4) = min(1); src_vertices(2, 4) = max(2);
src_vertices(0, 5) = max(0); src_vertices(1, 5) = min(1); src_vertices(2, 5) = max(2);
src_vertices(0, 6) = max(0); src_vertices(1, 6) = max(1); src_vertices(2, 6) = max(2);
src_vertices(0, 7) = min(0); src_vertices(1, 7) = max(1); src_vertices(2, 7) = max(2);
Eigen::Matrix<float, 3, 8, Eigen::DontAlign> transf_vertices = matrix * vertices.colwise().homogeneous();
Vertices dst_vertices = matrix * src_vertices.colwise().homogeneous();
float min_x = transf_vertices(0, 0);
float max_x = transf_vertices(0, 0);
float min_y = transf_vertices(1, 0);
float max_y = transf_vertices(1, 0);
float min_z = transf_vertices(2, 0);
float max_z = transf_vertices(2, 0);
Vec3d v_min(dst_vertices(0, 0), dst_vertices(1, 0), dst_vertices(2, 0));
Vec3d v_max = v_min;
for (int i = 1; i < 8; ++i)
{
min_x = std::min(min_x, transf_vertices(0, i));
max_x = std::max(max_x, transf_vertices(0, i));
min_y = std::min(min_y, transf_vertices(1, i));
max_y = std::max(max_y, transf_vertices(1, i));
min_z = std::min(min_z, transf_vertices(2, i));
max_z = std::max(max_z, transf_vertices(2, i));
for (int j = 0; j < 3; ++j)
{
v_min(j) = std::min(v_min(j), dst_vertices(j, i));
v_max(j) = std::max(v_max(j), dst_vertices(j, i));
}
}
return BoundingBoxf3(Pointf3((coordf_t)min_x, (coordf_t)min_y, (coordf_t)min_z), Pointf3((coordf_t)max_x, (coordf_t)max_y, (coordf_t)max_z));
return BoundingBoxf3(v_min, v_max);
}
}

View file

@ -7,11 +7,6 @@
namespace Slic3r {
typedef Point Size;
typedef Point3 Size3;
typedef Pointf Sizef;
typedef Pointf3 Sizef3;
template <class PointClass>
class BoundingBoxBase
{
@ -20,23 +15,20 @@ public:
PointClass max;
bool defined;
BoundingBoxBase() : defined(false) {};
BoundingBoxBase() : defined(false), min(PointClass::Zero()), max(PointClass::Zero()) {}
BoundingBoxBase(const PointClass &pmin, const PointClass &pmax) :
min(pmin), max(pmax), defined(pmin(0) < pmax(0) && pmin(1) < pmax(1)) {}
BoundingBoxBase(const std::vector<PointClass>& points)
BoundingBoxBase(const std::vector<PointClass>& points) : min(PointClass::Zero()), max(PointClass::Zero())
{
if (points.empty())
CONFESS("Empty point set supplied to BoundingBoxBase constructor");
typename std::vector<PointClass>::const_iterator it = points.begin();
this->min(0) = this->max(0) = (*it)(0);
this->min(1) = this->max(1) = (*it)(1);
for (++it; it != points.end(); ++it)
{
this->min(0) = std::min((*it)(0), this->min(0));
this->min(1) = std::min((*it)(1), this->min(1));
this->max(0) = std::max((*it)(0), this->max(0));
this->max(1) = std::max((*it)(1), this->max(1));
this->min = *it;
this->max = *it;
for (++ it; it != points.end(); ++ it) {
this->min = this->min.cwiseMin(*it);
this->max = this->max.cwiseMax(*it);
}
this->defined = (this->min(0) < this->max(0)) && (this->min(1) < this->max(1));
}
@ -47,7 +39,7 @@ public:
PointClass size() const;
double radius() const;
void translate(coordf_t x, coordf_t y) { assert(this->defined); PointClass v(x, y); this->min += v; this->max += v; }
void translate(const Pointf &v) { this->min += v; this->max += v; }
void translate(const Vec2d &v) { this->min += v; this->max += v; }
void offset(coordf_t delta);
PointClass center() const;
bool contains(const PointClass &point) const {
@ -71,19 +63,17 @@ public:
BoundingBoxBase<PointClass>(pmin, pmax)
{ if (pmin(2) >= pmax(2)) BoundingBoxBase<PointClass>::defined = false; }
BoundingBox3Base(const std::vector<PointClass>& points)
: BoundingBoxBase<PointClass>(points)
{
if (points.empty())
CONFESS("Empty point set supplied to BoundingBox3Base constructor");
typename std::vector<PointClass>::const_iterator it = points.begin();
this->min(2) = this->max(2) = (*it)(2);
for (++it; it != points.end(); ++it)
{
this->min(2) = std::min((*it)(2), this->min(2));
this->max(2) = std::max((*it)(2), this->max(2));
this->min = *it;
this->max = *it;
for (++ it; it != points.end(); ++ it) {
this->min = this->min.cwiseMin(*it);
this->max = this->max.cwiseMax(*it);
}
this->defined &= (this->min(2) < this->max(2));
this->defined = (this->min(0) < this->max(0)) && (this->min(1) < this->max(1)) && (this->min(2) < this->max(2));
}
void merge(const PointClass &point);
void merge(const std::vector<PointClass> &points);
@ -91,7 +81,7 @@ public:
PointClass size() const;
double radius() const;
void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointClass v(x, y, z); this->min += v; this->max += v; }
void translate(const Pointf3 &v) { this->min += v; this->max += v; }
void translate(const Vec3d &v) { this->min += v; this->max += v; }
void offset(coordf_t delta);
PointClass center() const;
coordf_t max_size() const;
@ -130,30 +120,30 @@ public:
friend BoundingBox get_extents_rotated(const Points &points, double angle);
};
class BoundingBox3 : public BoundingBox3Base<Point3>
class BoundingBox3 : public BoundingBox3Base<Vec3crd>
{
public:
BoundingBox3() : BoundingBox3Base<Point3>() {};
BoundingBox3(const Point3 &pmin, const Point3 &pmax) : BoundingBox3Base<Point3>(pmin, pmax) {};
BoundingBox3(const Points3& points) : BoundingBox3Base<Point3>(points) {};
BoundingBox3() : BoundingBox3Base<Vec3crd>() {};
BoundingBox3(const Vec3crd &pmin, const Vec3crd &pmax) : BoundingBox3Base<Vec3crd>(pmin, pmax) {};
BoundingBox3(const Points3& points) : BoundingBox3Base<Vec3crd>(points) {};
};
class BoundingBoxf : public BoundingBoxBase<Pointf>
class BoundingBoxf : public BoundingBoxBase<Vec2d>
{
public:
BoundingBoxf() : BoundingBoxBase<Pointf>() {};
BoundingBoxf(const Pointf &pmin, const Pointf &pmax) : BoundingBoxBase<Pointf>(pmin, pmax) {};
BoundingBoxf(const std::vector<Pointf> &points) : BoundingBoxBase<Pointf>(points) {};
BoundingBoxf() : BoundingBoxBase<Vec2d>() {};
BoundingBoxf(const Vec2d &pmin, const Vec2d &pmax) : BoundingBoxBase<Vec2d>(pmin, pmax) {};
BoundingBoxf(const std::vector<Vec2d> &points) : BoundingBoxBase<Vec2d>(points) {};
};
class BoundingBoxf3 : public BoundingBox3Base<Pointf3>
class BoundingBoxf3 : public BoundingBox3Base<Vec3d>
{
public:
BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base<Pointf3>(pmin, pmax) {};
BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(points) {};
BoundingBoxf3() : BoundingBox3Base<Vec3d>() {};
BoundingBoxf3(const Vec3d &pmin, const Vec3d &pmax) : BoundingBox3Base<Vec3d>(pmin, pmax) {};
BoundingBoxf3(const std::vector<Vec3d> &points) : BoundingBox3Base<Vec3d>(points) {};
BoundingBoxf3 transformed(const Transform3f& matrix) const;
BoundingBoxf3 transformed(const Transform3d& matrix) const;
};
template<typename VT>

View file

@ -49,9 +49,9 @@ enum ConfigOptionType {
coPercents = coPercent + coVectorType,
// a fraction or an absolute value
coFloatOrPercent = 5,
// single 2d point. Currently not used.
// single 2d point (Point2f). Currently not used.
coPoint = 6,
// vector of 2d points. Currently used for the definition of the print bed and for the extruder offsets.
// vector of 2d points (Point2f). Currently used for the definition of the print bed and for the extruder offsets.
coPoints = coPoint + coVectorType,
// single boolean value
coBool = 7,
@ -622,11 +622,11 @@ public:
}
};
class ConfigOptionPoint : public ConfigOptionSingle<Pointf>
class ConfigOptionPoint : public ConfigOptionSingle<Vec2d>
{
public:
ConfigOptionPoint() : ConfigOptionSingle<Pointf>(Pointf(0,0)) {}
explicit ConfigOptionPoint(const Pointf &value) : ConfigOptionSingle<Pointf>(value) {}
ConfigOptionPoint() : ConfigOptionSingle<Vec2d>(Vec2d(0,0)) {}
explicit ConfigOptionPoint(const Vec2d &value) : ConfigOptionSingle<Vec2d>(value) {}
static ConfigOptionType static_type() { return coPoint; }
ConfigOptionType type() const override { return static_type(); }
@ -652,13 +652,13 @@ public:
}
};
class ConfigOptionPoints : public ConfigOptionVector<Pointf>
class ConfigOptionPoints : public ConfigOptionVector<Vec2d>
{
public:
ConfigOptionPoints() : ConfigOptionVector<Pointf>() {}
explicit ConfigOptionPoints(size_t n, const Pointf &value) : ConfigOptionVector<Pointf>(n, value) {}
explicit ConfigOptionPoints(std::initializer_list<Pointf> il) : ConfigOptionVector<Pointf>(std::move(il)) {}
explicit ConfigOptionPoints(const std::vector<Pointf> &values) : ConfigOptionVector<Pointf>(values) {}
ConfigOptionPoints() : ConfigOptionVector<Vec2d>() {}
explicit ConfigOptionPoints(size_t n, const Vec2d &value) : ConfigOptionVector<Vec2d>(n, value) {}
explicit ConfigOptionPoints(std::initializer_list<Vec2d> il) : ConfigOptionVector<Vec2d>(std::move(il)) {}
explicit ConfigOptionPoints(const std::vector<Vec2d> &values) : ConfigOptionVector<Vec2d>(values) {}
static ConfigOptionType static_type() { return coPoints; }
ConfigOptionType type() const override { return static_type(); }
@ -696,7 +696,7 @@ public:
std::istringstream is(str);
std::string point_str;
while (std::getline(is, point_str, ',')) {
Pointf point;
Vec2d point(Vec2d::Zero());
std::istringstream iss(point_str);
std::string coord_str;
if (std::getline(iss, coord_str, 'x')) {
@ -821,12 +821,7 @@ public:
bool deserialize(const std::string &str, bool append = false) override
{
UNUSED(append);
const t_config_enum_values &enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
auto it = enum_keys_map.find(str);
if (it == enum_keys_map.end())
return false;
this->value = static_cast<T>(it->second);
return true;
return from_string(str, this->value);
}
static bool has(T value)
@ -838,7 +833,7 @@ public:
}
// Map from an enum name to an enum integer value.
static t_config_enum_names& get_enum_names()
static const t_config_enum_names& get_enum_names()
{
static t_config_enum_names names;
if (names.empty()) {
@ -855,7 +850,17 @@ public:
return names;
}
// Map from an enum name to an enum integer value.
static t_config_enum_values& get_enum_values();
static const t_config_enum_values& get_enum_values();
static bool from_string(const std::string &str, T &value)
{
const t_config_enum_values &enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
auto it = enum_keys_map.find(str);
if (it == enum_keys_map.end())
return false;
value = static_cast<T>(it->second);
return true;
}
};
// Generic enum configuration value.
@ -900,7 +905,7 @@ public:
// What type? bool, int, string etc.
ConfigOptionType type = coNone;
// Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor.
ConfigOption *default_value = nullptr;
const ConfigOption *default_value = nullptr;
// Usually empty.
// Special values - "i_enum_open", "f_enum_open" to provide combo box for int or float selection,
@ -958,7 +963,7 @@ public:
std::vector<std::string> enum_labels;
// For enums (when type == coEnum). Maps enum_values to enums.
// Initialized by ConfigOptionEnum<xxx>::get_enum_values()
t_config_enum_values *enum_keys_map = nullptr;
const t_config_enum_values *enum_keys_map = nullptr;
bool has_enum_value(const std::string &value) const {
for (const std::string &v : enum_values)

View file

@ -149,7 +149,7 @@ public:
// Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
double min_mm3_per_mm() const { return this->mm3_per_mm; }
Polyline as_polyline() const { return this->polyline; }
virtual double total_volume() const { return mm3_per_mm * unscale(length()); }
virtual double total_volume() const { return mm3_per_mm * unscale<double>(length()); }
private:
void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const;

View file

@ -54,7 +54,7 @@ static std::vector<coordf_t> perpendPoints(const coordf_t offset, const size_t b
// components that are outside these limits are set to the limits.
static inline void trim(Pointfs &pts, coordf_t minX, coordf_t minY, coordf_t maxX, coordf_t maxY)
{
for (Pointf &pt : pts) {
for (Vec2d &pt : pts) {
pt(0) = clamp(minX, maxX, pt(0));
pt(1) = clamp(minY, maxY, pt(1));
}
@ -66,7 +66,7 @@ static inline Pointfs zip(const std::vector<coordf_t> &x, const std::vector<coor
Pointfs out;
out.reserve(x.size());
for (size_t i = 0; i < x.size(); ++ i)
out.push_back(Pointf(x[i], y[i]));
out.push_back(Vec2d(x[i], y[i]));
return out;
}

View file

@ -21,7 +21,7 @@ void FillConcentric::_fill_surface_single(
if (params.density > 0.9999f && !params.dont_adjust) {
distance = this->_adjust_solid_spacing(bounding_box.size()(0), distance);
this->spacing = unscale(distance);
this->spacing = unscale<double>(distance);
}
Polygons loops = (Polygons)expolygon;

View file

@ -30,15 +30,15 @@ static inline double f(double x, double z_sin, double z_cos, bool vertical, bool
}
static inline Polyline make_wave(
const std::vector<Pointf>& one_period, double width, double height, double offset, double scaleFactor,
const std::vector<Vec2d>& one_period, double width, double height, double offset, double scaleFactor,
double z_cos, double z_sin, bool vertical)
{
std::vector<Pointf> points = one_period;
std::vector<Vec2d> points = one_period;
double period = points.back()(0);
points.pop_back();
int n = points.size();
do {
points.emplace_back(Pointf(points[points.size()-n](0) + period, points[points.size()-n](1)));
points.emplace_back(Vec2d(points[points.size()-n](0) + period, points[points.size()-n](1)));
} while (points.back()(0) < width);
points.back()(0) = width;
@ -55,14 +55,14 @@ static inline Polyline make_wave(
return polyline;
}
static std::vector<Pointf> make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip)
static std::vector<Vec2d> make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip)
{
std::vector<Pointf> points;
std::vector<Vec2d> points;
double dx = M_PI_4; // very coarse spacing to begin with
double limit = std::min(2*M_PI, width);
for (double x = 0.; x < limit + EPSILON; x += dx) { // so the last point is there too
x = std::min(x, limit);
points.emplace_back(Pointf(x,f(x, z_sin,z_cos, vertical, flip)));
points.emplace_back(Vec2d(x,f(x, z_sin,z_cos, vertical, flip)));
}
// now we will check all internal points and in case some are too far from the line connecting its neighbours,
@ -71,17 +71,19 @@ static std::vector<Pointf> make_one_period(double width, double scaleFactor, dou
for (unsigned int i=1;i<points.size()-1;++i) {
auto& lp = points[i-1]; // left point
auto& tp = points[i]; // this point
Vec2d lrv = tp - lp;
auto& rp = points[i+1]; // right point
// calculate distance of the point to the line:
double dist_mm = unscale(scaleFactor * std::abs( (rp(1) - lp(1))*tp(0) + (lp(0) - rp(0))*tp(1) + (rp(0)*lp(1) - rp(1)*lp(0)) ) / std::hypot((rp(1) - lp(1)),(lp(0) - rp(0))));
double dist_mm = unscale<double>(scaleFactor) * std::abs(cross2(rp, lp) - cross2(rp - lp, tp)) / lrv.norm();
if (dist_mm > tolerance) { // if the difference from straight line is more than this
double x = 0.5f * (points[i-1](0) + points[i](0));
points.emplace_back(Pointf(x, f(x, z_sin, z_cos, vertical, flip)));
points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip)));
x = 0.5f * (points[i+1](0) + points[i](0));
points.emplace_back(Pointf(x, f(x, z_sin, z_cos, vertical, flip)));
std::sort(points.begin(), points.end()); // we added the points to the end, but need them all in order
--i; // decrement i so we also check the first newly added point
points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip)));
// we added the points to the end, but need them all in order
std::sort(points.begin(), points.end(), [](const Vec2d &lhs, const Vec2d &rhs){ return lhs < rhs; });
// decrement i so we also check the first newly added point
--i;
}
}
return points;
@ -107,7 +109,7 @@ static Polylines make_gyroid_waves(double gridZ, double density_adjusted, double
std::swap(width,height);
}
std::vector<Pointf> one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // creates one period of the waves, so it doesn't have to be recalculated all the time
std::vector<Vec2d> one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // creates one period of the waves, so it doesn't have to be recalculated all the time
Polylines result;
for (double y0 = lower_bound; y0 < upper_bound+EPSILON; y0 += 2*M_PI) // creates odd polylines

View file

@ -86,12 +86,12 @@ Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t m
coordf_t r = 1;
Pointfs out;
//FIXME Vojtech: If used as a solid infill, there is a gap left at the center.
out.push_back(Pointf(0, 0));
out.push_back(Pointf(1, 0));
out.push_back(Vec2d(0, 0));
out.push_back(Vec2d(1, 0));
while (r < rmax) {
theta += 1. / r;
r = a + b * theta;
out.push_back(Pointf(r * cos(theta), r * sin(theta)));
out.push_back(Vec2d(r * cos(theta), r * sin(theta)));
}
return out;
}
@ -162,7 +162,7 @@ Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x,
line.reserve(sz2);
for (size_t i = 0; i < sz2; ++ i) {
Point p = hilbert_n_to_xy(i);
line.push_back(Pointf(p(0) + min_x, p(1) + min_y));
line.push_back(Vec2d(p(0) + min_x, p(1) + min_y));
}
return line;
}
@ -175,27 +175,27 @@ Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_
coordf_t r = 0;
coordf_t r_inc = sqrt(2.);
Pointfs out;
out.push_back(Pointf(0, 0));
out.push_back(Vec2d(0, 0));
while (r < rmax) {
r += r_inc;
coordf_t rx = r / sqrt(2.);
coordf_t r2 = r + rx;
out.push_back(Pointf( r, 0.));
out.push_back(Pointf( r2, rx));
out.push_back(Pointf( rx, rx));
out.push_back(Pointf( rx, r2));
out.push_back(Pointf(0., r));
out.push_back(Pointf(-rx, r2));
out.push_back(Pointf(-rx, rx));
out.push_back(Pointf(-r2, rx));
out.push_back(Pointf(-r, 0.));
out.push_back(Pointf(-r2, -rx));
out.push_back(Pointf(-rx, -rx));
out.push_back(Pointf(-rx, -r2));
out.push_back(Pointf(0., -r));
out.push_back(Pointf( rx, -r2));
out.push_back(Pointf( rx, -rx));
out.push_back(Pointf( r2+r_inc, -rx));
out.push_back(Vec2d( r, 0.));
out.push_back(Vec2d( r2, rx));
out.push_back(Vec2d( rx, rx));
out.push_back(Vec2d( rx, r2));
out.push_back(Vec2d(0., r));
out.push_back(Vec2d(-rx, r2));
out.push_back(Vec2d(-rx, rx));
out.push_back(Vec2d(-r2, rx));
out.push_back(Vec2d(-r, 0.));
out.push_back(Vec2d(-r2, -rx));
out.push_back(Vec2d(-rx, -rx));
out.push_back(Vec2d(-rx, -r2));
out.push_back(Vec2d(0., -r));
out.push_back(Vec2d( rx, -r2));
out.push_back(Vec2d( rx, -rx));
out.push_back(Vec2d( r2+r_inc, -rx));
}
return out;
}

View file

@ -27,7 +27,7 @@ void FillRectilinear::_fill_surface_single(
// define flow spacing according to requested density
if (params.density > 0.9999f && !params.dont_adjust) {
this->_line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), this->_line_spacing);
this->spacing = unscale(this->_line_spacing);
this->spacing = unscale<double>(this->_line_spacing);
} else {
// extend bounding box so that our pattern will be aligned with other layers
// Transform the reference point to the rotated coordinate system.

View file

@ -792,7 +792,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
// define flow spacing according to requested density
if (params.full_infill() && !params.dont_adjust) {
line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing);
this->spacing = unscale(line_spacing);
this->spacing = unscale<double>(line_spacing);
} else {
// extend bounding box so that our pattern will be aligned with other layers
// Transform the reference point to the rotated coordinate system.

View file

@ -217,11 +217,11 @@ Point SegmentIntersection::pos() const
const Point &seg_start = poly.points[(this->iSegment == 0) ? poly.points.size() - 1 : this->iSegment - 1];
const Point &seg_end = poly.points[this->iSegment];
// Point, vector of the segment.
const Pointf p1(seg_start.cast<coordf_t>());
const Pointf v1((seg_end - seg_start).cast<coordf_t>());
const Vec2d p1(seg_start.cast<coordf_t>());
const Vec2d v1((seg_end - seg_start).cast<coordf_t>());
// Point, vector of this hatching line.
const Pointf p2(line->pos.cast<coordf_t>());
const Pointf v2(line->dir.cast<coordf_t>());
const Vec2d p2(line->pos.cast<coordf_t>());
const Vec2d v2(line->dir.cast<coordf_t>());
// Intersect the two rays.
double denom = v1(0) * v2(1) - v2(0) * v1(1);
Point out;
@ -391,7 +391,7 @@ static bool prepare_infill_hatching_segments(
// Full infill, adjust the line spacing to fit an integer number of lines.
out.line_spacing = Fill::_adjust_solid_spacing(bounding_box.size()(0), line_spacing);
// Report back the adjusted line spacing.
fill_dir_params.spacing = float(unscale(line_spacing));
fill_dir_params.spacing = unscale<double>(line_spacing);
} else {
// Extend bounding box so that our pattern will be aligned with the other layers.
// Transform the reference point to the rotated coordinate system.

View file

@ -1485,12 +1485,13 @@ namespace Slic3r {
stl_facet& facet = stl.facet_start[i];
for (unsigned int v = 0; v < 3; ++v)
{
::memcpy((void*)&facet.vertex[v].x, (const void*)&geometry.vertices[geometry.triangles[src_start_id + ii + v] * 3], 3 * sizeof(float));
::memcpy(facet.vertex[v].data(), (const void*)&geometry.vertices[geometry.triangles[src_start_id + ii + v] * 3], 3 * sizeof(float));
}
}
stl_get_size(&stl);
volume->mesh.repair();
volume->calculate_convex_hull();
// apply volume's name and config data
for (const Metadata& metadata : volume_data.metadata)
@ -1844,9 +1845,9 @@ namespace Slic3r {
for (int i = 0; i < stl.stats.shared_vertices; ++i)
{
stream << " <" << VERTEX_TAG << " ";
stream << "x=\"" << stl.v_shared[i].x << "\" ";
stream << "y=\"" << stl.v_shared[i].y << "\" ";
stream << "z=\"" << stl.v_shared[i].z << "\" />\n";
stream << "x=\"" << stl.v_shared[i](0) << "\" ";
stream << "y=\"" << stl.v_shared[i](1) << "\" ";
stream << "z=\"" << stl.v_shared[i](2) << "\" />\n";
}
}

View file

@ -402,10 +402,11 @@ void AMFParserContext::endElement(const char * /* name */)
for (size_t i = 0; i < m_volume_facets.size();) {
stl_facet &facet = stl.facet_start[i/3];
for (unsigned int v = 0; v < 3; ++ v)
memcpy(&facet.vertex[v].x, &m_object_vertices[m_volume_facets[i ++] * 3], 3 * sizeof(float));
memcpy(facet.vertex[v].data(), &m_object_vertices[m_volume_facets[i ++] * 3], 3 * sizeof(float));
}
stl_get_size(&stl);
m_volume->mesh.repair();
m_volume->calculate_convex_hull();
m_volume_facets.clear();
m_volume = nullptr;
break;
@ -760,9 +761,9 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c
for (size_t i = 0; i < stl.stats.shared_vertices; ++ i) {
stream << " <vertex>\n";
stream << " <coordinates>\n";
stream << " <x>" << stl.v_shared[i].x << "</x>\n";
stream << " <y>" << stl.v_shared[i].y << "</y>\n";
stream << " <z>" << stl.v_shared[i].z << "</z>\n";
stream << " <x>" << stl.v_shared[i](0) << "</x>\n";
stream << " <y>" << stl.v_shared[i](1) << "</y>\n";
stream << " <z>" << stl.v_shared[i](2) << "</z>\n";
stream << " </coordinates>\n";
stream << " </vertex>\n";
}

View file

@ -57,14 +57,14 @@ bool load_obj(const char *path, Model *model, const char *object_name_in)
continue;
stl_facet &facet = stl.facet_start[i_face ++];
size_t num_normals = 0;
stl_normal normal = { 0.f };
stl_normal normal(stl_normal::Zero());
for (unsigned int v = 0; v < 3; ++ v) {
const ObjParser::ObjVertex &vertex = data.vertices[i++];
memcpy(&facet.vertex[v].x, &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float));
memcpy(facet.vertex[v].data(), &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float));
if (vertex.normalIdx != -1) {
normal.x += data.normals[vertex.normalIdx*3];
normal.y += data.normals[vertex.normalIdx*3+1];
normal.z += data.normals[vertex.normalIdx*3+2];
normal(0) += data.normals[vertex.normalIdx*3];
normal(1) += data.normals[vertex.normalIdx*3+1];
normal(2) += data.normals[vertex.normalIdx*3+2];
++ num_normals;
}
}
@ -74,33 +74,27 @@ bool load_obj(const char *path, Model *model, const char *object_name_in)
facet2.vertex[0] = facet.vertex[0];
facet2.vertex[1] = facet.vertex[2];
const ObjParser::ObjVertex &vertex = data.vertices[i++];
memcpy(&facet2.vertex[2].x, &data.coordinates[vertex.coordIdx * 4], 3 * sizeof(float));
memcpy(facet2.vertex[2].data(), &data.coordinates[vertex.coordIdx * 4], 3 * sizeof(float));
if (vertex.normalIdx != -1) {
normal.x += data.normals[vertex.normalIdx*3];
normal.y += data.normals[vertex.normalIdx*3+1];
normal.z += data.normals[vertex.normalIdx*3+2];
normal(0) += data.normals[vertex.normalIdx*3];
normal(1) += data.normals[vertex.normalIdx*3+1];
normal(2) += data.normals[vertex.normalIdx*3+2];
++ num_normals;
}
if (num_normals == 4) {
// Normalize an average normal of a quad.
float len = sqrt(facet.normal.x*facet.normal.x + facet.normal.y*facet.normal.y + facet.normal.z*facet.normal.z);
float len = facet.normal.norm();
if (len > EPSILON) {
normal.x /= len;
normal.y /= len;
normal.z /= len;
normal /= len;
facet.normal = normal;
facet2.normal = normal;
}
}
} else if (num_normals == 3) {
// Normalize an average normal of a triangle.
float len = sqrt(facet.normal.x*facet.normal.x + facet.normal.y*facet.normal.y + facet.normal.z*facet.normal.z);
if (len > EPSILON) {
normal.x /= len;
normal.y /= len;
normal.z /= len;
facet.normal = normal;
}
float len = facet.normal.norm();
if (len > EPSILON)
facet.normal = normal / len;
}
}
stl_get_size(&stl);

View file

@ -166,7 +166,7 @@ bool load_prus(const char *path, Model *model)
float trafo[3][4] = { 0 };
double instance_rotation = 0.;
double instance_scaling_factor = 1.f;
Pointf instance_offset(0., 0.);
Vec2d instance_offset(0., 0.);
bool trafo_set = false;
unsigned int group_id = (unsigned int)-1;
unsigned int extruder_id = (unsigned int)-1;
@ -260,8 +260,8 @@ bool load_prus(const char *path, Model *model)
mesh.repair();
// Transform the model.
stl_transform(&stl, &trafo[0][0]);
if (std::abs(stl.stats.min.z) < EPSILON)
stl.stats.min.z = 0.;
if (std::abs(stl.stats.min(2)) < EPSILON)
stl.stats.min(2) = 0.;
// Add a mesh to a model.
if (mesh.facets_count() > 0)
mesh_valid = true;
@ -309,11 +309,11 @@ bool load_prus(const char *path, Model *model)
assert(res_normal == 3);
int res_outer_loop = line_reader.next_line_scanf(" outer loop");
assert(res_outer_loop == 0);
int res_vertex1 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z);
int res_vertex1 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2));
assert(res_vertex1 == 3);
int res_vertex2 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z);
int res_vertex2 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2));
assert(res_vertex2 == 3);
int res_vertex3 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z);
int res_vertex3 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2));
assert(res_vertex3 == 3);
int res_endloop = line_reader.next_line_scanf(" endloop");
assert(res_endloop == 0);
@ -324,9 +324,9 @@ bool load_prus(const char *path, Model *model)
break;
}
// The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition.
if (sscanf(normal_buf[0], "%f", &facet.normal.x) != 1 ||
sscanf(normal_buf[1], "%f", &facet.normal.y) != 1 ||
sscanf(normal_buf[2], "%f", &facet.normal.z) != 1) {
if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 ||
sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 ||
sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) {
// Normal was mangled. Maybe denormals or "not a number" were stored?
// Just reset the normal and silently ignore it.
memset(&facet.normal, 0, sizeof(facet.normal));

View file

@ -64,7 +64,7 @@ std::string OozePrevention::pre_toolchange(GCode &gcodegen)
// move to the nearest standby point
if (!this->standby_points.empty()) {
// get current position in print coordinates
Pointf3 writer_pos = gcodegen.writer().get_position();
Vec3d writer_pos = gcodegen.writer().get_position();
Point pos = Point::new_scale(writer_pos(0), writer_pos(1));
// find standby point
@ -74,7 +74,7 @@ std::string OozePrevention::pre_toolchange(GCode &gcodegen)
/* We don't call gcodegen.travel_to() because we don't need retraction (it was already
triggered by the caller) nor avoid_crossing_perimeters and also because the coordinates
of the destination point must not be transformed by origin nor current extruder offset. */
gcode += gcodegen.writer().travel_to_xy(Pointf::new_unscale(standby_point),
gcode += gcodegen.writer().travel_to_xy(unscale(standby_point),
"move to standby position");
}
@ -207,7 +207,7 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
check_add_eol(gcode);
}
// A phony move to the end position at the wipe tower.
gcodegen.writer().travel_to_xy(Pointf(end_pos.x, end_pos.y));
gcodegen.writer().travel_to_xy(Vec2d(end_pos.x, end_pos.y));
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, end_pos));
// Prepare a future wipe.
@ -293,7 +293,7 @@ std::string WipeTowerIntegration::prime(GCode &gcodegen)
gcodegen.writer().toolchange(current_extruder_id);
gcodegen.placeholder_parser().set("current_extruder", current_extruder_id);
// A phony move to the end position at the wipe tower.
gcodegen.writer().travel_to_xy(Pointf(m_priming.end_pos.x, m_priming.end_pos.y));
gcodegen.writer().travel_to_xy(Vec2d(m_priming.end_pos.x, m_priming.end_pos.y));
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos));
// Prepare a future wipe.
gcodegen.m_wipe.path.points.clear();
@ -783,7 +783,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
Polygon outer_skirt = Slic3r::Geometry::convex_hull(skirt_points);
Polygons skirts;
for (unsigned int extruder_id : print.extruders()) {
const Pointf &extruder_offset = print.config.extruder_offset.get_at(extruder_id);
const Vec2d &extruder_offset = print.config.extruder_offset.get_at(extruder_id);
Polygon s(outer_skirt);
s.translate(Point::new_scale(- extruder_offset(0), - extruder_offset(1)));
skirts.emplace_back(std::move(s));
@ -831,7 +831,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
final_extruder_id = tool_ordering.last_extruder();
assert(final_extruder_id != (unsigned int)-1);
}
this->set_origin(unscale(copy(0)), unscale(copy(1)));
this->set_origin(unscale(copy));
if (finished_objects > 0) {
// Move to the origin position for the copy we're going to print.
// This happens before Z goes down to layer 0 again, so that no collision happens hopefully.
@ -1547,7 +1547,7 @@ void GCode::process_layer(
if (m_last_obj_copy != this_object_copy)
m_avoid_crossing_perimeters.use_external_mp_once = true;
m_last_obj_copy = this_object_copy;
this->set_origin(unscale(copy(0)), unscale(copy(1)));
this->set_origin(unscale(copy));
if (object_by_extruder.support != nullptr && !print_wipe_extrusions) {
m_layer = layers[layer_id].support_layer;
gcode += this->extrude_support(
@ -1632,7 +1632,7 @@ void GCode::set_extruders(const std::vector<unsigned int> &extruder_ids)
}
}
void GCode::set_origin(const Pointf &pointf)
void GCode::set_origin(const Vec2d &pointf)
{
// if origin increases (goes towards right), last_pos decreases because it goes towards left
const Point translate(
@ -2618,24 +2618,21 @@ std::string GCode::set_extruder(unsigned int extruder_id)
}
// convert a model-space scaled point into G-code coordinates
Pointf GCode::point_to_gcode(const Point &point) const
Vec2d GCode::point_to_gcode(const Point &point) const
{
Pointf extruder_offset = EXTRUDER_CONFIG(extruder_offset);
return Pointf(
unscale(point(0)) + m_origin(0) - extruder_offset(0),
unscale(point(1)) + m_origin(1) - extruder_offset(1));
Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
return unscale(point) + m_origin - extruder_offset;
}
// convert a model-space scaled point into G-code coordinates
Point GCode::gcode_to_point(const Pointf &point) const
Point GCode::gcode_to_point(const Vec2d &point) const
{
Pointf extruder_offset = EXTRUDER_CONFIG(extruder_offset);
Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
return Point(
scale_(point(0) - m_origin(0) + extruder_offset(0)),
scale_(point(1) - m_origin(1) + extruder_offset(1)));
}
// Goes through by_region std::vector and returns reference to a subvector of entities, that are to be printed
// during infill/perimeter wiping, or normally (depends on wiping_entities parameter)
// Returns a reference to member to avoid copying.

View file

@ -125,6 +125,7 @@ private:
class GCode {
public:
GCode() :
m_origin(Vec2d::Zero()),
m_enable_loop_clipping(true),
m_enable_cooling_markers(false),
m_enable_extrusion_role_markers(false),
@ -152,12 +153,12 @@ public:
void do_export(Print *print, const char *path, GCodePreviewData *preview_data = nullptr);
// Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
const Pointf& origin() const { return m_origin; }
void set_origin(const Pointf &pointf);
void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Pointf(x, y)); }
const Vec2d& origin() const { return m_origin; }
void set_origin(const Vec2d &pointf);
void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); }
const Point& last_pos() const { return m_last_pos; }
Pointf point_to_gcode(const Point &point) const;
Point gcode_to_point(const Pointf &point) const;
Vec2d point_to_gcode(const Point &point) const;
Point gcode_to_point(const Vec2d &point) const;
const FullPrintConfig &config() const { return m_config; }
const Layer* layer() const { return m_layer; }
GCodeWriter& writer() { return m_writer; }
@ -258,7 +259,7 @@ protected:
/* Origin of print coordinates expressed in unscaled G-code coordinates.
This affects the input arguments supplied to the extrude*() and travel_to()
methods. */
Pointf m_origin;
Vec2d m_origin;
FullPrintConfig m_config;
GCodeWriter m_writer;
PlaceholderParser m_placeholder_parser;

View file

@ -14,7 +14,7 @@ static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
static const float INCHES_TO_MM = 25.4f;
static const float DEFAULT_FEEDRATE = 0.0f;
static const unsigned int DEFAULT_EXTRUDER_ID = 0;
static const Slic3r::Pointf3 DEFAULT_START_POSITION = Slic3r::Pointf3(0.0f, 0.0f, 0.0f);
static const Slic3r::Vec3d DEFAULT_START_POSITION = Slic3r::Vec3d(0.0f, 0.0f, 0.0f);
static const float DEFAULT_START_EXTRUSION = 0.0f;
namespace Slic3r {
@ -71,7 +71,7 @@ bool GCodeAnalyzer::Metadata::operator != (const GCodeAnalyzer::Metadata& other)
return false;
}
GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder)
GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder)
: type(type)
, data(extrusion_role, extruder_id, mm3_per_mm, width, height, feedrate)
, start_position(start_position)
@ -80,7 +80,7 @@ GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusi
{
}
GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, const GCodeAnalyzer::Metadata& data, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder)
GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, const GCodeAnalyzer::Metadata& data, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder)
: type(type)
, data(data)
, start_position(start_position)
@ -587,12 +587,12 @@ void GCodeAnalyzer::_reset_axes_position()
::memset((void*)m_state.position, 0, Num_Axis * sizeof(float));
}
void GCodeAnalyzer::_set_start_position(const Pointf3& position)
void GCodeAnalyzer::_set_start_position(const Vec3d& position)
{
m_state.start_position = position;
}
const Pointf3& GCodeAnalyzer::_get_start_position() const
const Vec3d& GCodeAnalyzer::_get_start_position() const
{
return m_state.start_position;
}
@ -612,9 +612,9 @@ float GCodeAnalyzer::_get_delta_extrusion() const
return _get_axis_position(E) - m_state.start_extrusion;
}
Pointf3 GCodeAnalyzer::_get_end_position() const
Vec3d GCodeAnalyzer::_get_end_position() const
{
return Pointf3(m_state.position[X], m_state.position[Y], m_state.position[Z]);
return Vec3d(m_state.position[X], m_state.position[Y], m_state.position[Z]);
}
void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type)
@ -673,7 +673,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
Metadata data;
float z = FLT_MAX;
Polyline polyline;
Pointf3 position(FLT_MAX, FLT_MAX, FLT_MAX);
Vec3d position(FLT_MAX, FLT_MAX, FLT_MAX);
float volumetric_rate = FLT_MAX;
GCodePreviewData::Range height_range;
GCodePreviewData::Range width_range;
@ -742,7 +742,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
return;
Polyline3 polyline;
Pointf3 position(FLT_MAX, FLT_MAX, FLT_MAX);
Vec3d position(FLT_MAX, FLT_MAX, FLT_MAX);
GCodePreviewData::Travel::EType type = GCodePreviewData::Travel::Num_Types;
GCodePreviewData::Travel::Polyline::EDirection direction = GCodePreviewData::Travel::Polyline::Num_Directions;
float feedrate = FLT_MAX;
@ -768,12 +768,12 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
polyline = Polyline3();
// add both vertices of the move
polyline.append(Point3(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z())));
polyline.append(Point3(scale_(move.end_position.x()), scale_(move.end_position.y()), scale_(move.end_position.z())));
polyline.append(Vec3crd(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z())));
polyline.append(Vec3crd(scale_(move.end_position.x()), scale_(move.end_position.y()), scale_(move.end_position.z())));
}
else
// append end vertex of the move to current polyline
polyline.append(Point3(scale_(move.end_position.x()), scale_(move.end_position.y()), scale_(move.end_position.z())));
polyline.append(Vec3crd(scale_(move.end_position.x()), scale_(move.end_position.y()), scale_(move.end_position.z())));
// update current values
position = move.end_position;
@ -804,7 +804,7 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da
for (const GCodeMove& move : retraction_moves->second)
{
// store position
Point3 position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
preview_data.retraction.positions.emplace_back(position, move.data.width, move.data.height);
}
}
@ -818,7 +818,7 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_
for (const GCodeMove& move : unretraction_moves->second)
{
// store position
Point3 position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
preview_data.unretraction.positions.emplace_back(position, move.data.width, move.data.height);
}
}

View file

@ -75,12 +75,12 @@ public:
EType type;
Metadata data;
Pointf3 start_position;
Pointf3 end_position;
Vec3d start_position;
Vec3d end_position;
float delta_extruder;
GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder);
GCodeMove(EType type, const Metadata& data, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder);
GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder);
GCodeMove(EType type, const Metadata& data, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder);
};
typedef std::vector<GCodeMove> GCodeMovesList;
@ -93,7 +93,7 @@ private:
EPositioningType global_positioning_type;
EPositioningType e_local_positioning_type;
Metadata data;
Pointf3 start_position;
Vec3d start_position = Vec3d::Zero();
float start_extrusion;
float position[Num_Axis];
};
@ -206,15 +206,15 @@ private:
// Sets axes position to zero
void _reset_axes_position();
void _set_start_position(const Pointf3& position);
const Pointf3& _get_start_position() const;
void _set_start_position(const Vec3d& position);
const Vec3d& _get_start_position() const;
void _set_start_extrusion(float extrusion);
float _get_start_extrusion() const;
float _get_delta_extrusion() const;
// Returns current xyz position (from m_state.position[])
Pointf3 _get_end_position() const;
Vec3d _get_end_position() const;
// Adds a new move with the given data
void _store_move(GCodeMove::EType type);

View file

@ -23,7 +23,7 @@ CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_gcodegen(gcodegen), m_current_
void CoolingBuffer::reset()
{
m_current_pos.assign(5, 0.f);
Pointf3 pos = m_gcodegen.writer().get_position();
Vec3d pos = m_gcodegen.writer().get_position();
m_current_pos[0] = float(pos(0));
m_current_pos[1] = float(pos(1));
m_current_pos[2] = float(pos(2));

View file

@ -226,7 +226,7 @@ void GCodePreviewData::Travel::set_default()
const GCodePreviewData::Color GCodePreviewData::Retraction::Default_Color = GCodePreviewData::Color(1.0f, 1.0f, 1.0f, 1.0f);
GCodePreviewData::Retraction::Position::Position(const Point3& position, float width, float height)
GCodePreviewData::Retraction::Position::Position(const Vec3crd& position, float width, float height)
: position(position)
, width(width)
, height(height)

View file

@ -151,11 +151,11 @@ public:
struct Position
{
Point3 position;
Vec3crd position;
float width;
float height;
Position(const Point3& position, float width, float height);
Position(const Vec3crd& position, float width, float height);
};
typedef std::vector<Position> PositionsList;

View file

@ -32,8 +32,8 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionPath &extrusio
BoundingBox bbox = extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = Pointf::new_unscale(bbox.min);
bboxf.max = Pointf::new_unscale(bbox.max);
bboxf.min = unscale(bbox.min);
bboxf.max = unscale(bbox.max);
bboxf.defined = true;
}
return bboxf;
@ -46,8 +46,8 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionLoop &extrusio
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width)));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = Pointf::new_unscale(bbox.min);
bboxf.max = Pointf::new_unscale(bbox.max);
bboxf.min = unscale(bbox.min);
bboxf.max = unscale(bbox.max);
bboxf.defined = true;
}
return bboxf;
@ -60,8 +60,8 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionMultiPath &ext
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width)));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = Pointf::new_unscale(bbox.min);
bboxf.max = Pointf::new_unscale(bbox.max);
bboxf.min = unscale(bbox.min);
bboxf.max = unscale(bbox.max);
bboxf.defined = true;
}
return bboxf;
@ -123,7 +123,7 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object
bbox_this.merge(extrusionentity_extents(extrusion_entity));
for (const Point &offset : print_object._shifted_copies) {
BoundingBoxf bbox_translated(bbox_this);
bbox_translated.translate(Pointf::new_unscale(offset));
bbox_translated.translate(unscale(offset));
bbox.merge(bbox_translated);
}
}
@ -136,8 +136,9 @@ BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_
{
// Wipe tower extrusions are saved as if the tower was at the origin with no rotation
// We need to get position and angle of the wipe tower to transform them to actual position.
Pointf wipe_tower_pos(print.config.wipe_tower_x.value, print.config.wipe_tower_y.value);
float wipe_tower_angle = print.config.wipe_tower_rotation_angle.value;
Transform2d trafo =
Eigen::Translation2d(print.config.wipe_tower_x.value, print.config.wipe_tower_y.value) *
Eigen::Rotation2Dd(print.config.wipe_tower_rotation_angle.value);
BoundingBoxf bbox;
for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.m_wipe_tower_tool_changes) {
@ -147,19 +148,11 @@ BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
const WipeTower::Extrusion &e = tcr.extrusions[i];
if (e.width > 0) {
Pointf p1((&e - 1)->pos.x, (&e - 1)->pos.y);
Pointf p2(e.pos.x, e.pos.y);
p1.rotate(wipe_tower_angle);
p1 += wipe_tower_pos;
p2.rotate(wipe_tower_angle);
p2 += wipe_tower_pos;
bbox.merge(p1);
coordf_t radius = 0.5 * e.width;
bbox.min(0) = std::min(bbox.min(0), std::min(p1(0), p2(0)) - radius);
bbox.min(1) = std::min(bbox.min(1), std::min(p1(1), p2(1)) - radius);
bbox.max(0) = std::max(bbox.max(0), std::max(p1(0), p2(0)) + radius);
bbox.max(1) = std::max(bbox.max(1), std::max(p1(1), p2(1)) + radius);
Vec2d delta = 0.5 * Vec2d(e.width, e.width);
Vec2d p1 = trafo * Vec2d((&e - 1)->pos.x, (&e - 1)->pos.y);
Vec2d p2 = trafo * Vec2d(e.pos.x, e.pos.y);
bbox.merge(p1.cwiseMin(p2) - delta);
bbox.merge(p1.cwiseMax(p2) + delta);
}
}
}
@ -176,8 +169,8 @@ BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print)
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
const WipeTower::Extrusion &e = tcr.extrusions[i];
if (e.width > 0) {
Pointf p1((&e - 1)->pos.x, (&e - 1)->pos.y);
Pointf p2(e.pos.x, e.pos.y);
Vec2d p1((&e - 1)->pos.x, (&e - 1)->pos.y);
Vec2d p2(e.pos.x, e.pos.y);
bbox.merge(p1);
coordf_t radius = 0.5 * e.width;
bbox.min(0) = std::min(bbox.min(0), std::min(p1(0), p2(0)) - radius);

View file

@ -276,7 +276,7 @@ std::string GCodeWriter::set_speed(double F, const std::string &comment, const s
return gcode.str();
}
std::string GCodeWriter::travel_to_xy(const Pointf &point, const std::string &comment)
std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment)
{
m_pos(0) = point(0);
m_pos(1) = point(1);
@ -290,7 +290,7 @@ std::string GCodeWriter::travel_to_xy(const Pointf &point, const std::string &co
return gcode.str();
}
std::string GCodeWriter::travel_to_xyz(const Pointf3 &point, const std::string &comment)
std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment)
{
/* If target Z is lower than current Z but higher than nominal Z we
don't perform the Z move but we only move in the XY plane and
@ -299,7 +299,7 @@ std::string GCodeWriter::travel_to_xyz(const Pointf3 &point, const std::string &
if (!this->will_move_z(point(2))) {
double nominal_z = m_pos(2) - m_lifted;
m_lifted = m_lifted - (point(2) - nominal_z);
return this->travel_to_xy(point.xy());
return this->travel_to_xy(to_2d(point));
}
/* In all the other cases, we perform an actual XYZ move and cancel
@ -358,7 +358,7 @@ bool GCodeWriter::will_move_z(double z) const
return true;
}
std::string GCodeWriter::extrude_to_xy(const Pointf &point, double dE, const std::string &comment)
std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std::string &comment)
{
m_pos(0) = point(0);
m_pos(1) = point(1);
@ -373,7 +373,7 @@ std::string GCodeWriter::extrude_to_xy(const Pointf &point, double dE, const std
return gcode.str();
}
std::string GCodeWriter::extrude_to_xyz(const Pointf3 &point, double dE, const std::string &comment)
std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment)
{
m_pos = point;
m_lifted = 0;

View file

@ -55,18 +55,18 @@ public:
std::string toolchange_prefix() const;
std::string toolchange(unsigned int extruder_id);
std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string()) const;
std::string travel_to_xy(const Pointf &point, const std::string &comment = std::string());
std::string travel_to_xyz(const Pointf3 &point, const std::string &comment = std::string());
std::string travel_to_xy(const Vec2d &point, const std::string &comment = std::string());
std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string());
std::string travel_to_z(double z, const std::string &comment = std::string());
bool will_move_z(double z) const;
std::string extrude_to_xy(const Pointf &point, double dE, const std::string &comment = std::string());
std::string extrude_to_xyz(const Pointf3 &point, double dE, const std::string &comment = std::string());
std::string extrude_to_xy(const Vec2d &point, double dE, const std::string &comment = std::string());
std::string extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment = std::string());
std::string retract(bool before_wipe = false);
std::string retract_for_toolchange(bool before_wipe = false);
std::string unretract();
std::string lift();
std::string unlift();
Pointf3 get_position() const { return m_pos; }
Vec3d get_position() const { return m_pos; }
private:
std::vector<Extruder> m_extruders;
@ -81,7 +81,7 @@ private:
unsigned int m_last_bed_temperature;
bool m_last_bed_temperature_reached;
double m_lifted;
Pointf3 m_pos;
Vec3d m_pos = Vec3d::Zero();
std::string _travel_to_z(double z, const std::string &comment);
std::string _retract(double length, double restart_extra, const std::string &comment);

View file

@ -345,7 +345,7 @@ linint(double value, double oldmin, double oldmax, double newmin, double newmax)
// If the points have the same weight, sort them lexicographically by their positions.
struct ArrangeItem {
ArrangeItem() {}
Pointf pos;
Vec2d pos;
coordf_t weight;
bool operator<(const ArrangeItem &other) const {
return weight < other.weight ||
@ -353,17 +353,17 @@ struct ArrangeItem {
}
};
Pointfs arrange(size_t num_parts, const Pointf &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box)
Pointfs arrange(size_t num_parts, const Vec2d &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box)
{
// Use actual part size (the largest) plus separation distance (half on each side) in spacing algorithm.
const Pointf cell_size(part_size(0) + gap, part_size(1) + gap);
const Vec2d cell_size(part_size(0) + gap, part_size(1) + gap);
const BoundingBoxf bed_bbox = (bed_bounding_box != NULL && bed_bounding_box->defined) ?
*bed_bounding_box :
// Bogus bed size, large enough not to trigger the unsufficient bed size error.
BoundingBoxf(
Pointf(0, 0),
Pointf(cell_size(0) * num_parts, cell_size(1) * num_parts));
Vec2d(0, 0),
Vec2d(cell_size(0) * num_parts, cell_size(1) * num_parts));
// This is how many cells we have available into which to put parts.
size_t cellw = size_t(floor((bed_bbox.size()(0) + gap) / cell_size(0)));
@ -372,8 +372,8 @@ Pointfs arrange(size_t num_parts, const Pointf &part_size, coordf_t gap, const B
CONFESS(PRINTF_ZU " parts won't fit in your print area!\n", num_parts);
// Get a bounding box of cellw x cellh cells, centered at the center of the bed.
Pointf cells_size(cellw * cell_size(0) - gap, cellh * cell_size(1) - gap);
Pointf cells_offset(bed_bbox.center() - 0.5 * cells_size);
Vec2d cells_size(cellw * cell_size(0) - gap, cellh * cell_size(1) - gap);
Vec2d cells_offset(bed_bbox.center() - 0.5 * cells_size);
BoundingBoxf cells_bb(cells_offset, cells_size + cells_offset);
// List of cells, sorted by distance from center.
@ -405,35 +405,35 @@ Pointfs arrange(size_t num_parts, const Pointf &part_size, coordf_t gap, const B
Pointfs positions;
positions.reserve(num_parts);
for (std::vector<ArrangeItem>::const_iterator it = cellsorder.begin(); it != cellsorder.end(); ++ it)
positions.push_back(Pointf(it->pos(0) - 0.5 * part_size(0), it->pos(1) - 0.5 * part_size(1)));
positions.push_back(Vec2d(it->pos(0) - 0.5 * part_size(0), it->pos(1) - 0.5 * part_size(1)));
return positions;
}
#else
class ArrangeItem {
public:
Pointf pos;
public:
Vec2d pos = Vec2d::Zero();
size_t index_x, index_y;
coordf_t dist;
};
class ArrangeItemIndex {
public:
public:
coordf_t index;
ArrangeItem item;
ArrangeItemIndex(coordf_t _index, ArrangeItem _item) : index(_index), item(_item) {};
};
bool
arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const BoundingBoxf* bb, Pointfs &positions)
arrange(size_t total_parts, const Vec2d &part_size, coordf_t dist, const BoundingBoxf* bb, Pointfs &positions)
{
positions.clear();
Pointf part = part_size;
Vec2d part = part_size;
// use actual part size (the largest) plus separation distance (half on each side) in spacing algorithm
part(0) += dist;
part(1) += dist;
Pointf area;
Vec2d area(Vec2d::Zero());
if (bb != NULL && bb->defined) {
area = bb->size();
} else {
@ -449,11 +449,11 @@ arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const Boundi
return false;
// total space used by cells
Pointf cells(cellw * part(0), cellh * part(1));
Vec2d cells(cellw * part(0), cellh * part(1));
// bounding box of total space used by cells
BoundingBoxf cells_bb;
cells_bb.merge(Pointf(0,0)); // min
cells_bb.merge(Vec2d(0,0)); // min
cells_bb.merge(cells); // max
// center bounding box to area
@ -533,7 +533,7 @@ arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const Boundi
coordf_t cx = c.item.index_x - lx;
coordf_t cy = c.item.index_y - ty;
positions.push_back(Pointf(cx * part(0), cy * part(1)));
positions.push_back(Vec2d(cx * part(0), cy * part(1)));
}
if (bb != NULL && bb->defined) {

View file

@ -66,7 +66,7 @@ static inline bool is_ccw(const Polygon &poly)
return o == ORIENTATION_CCW;
}
inline bool ray_ray_intersection(const Pointf &p1, const Vectorf &v1, const Pointf &p2, const Vectorf &v2, Pointf &res)
inline bool ray_ray_intersection(const Vec2d &p1, const Vec2d &v1, const Vec2d &p2, const Vec2d &v2, Vec2d &res)
{
double denom = v1(0) * v2(1) - v2(0) * v1(1);
if (std::abs(denom) < EPSILON)
@ -77,7 +77,7 @@ inline bool ray_ray_intersection(const Pointf &p1, const Vectorf &v1, const Poin
return true;
}
inline bool segment_segment_intersection(const Pointf &p1, const Vectorf &v1, const Pointf &p2, const Vectorf &v2, Pointf &res)
inline bool segment_segment_intersection(const Vec2d &p1, const Vec2d &v1, const Vec2d &p2, const Vec2d &v2, Vec2d &res)
{
double denom = v1(0) * v2(1) - v2(0) * v1(1);
if (std::abs(denom) < EPSILON)
@ -123,7 +123,7 @@ void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* ret
double linint(double value, double oldmin, double oldmax, double newmin, double newmax);
bool arrange(
// input
size_t num_parts, const Pointf &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box,
size_t num_parts, const Vec2d &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box,
// output
Pointfs &positions);

View file

@ -97,11 +97,11 @@ bool Line::intersection(const Line &l2, Point *intersection) const
return false; // not intersecting
}
Pointf3 Linef3::intersect_plane(double z) const
Vec3d Linef3::intersect_plane(double z) const
{
auto v = (this->b - this->a).cast<double>();
double t = (z - this->a(2)) / v(2);
return Pointf3(this->a(0) + v(0) * t, this->a(1) + v(1) * t, z);
return Vec3d(this->a(0) + v(0) * t, this->a(1) + v(1) * t, z);
}
}

View file

@ -19,7 +19,7 @@ class Line
{
public:
Line() {}
explicit Line(Point _a, Point _b): a(_a), b(_b) {}
Line(const Point& _a, const Point& _b) : a(_a), b(_b) {}
explicit operator Lines() const { Lines lines; lines.emplace_back(*this); return lines; }
void scale(double factor) { this->a *= factor; this->b *= factor; }
void translate(double x, double y) { Vector v(x, y); this->a += v; this->b += v; }
@ -49,45 +49,49 @@ class ThickLine : public Line
{
public:
ThickLine() : a_width(0), b_width(0) {}
ThickLine(Point a, Point b) : Line(a, b), a_width(0), b_width(0) {}
ThickLine(Point a, Point b, double wa, double wb) : Line(a, b), a_width(wa), b_width(wb) {}
ThickLine(const Point& a, const Point& b) : Line(a, b), a_width(0), b_width(0) {}
ThickLine(const Point& a, const Point& b, double wa, double wb) : Line(a, b), a_width(wa), b_width(wb) {}
coordf_t a_width, b_width;
double a_width, b_width;
};
class Line3
{
public:
Line3() {}
Line3(const Point3& _a, const Point3& _b) : a(_a), b(_b) {}
Line3() : a(Vec3crd::Zero()), b(Vec3crd::Zero()) {}
Line3(const Vec3crd& _a, const Vec3crd& _b) : a(_a), b(_b) {}
double length() const { return (this->a - this->b).cast<double>().norm(); }
Vector3 vector() const { return this->b - this->a; }
Vec3crd vector() const { return this->b - this->a; }
Point3 a;
Point3 b;
Vec3crd a;
Vec3crd b;
};
class Linef
{
public:
Linef() {}
explicit Linef(Pointf _a, Pointf _b): a(_a), b(_b) {}
Linef() : a(Vec2d::Zero()), b(Vec2d::Zero()) {}
Linef(const Vec2d& _a, const Vec2d& _b) : a(_a), b(_b) {}
Pointf a;
Pointf b;
Vec2d a;
Vec2d b;
};
class Linef3
{
public:
Linef3() {}
explicit Linef3(Pointf3 _a, Pointf3 _b): a(_a), b(_b) {}
Pointf3 intersect_plane(double z) const;
void scale(double factor) { this->a *= factor; this->b *= factor; }
Linef3() : a(Vec3d::Zero()), b(Vec3d::Zero()) {}
Linef3(const Vec3d& _a, const Vec3d& _b) : a(_a), b(_b) {}
Pointf3 a;
Pointf3 b;
Vec3d intersect_plane(double z) const;
void scale(double factor) { this->a *= factor; this->b *= factor; }
Vec3d vector() const { return this->b - this->a; }
Vec3d unit_vector() const { return (length() == 0.0) ? Vec3d::Zero() : vector().normalized(); }
double length() const { return vector().norm(); }
Vec3d a;
Vec3d b;
};
} // namespace Slic3r

View file

@ -235,15 +235,7 @@ BoundingBoxf3 Model::bounding_box() const
return bb;
}
BoundingBoxf3 Model::transformed_bounding_box() const
{
BoundingBoxf3 bb;
for (const ModelObject* obj : this->objects)
bb.merge(obj->tight_bounding_box(false));
return bb;
}
void Model::center_instances_around_point(const Pointf &point)
void Model::center_instances_around_point(const Vec2d &point)
{
// BoundingBoxf3 bb = this->bounding_box();
BoundingBoxf3 bb;
@ -251,7 +243,7 @@ void Model::center_instances_around_point(const Pointf &point)
for (size_t i = 0; i < o->instances.size(); ++ i)
bb.merge(o->instance_bounding_box(i, false));
Pointf shift = point - 0.5 * bb.size().xy() - bb.min.xy();
Vec2d shift = point - 0.5 * to_2d(bb.size()) - to_2d(bb.min);
for (ModelObject *o : this->objects) {
for (ModelInstance *i : o->instances)
i->offset += shift;
@ -309,8 +301,8 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb)
for (size_t i = 0; i < o->instances.size(); ++ i) {
// an accurate snug bounding box around the transformed mesh.
BoundingBoxf3 bbox(o->instance_bounding_box(i, true));
instance_sizes.push_back(bbox.size().xy());
instance_centers.push_back(bbox.center().xy());
instance_sizes.emplace_back(to_2d(bbox.size()));
instance_centers.emplace_back(to_2d(bbox.center()));
}
Pointfs positions;
@ -332,7 +324,7 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb)
// Duplicate the entire model preserving instance relative positions.
void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb)
{
Pointfs model_sizes(copies_num-1, this->bounding_box().size().xy());
Pointfs model_sizes(copies_num-1, to_2d(this->bounding_box().size()));
Pointfs positions;
if (! _arrange(model_sizes, dist, bb, positions))
CONFESS("Cannot duplicate part as the resulting objects would not fit on the print bed.\n");
@ -343,7 +335,7 @@ void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb)
// make a copy of the pointers in order to avoid recursion when appending their copies
ModelInstancePtrs instances = o->instances;
for (const ModelInstance *i : instances) {
for (const Pointf &pos : positions) {
for (const Vec2d &pos : positions) {
ModelInstance *instance = o->add_instance(*i);
instance->offset += pos;
}
@ -375,7 +367,7 @@ void Model::duplicate_objects_grid(size_t x, size_t y, coordf_t dist)
ModelObject* object = this->objects.front();
object->clear_instances();
Sizef3 size = object->bounding_box().size();
Vec3d size = object->bounding_box().size();
for (size_t x_copy = 1; x_copy <= x; ++x_copy) {
for (size_t y_copy = 1; y_copy <= y; ++y_copy) {
@ -621,54 +613,6 @@ const BoundingBoxf3& ModelObject::bounding_box() const
return m_bounding_box;
}
BoundingBoxf3 ModelObject::tight_bounding_box(bool include_modifiers) const
{
BoundingBoxf3 bb;
for (const ModelVolume* vol : this->volumes)
{
if (include_modifiers || !vol->modifier)
{
for (const ModelInstance* inst : this->instances)
{
double c = cos(inst->rotation);
double s = sin(inst->rotation);
for (int f = 0; f < vol->mesh.stl.stats.number_of_facets; ++f)
{
const stl_facet& facet = vol->mesh.stl.facet_start[f];
for (int i = 0; i < 3; ++i)
{
// original point
const stl_vertex& v = facet.vertex[i];
Pointf3 p((double)v.x, (double)v.y, (double)v.z);
// scale
p(0) *= inst->scaling_factor;
p(1) *= inst->scaling_factor;
p(2) *= inst->scaling_factor;
// rotate Z
double x = p(0);
double y = p(1);
p(0) = c * x - s * y;
p(1) = s * x + c * y;
// translate
p(0) += inst->offset(0);
p(1) += inst->offset(1);
bb.merge(p);
}
}
}
}
}
return bb;
}
// A mesh containing all transformed instances of this object.
TriangleMesh ModelObject::mesh() const
{
@ -726,24 +670,22 @@ void ModelObject::center_around_origin()
if (! v->modifier)
bb.merge(v->mesh.bounding_box());
// first align to origin on XYZ
Vectorf3 vector(-bb.min(0), -bb.min(1), -bb.min(2));
// First align to origin on XYZ, then center it on XY.
Vec3d size = bb.size();
size(2) = 0.;
Vec3d shift3 = - bb.min - 0.5 * size;
// Unaligned vector, for the Rotation2D to work on Visual Studio 2013.
Eigen::Vector2d shift2 = to_2d(shift3);
// then center it on XY
Sizef3 size = bb.size();
vector(0) -= size(0)/2;
vector(1) -= size(1)/2;
this->translate(vector);
this->origin_translation += vector;
this->translate(shift3);
this->origin_translation += shift3;
if (!this->instances.empty()) {
for (ModelInstance *i : this->instances) {
// apply rotation and scaling to vector as well before translating instance,
// in order to leave final position unaltered
Vectorf v = - vector.xy();
v.rotate(i->rotation);
i->offset += v * i->scaling_factor;
Eigen::Rotation2Dd rot(i->rotation);
i->offset -= rot * shift2 * i->scaling_factor;
}
this->invalidate_bounding_box();
}
@ -752,39 +694,38 @@ void ModelObject::center_around_origin()
void ModelObject::translate(coordf_t x, coordf_t y, coordf_t z)
{
for (ModelVolume *v : this->volumes)
{
v->mesh.translate(float(x), float(y), float(z));
if (m_bounding_box_valid)
v->m_convex_hull.translate(float(x), float(y), float(z));
}
if (m_bounding_box_valid)
m_bounding_box.translate(x, y, z);
}
void ModelObject::scale(const Pointf3 &versor)
void ModelObject::scale(const Vec3d &versor)
{
for (ModelVolume *v : this->volumes)
{
v->mesh.scale(versor);
v->m_convex_hull.scale(versor);
}
// reset origin translation since it doesn't make sense anymore
this->origin_translation = Pointf3(0,0,0);
this->origin_translation = Vec3d::Zero();
this->invalidate_bounding_box();
}
void ModelObject::rotate(float angle, const Axis &axis)
{
float min_z = FLT_MAX;
for (ModelVolume *v : this->volumes)
{
v->mesh.rotate(angle, axis);
min_z = std::min(min_z, v->mesh.stl.stats.min.z);
v->m_convex_hull.rotate(angle, axis);
}
if (min_z != 0.0f)
{
// translate the object so that its minimum z lays on the bed
for (ModelVolume *v : this->volumes)
{
v->mesh.translate(0.0f, 0.0f, -min_z);
}
}
center_around_origin();
this->origin_translation = Pointf3(0, 0, 0);
this->origin_translation = Vec3d::Zero();
this->invalidate_bounding_box();
}
@ -796,17 +737,22 @@ void ModelObject::transform(const float* matrix3x4)
for (ModelVolume* v : volumes)
{
v->mesh.transform(matrix3x4);
v->m_convex_hull.transform(matrix3x4);
}
origin_translation = Pointf3(0.0, 0.0, 0.0);
invalidate_bounding_box();
this->origin_translation = Vec3d::Zero();
this->invalidate_bounding_box();
}
void ModelObject::mirror(const Axis &axis)
{
for (ModelVolume *v : this->volumes)
{
v->mesh.mirror(axis);
this->origin_translation = Pointf3(0,0,0);
v->m_convex_hull.mirror(axis);
}
this->origin_translation = Vec3d::Zero();
this->invalidate_bounding_box();
}
@ -910,45 +856,18 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
void ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume)
{
for (ModelVolume* vol : this->volumes)
for (const ModelVolume* vol : this->volumes)
{
if (!vol->modifier)
{
for (ModelInstance* inst : this->instances)
{
BoundingBoxf3 bb;
Transform3d m = Transform3d::Identity();
m.translate(Vec3d(inst->offset(0), inst->offset(1), 0.0));
m.rotate(Eigen::AngleAxisd(inst->rotation, Vec3d::UnitZ()));
m.scale(inst->scaling_factor);
double c = cos(inst->rotation);
double s = sin(inst->rotation);
for (int f = 0; f < vol->mesh.stl.stats.number_of_facets; ++f)
{
const stl_facet& facet = vol->mesh.stl.facet_start[f];
for (int i = 0; i < 3; ++i)
{
// original point
const stl_vertex& v = facet.vertex[i];
Pointf3 p((double)v.x, (double)v.y, (double)v.z);
// scale
p(0) *= inst->scaling_factor;
p(1) *= inst->scaling_factor;
p(2) *= inst->scaling_factor;
// rotate Z
double x = p(0);
double y = p(1);
p(0) = c * x - s * y;
p(1) = s * x + c * y;
// translate
p(0) += inst->offset(0);
p(1) += inst->offset(1);
bb.merge(p);
}
}
BoundingBoxf3 bb = vol->get_convex_hull().transformed_bounding_box(m);
if (print_volume.contains(bb))
inst->print_volume_state = ModelInstance::PVS_Inside;
@ -970,7 +889,7 @@ void ModelObject::print_info() const
TriangleMesh mesh = this->raw_mesh();
mesh.check_topology();
BoundingBoxf3 bb = mesh.bounding_box();
Sizef3 size = bb.size();
Vec3d size = bb.size();
cout << "size_x = " << size(0) << endl;
cout << "size_y = " << size(1) << endl;
cout << "size_z = " << size(2) << endl;
@ -1031,6 +950,16 @@ ModelMaterial* ModelVolume::assign_unique_material()
return model->add_material(this->_material_id);
}
void ModelVolume::calculate_convex_hull()
{
m_convex_hull = mesh.convex_hull_3d();
}
const TriangleMesh& ModelVolume::get_convex_hull() const
{
return m_convex_hull;
}
// Split this volume, append the result to the object owning this volume.
// Return the number of volumes created from this one.
// This is useful to assign different materials to different volumes of an object.
@ -1082,30 +1011,20 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes
for (int i = 0; i < mesh->stl.stats.number_of_facets; ++ i) {
const stl_facet &facet = mesh->stl.facet_start[i];
for (int j = 0; j < 3; ++ j) {
stl_vertex v = facet.vertex[j];
double xold = v.x;
double yold = v.y;
v.x = float(c * xold - s * yold);
v.y = float(s * xold + c * yold);
bbox.merge(Pointf3(v.x, v.y, v.z));
const stl_vertex &v = facet.vertex[j];
bbox.merge(Vec3d(c * v(0) - s * v(1), s * v(0) + c * v(1), v(2)));
}
}
if (! empty(bbox)) {
// Scale the bounding box uniformly.
if (std::abs(this->scaling_factor - 1.) > EPSILON) {
bbox.min(0) *= float(this->scaling_factor);
bbox.min(1) *= float(this->scaling_factor);
bbox.min(2) *= float(this->scaling_factor);
bbox.max(0) *= float(this->scaling_factor);
bbox.max(1) *= float(this->scaling_factor);
bbox.max(2) *= float(this->scaling_factor);
bbox.min *= this->scaling_factor;
bbox.max *= this->scaling_factor;
}
// Translate the bounding box.
if (! dont_translate) {
bbox.min(0) += float(this->offset(0));
bbox.min(1) += float(this->offset(1));
bbox.max(0) += float(this->offset(0));
bbox.max(1) += float(this->offset(1));
Eigen::Map<Vec2d>(bbox.min.data()) += this->offset;
Eigen::Map<Vec2d>(bbox.max.data()) += this->offset;
}
}
return bbox;
@ -1113,10 +1032,11 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes
BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
{
auto matrix = Transform3f::Identity();
Transform3d matrix = Transform3d::Identity();
if (!dont_translate)
matrix.translate(Vec3f((float)offset(0), (float)offset(1), 0.0f));
matrix.rotate(Eigen::AngleAxisf(rotation, Vec3f::UnitZ()));
matrix.translate(Vec3d(offset(0), offset(1), 0.0));
matrix.rotate(Eigen::AngleAxisd(rotation, Vec3d::UnitZ()));
matrix.scale(scaling_factor);
return bbox.transformed(matrix);
}

View file

@ -84,7 +84,7 @@ public:
center_around_origin() method. Callers might want to apply the same translation
to new volumes before adding them to this object in order to preserve alignment
when user expects that. */
Pointf3 origin_translation;
Vec3d origin_translation;
Model* get_model() const { return m_model; };
@ -105,9 +105,6 @@ public:
// This bounding box is being cached.
const BoundingBoxf3& bounding_box() const;
void invalidate_bounding_box() { m_bounding_box_valid = false; }
// Returns a snug bounding box of the transformed instances.
// This bounding box is not being cached.
BoundingBoxf3 tight_bounding_box(bool include_modifiers) const;
// A mesh containing all transformed instances of this object.
TriangleMesh mesh() const;
@ -120,9 +117,9 @@ public:
// A snug bounding box around the transformed non-modifier object volumes.
BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const;
void center_around_origin();
void translate(const Vectorf3 &vector) { this->translate(vector(0), vector(1), vector(2)); }
void translate(const Vec3d &vector) { this->translate(vector(0), vector(1), vector(2)); }
void translate(coordf_t x, coordf_t y, coordf_t z);
void scale(const Pointf3 &versor);
void scale(const Vec3d &versor);
void rotate(float angle, const Axis &axis);
void transform(const float* matrix3x4);
void mirror(const Axis &axis);
@ -138,7 +135,7 @@ public:
void print_info() const;
private:
ModelObject(Model *model) : layer_height_profile_valid(false), m_model(model), m_bounding_box_valid(false) {}
ModelObject(Model *model) : layer_height_profile_valid(false), m_model(model), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false) {}
ModelObject(Model *model, const ModelObject &other, bool copy_volumes = true);
ModelObject& operator= (ModelObject other);
void swap(ModelObject &other);
@ -157,6 +154,10 @@ private:
class ModelVolume
{
friend class ModelObject;
// The convex hull of this model's mesh.
TriangleMesh m_convex_hull;
public:
std::string name;
// The triangular model.
@ -180,19 +181,32 @@ public:
ModelMaterial* assign_unique_material();
void calculate_convex_hull();
const TriangleMesh& get_convex_hull() const;
private:
// Parent object owning this ModelVolume.
ModelObject* object;
t_model_material_id _material_id;
ModelVolume(ModelObject *object, const TriangleMesh &mesh) : mesh(mesh), modifier(false), object(object) {}
ModelVolume(ModelObject *object, TriangleMesh &&mesh) : mesh(std::move(mesh)), modifier(false), object(object) {}
ModelVolume(ModelObject *object, const ModelVolume &other) :
name(other.name), mesh(other.mesh), config(other.config), modifier(other.modifier), object(object)
{ this->material_id(other.material_id()); }
ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) :
ModelVolume(ModelObject *object, const TriangleMesh &mesh) : mesh(mesh), modifier(false), object(object)
{
if (mesh.stl.stats.number_of_facets > 1)
calculate_convex_hull();
}
ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull) : mesh(std::move(mesh)), m_convex_hull(std::move(convex_hull)), modifier(false), object(object) {}
ModelVolume(ModelObject *object, const ModelVolume &other) :
name(other.name), mesh(other.mesh), m_convex_hull(other.m_convex_hull), config(other.config), modifier(other.modifier), object(object)
{
this->material_id(other.material_id());
}
ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) :
name(other.name), mesh(std::move(mesh)), config(other.config), modifier(other.modifier), object(object)
{ this->material_id(other.material_id()); }
{
this->material_id(other.material_id());
if (mesh.stl.stats.number_of_facets > 1)
calculate_convex_hull();
}
};
// A single instance of a ModelObject.
@ -213,7 +227,7 @@ public:
// Transform3d transform;
double rotation; // Rotation around the Z axis, in radians around mesh center point
double scaling_factor;
Pointf offset; // in unscaled coordinates
Vec2d offset; // in unscaled coordinates
// flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state())
EPrintVolumeState print_volume_state;
@ -235,7 +249,7 @@ private:
// Parent object, owning this instance.
ModelObject* object;
ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object), print_volume_state(PVS_Inside) {}
ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), offset(Vec2d::Zero()), object(object), print_volume_state(PVS_Inside) {}
ModelInstance(ModelObject *object, const ModelInstance &other) :
rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object), print_volume_state(PVS_Inside) {}
};
@ -286,9 +300,7 @@ public:
bool add_default_instances();
// Returns approximate axis aligned bounding box of this model
BoundingBoxf3 bounding_box() const;
// Returns tight axis aligned bounding box of this model
BoundingBoxf3 transformed_bounding_box() const;
void center_instances_around_point(const Pointf &point);
void center_instances_around_point(const Vec2d &point);
void translate(coordf_t x, coordf_t y, coordf_t z) { for (ModelObject *o : this->objects) o->translate(x, y, z); }
TriangleMesh mesh() const;
bool arrange_objects(coordf_t dist, const BoundingBoxf* bb = NULL);

View file

@ -468,7 +468,7 @@ void applyResult(
// appropriately
auto off = item.translation();
Radians rot = item.rotation();
Pointf foff(off.X*SCALING_FACTOR + batch_offset,
Vec2d foff(off.X*SCALING_FACTOR + batch_offset,
off.Y*SCALING_FACTOR);
// write the tranformation data into the model instance

View file

@ -196,7 +196,7 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
void MultiPoint3::translate(double x, double y)
{
for (Point3 &p : points) {
for (Vec3crd &p : points) {
p(0) += x;
p(1) += y;
}

View file

@ -85,7 +85,7 @@ class MultiPoint3
public:
Points3 points;
void append(const Point3& point) { this->points.push_back(point); }
void append(const Vec3crd& point) { this->points.push_back(point); }
void translate(double x, double y);
void translate(const Point& vector);

View file

@ -243,7 +243,7 @@ void PerimeterGenerator::process()
perimeter_spacing / 2;
// only apply infill overlap if we actually have one perimeter
if (inset > 0)
inset -= scale_(this->config->get_abs_value("infill_overlap", unscale(inset + solid_infill_spacing / 2)));
inset -= scale_(this->config->get_abs_value("infill_overlap", unscale<double>(inset + solid_infill_spacing / 2)));
// simplify infill contours according to resolution
Polygons pp;
for (ExPolygon &ex : last)
@ -420,7 +420,7 @@ static inline ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyli
path.polyline.append(line.b);
// Convert from spacing to extrusion width based on the extrusion model
// of a square extrusion ended with semi circles.
flow.width = unscale(w) + flow.height * (1. - 0.25 * PI);
flow.width = unscale<float>(w) + flow.height * (1. - 0.25 * PI);
#ifdef SLIC3R_DEBUG
printf(" filling %f gap\n", flow.width);
#endif

View file

@ -148,33 +148,11 @@ Point Point::projection_onto(const Line &line) const
return ((line.a - *this).cast<double>().squaredNorm() < (line.b - *this).cast<double>().squaredNorm()) ? line.a : line.b;
}
std::ostream& operator<<(std::ostream &stm, const Pointf &pointf)
std::ostream& operator<<(std::ostream &stm, const Vec2d &pointf)
{
return stm << pointf(0) << "," << pointf(1);
}
void Pointf::rotate(double angle)
{
double cur_x = (*this)(0);
double cur_y = (*this)(1);
double s = ::sin(angle);
double c = ::cos(angle);
(*this)(0) = c * cur_x - s * cur_y;
(*this)(1) = c * cur_y + s * cur_x;
}
void Pointf::rotate(double angle, const Pointf &center)
{
double cur_x = (*this)(0);
double cur_y = (*this)(1);
double s = ::sin(angle);
double c = ::cos(angle);
double dx = cur_x - center(0);
double dy = cur_y - center(1);
(*this)(0) = center(0) + c * dx - s * dy;
(*this)(1) = center(1) + c * dy + s * dx;
}
namespace int128 {
int orient(const Vec2crd &p1, const Vec2crd &p2, const Vec2crd &p3)

View file

@ -16,19 +16,7 @@ namespace Slic3r {
class Line;
class MultiPoint;
class Point;
class Point3;
class Pointf;
class Pointf3;
typedef Point Vector;
typedef Point3 Vector3;
typedef Pointf Vectorf;
typedef Pointf3 Vectorf3;
typedef std::vector<Point> Points;
typedef std::vector<Point*> PointPtrs;
typedef std::vector<const Point*> PointConstPtrs;
typedef std::vector<Point3> Points3;
typedef std::vector<Pointf> Pointfs;
typedef std::vector<Pointf3> Pointf3s;
typedef Point Vector;
// Eigen types, to replace the Slic3r's own types in the future.
// Vector types with a fixed point coordinate base type.
@ -43,16 +31,37 @@ typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> Vec3f;
typedef Eigen::Matrix<double, 2, 1, Eigen::DontAlign> Vec2d;
typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> Vec3d;
typedef std::vector<Point> Points;
typedef std::vector<Point*> PointPtrs;
typedef std::vector<const Point*> PointConstPtrs;
typedef std::vector<Vec3crd> Points3;
typedef std::vector<Vec2d> Pointfs;
typedef std::vector<Vec3d> Pointf3s;
typedef Eigen::Transform<float, 2, Eigen::Affine, Eigen::DontAlign> Transform2f;
typedef Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAlign> Transform2d;
typedef Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign> Transform3f;
typedef Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign> Transform3d;
inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); }
inline int64_t cross2(const Vec2i64 &v1, const Vec2i64 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
inline coord_t cross2(const Vec2crd &v1, const Vec2crd &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
inline Vec2crd to_2d(const Vec3crd &pt3) { return Vec2crd(pt3(0), pt3(1)); }
inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); }
inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); }
inline Vec2d to_2d(const Vec3d &pt3) { return Vec2d (pt3(0), pt3(1)); }
inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale<double>(x), unscale<double>(y)); }
inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale<double>(pt(0)), unscale<double>(pt(1))); }
inline Vec2d unscale(const Vec2d &pt) { return Vec2d(unscale<double>(pt(0)), unscale<double>(pt(1))); }
inline Vec3d unscale(coord_t x, coord_t y, coord_t z) { return Vec3d(unscale<double>(x), unscale<double>(y), unscale<double>(z)); }
inline Vec3d unscale(const Vec3crd &pt) { return Vec3d(unscale<double>(pt(0)), unscale<double>(pt(1)), unscale<double>(pt(2))); }
inline Vec3d unscale(const Vec3d &pt) { return Vec3d(unscale<double>(pt(0)), unscale<double>(pt(1)), unscale<double>(pt(2))); }
inline std::string to_string(const Vec2crd &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + "]"; }
inline std::string to_string(const Vec2d &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + "]"; }
inline std::string to_string(const Vec3crd &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + ", " + std::to_string(pt(2)) + "]"; }
@ -210,81 +219,7 @@ private:
coord_t m_grid_log2;
};
class Point3 : public Vec3crd
{
public:
typedef coord_t coord_type;
explicit Point3() { (*this)(0) = (*this)(1) = (*this)(2) = 0; }
explicit Point3(coord_t x, coord_t y, coord_t z) { (*this)(0) = x; (*this)(1) = y; (*this)(2) = z; }
// This constructor allows you to construct Point3 from Eigen expressions
template<typename OtherDerived>
Point3(const Eigen::MatrixBase<OtherDerived> &other) : Vec3crd(other) {}
static Point3 new_scale(coordf_t x, coordf_t y, coordf_t z) { return Point3(coord_t(scale_(x)), coord_t(scale_(y)), coord_t(scale_(z))); }
// This method allows you to assign Eigen expressions to MyVectorType
template<typename OtherDerived>
Point3& operator=(const Eigen::MatrixBase<OtherDerived> &other)
{
this->Vec3crd::operator=(other);
return *this;
}
Point xy() const { return Point((*this)(0), (*this)(1)); }
};
std::ostream& operator<<(std::ostream &stm, const Pointf &pointf);
class Pointf : public Vec2d
{
public:
typedef coordf_t coord_type;
explicit Pointf() { (*this)(0) = (*this)(1) = 0.; }
explicit Pointf(coordf_t x, coordf_t y) { (*this)(0) = x; (*this)(1) = y; }
// This constructor allows you to construct Pointf from Eigen expressions
template<typename OtherDerived>
Pointf(const Eigen::MatrixBase<OtherDerived> &other) : Vec2d(other) {}
static Pointf new_unscale(coord_t x, coord_t y) { return Pointf(unscale(x), unscale(y)); }
static Pointf new_unscale(const Point &p) { return Pointf(unscale(p(0)), unscale(p(1))); }
// This method allows you to assign Eigen expressions to MyVectorType
template<typename OtherDerived>
Pointf& operator=(const Eigen::MatrixBase<OtherDerived> &other)
{
this->Vec2d::operator=(other);
return *this;
}
void rotate(double angle);
void rotate(double angle, const Pointf &center);
bool operator< (const Pointf& rhs) const { return (*this)(0) < rhs(0) || ((*this)(0) == rhs(0) && (*this)(1) < rhs(1)); }
};
class Pointf3 : public Vec3d
{
public:
typedef coordf_t coord_type;
explicit Pointf3() { (*this)(0) = (*this)(1) = (*this)(2) = 0.; }
explicit Pointf3(coordf_t x, coordf_t y, coordf_t z) { (*this)(0) = x; (*this)(1) = y; (*this)(2) = z; }
// This constructor allows you to construct Pointf from Eigen expressions
template<typename OtherDerived>
Pointf3(const Eigen::MatrixBase<OtherDerived> &other) : Vec3d(other) {}
static Pointf3 new_unscale(coord_t x, coord_t y, coord_t z) { return Pointf3(unscale(x), unscale(y), unscale(z)); }
static Pointf3 new_unscale(const Point3& p) { return Pointf3(unscale(p(0)), unscale(p(1)), unscale(p(2))); }
// This method allows you to assign Eigen expressions to MyVectorType
template<typename OtherDerived>
Pointf3& operator=(const Eigen::MatrixBase<OtherDerived> &other)
{
this->Vec3d::operator=(other);
return *this;
}
Pointf xy() const { return Pointf((*this)(0), (*this)(1)); }
};
std::ostream& operator<<(std::ostream &stm, const Vec2d &pointf);
} // namespace Slic3r

View file

@ -297,10 +297,10 @@ Point Polygon::point_projection(const Point &point) const
dmin = d;
proj = pt1;
}
Pointf v1(coordf_t(pt1(0) - pt0(0)), coordf_t(pt1(1) - pt0(1)));
Vec2d v1(coordf_t(pt1(0) - pt0(0)), coordf_t(pt1(1) - pt0(1)));
coordf_t div = v1.squaredNorm();
if (div > 0.) {
Pointf v2(coordf_t(point(0) - pt0(0)), coordf_t(point(1) - pt0(1)));
Vec2d v2(coordf_t(point(0) - pt0(0)), coordf_t(point(1) - pt0(1)));
coordf_t t = v1.dot(v2) / div;
if (t > 0. && t < 1.) {
Point foot(coord_t(floor(coordf_t(pt0(0)) + t * v1(0) + 0.5)), coord_t(floor(coordf_t(pt0(1)) + t * v1(1) + 0.5)));

View file

@ -24,11 +24,12 @@ public:
explicit Polygon(const Points &points): MultiPoint(points) {}
Polygon(const Polygon &other) : MultiPoint(other.points) {}
Polygon(Polygon &&other) : MultiPoint(std::move(other.points)) {}
static Polygon new_scale(std::vector<Pointf> points) {
Points int_points;
for (auto pt : points)
int_points.push_back(Point::new_scale(pt(0), pt(1)));
return Polygon(int_points);
static Polygon new_scale(const std::vector<Vec2d> &points) {
Polygon pgn;
pgn.points.reserve(points.size());
for (const Vec2d &pt : points)
pgn.points.emplace_back(Point::new_scale(pt(0), pt(1)));
return pgn;
}
Polygon& operator=(const Polygon &other) { points = other.points; return *this; }
Polygon& operator=(Polygon &&other) { points = std::move(other.points); return *this; }

View file

@ -23,12 +23,11 @@ public:
explicit Polyline(const Point &p1, const Point &p2) { points.reserve(2); points.emplace_back(p1); points.emplace_back(p2); }
Polyline& operator=(const Polyline &other) { points = other.points; return *this; }
Polyline& operator=(Polyline &&other) { points = std::move(other.points); return *this; }
static Polyline new_scale(std::vector<Pointf> points) {
static Polyline new_scale(const std::vector<Vec2d> &points) {
Polyline pl;
Points int_points;
for (auto pt : points)
int_points.push_back(Point::new_scale(pt(0), pt(1)));
pl.append(int_points);
pl.points.reserve(points.size());
for (const Vec2d &pt : points)
pl.points.emplace_back(Point::new_scale(pt(0), pt(1)));
return pl;
}

View file

@ -540,7 +540,7 @@ bool Print::has_skirt() const
std::string Print::validate() const
{
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.bed_shape.values));
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min(0)), unscale(bed_box_2D.min(1)), 0.0), Pointf3(unscale(bed_box_2D.max(0)), unscale(bed_box_2D.max(1)), config.max_print_height));
BoundingBoxf3 print_volume(unscale(bed_box_2D.min(0), bed_box_2D.min(1), 0.0), unscale(bed_box_2D.max(0), bed_box_2D.max(1), scale_(config.max_print_height)));
// Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced.
print_volume.min(2) = -1e10;
unsigned int printable_count = 0;
@ -728,7 +728,7 @@ BoundingBox Print::bounding_box() const
for (const PrintObject *object : this->objects)
for (Point copy : object->_shifted_copies) {
bb.merge(copy);
copy += object->size.xy();
copy += to_2d(object->size);
bb.merge(copy);
}
return bb;
@ -971,7 +971,7 @@ void Print::_make_skirt()
this->skirt.append(eloop);
if (this->config.min_skirt_length.value > 0) {
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx];
extruded_length[extruder_idx] += unscale<double>(loop.length()) * extruders_e_per_mm[extruder_idx];
if (extruded_length[extruder_idx] < this->config.min_skirt_length.value) {
// Not extruded enough yet with the current extruder. Add another loop.
if (i == 1)

View file

@ -118,7 +118,7 @@ public:
// so that next call to make_perimeters() performs a union() before computing loops
bool typed_slices;
Point3 size; // XYZ in scaled coordinates
Vec3crd size; // XYZ in scaled coordinates
// scaled coordinates to add to copies (to compensate for the alignment
// operated when creating the object but still preserving a coherent API
@ -138,13 +138,13 @@ public:
const ModelObject* model_object() const { return this->_model_object; }
const Points& copies() const { return this->_copies; }
bool add_copy(const Pointf &point);
bool add_copy(const Vec2d &point);
bool delete_last_copy();
bool delete_all_copies() { return this->set_copies(Points()); }
bool set_copies(const Points &points);
bool reload_model_instances();
// since the object is aligned to origin, bounding box coincides with size
BoundingBox bounding_box() const { return BoundingBox(Point(0,0), this->size.xy()); }
BoundingBox bounding_box() const { return BoundingBox(Point(0,0), to_2d(this->size)); }
// adds region_id, too, if necessary
void add_region_volume(unsigned int region_id, int volume_id) {

View file

@ -17,9 +17,51 @@ namespace Slic3r {
#define L(s) Slic3r::I18N::translate(s)
PrintConfigDef::PrintConfigDef()
{
this->init_common_params();
this->init_fff_params();
this->init_sla_params();
}
void PrintConfigDef::init_common_params()
{
t_optiondef_map &Options = this->options;
ConfigOptionDef* def;
def = this->add("printer_technology", coEnum);
def->label = L("Printer technology");
def->tooltip = L("Printer technology");
def->cli = "printer-technology=s";
def->enum_keys_map = &ConfigOptionEnum<PrinterTechnology>::get_enum_values();
def->enum_values.push_back("FFF");
def->enum_values.push_back("SLA");
def->default_value = new ConfigOptionEnum<PrinterTechnology>(ptFFF);
def = this->add("bed_shape", coPoints);
def->label = L("Bed shape");
def->default_value = new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) };
def = this->add("layer_height", coFloat);
def->label = L("Layer height");
def->category = L("Layers and Perimeters");
def->tooltip = L("This setting controls the height (and thus the total number) of the slices/layers. "
"Thinner layers give better accuracy but take more time to print.");
def->sidetext = L("mm");
def->cli = "layer-height=f";
def->min = 0;
def->default_value = new ConfigOptionFloat(0.3);
def = this->add("max_print_height", coFloat);
def->label = L("Max print height");
def->tooltip = L("Set this to the maximum height that can be reached by your extruder while printing.");
def->sidetext = L("mm");
def->cli = "max-print-height=f";
def->default_value = new ConfigOptionFloat(200.0);
}
void PrintConfigDef::init_fff_params()
{
t_optiondef_map &Options = this->options;
ConfigOptionDef* def;
// Maximum extruder temperature, bumped to 1500 to support printing of glass.
@ -33,10 +75,6 @@ PrintConfigDef::PrintConfigDef()
def->cli = "avoid-crossing-perimeters!";
def->default_value = new ConfigOptionBool(false);
def = this->add("bed_shape", coPoints);
def->label = L("Bed shape");
def->default_value = new ConfigOptionPoints { Pointf(0,0), Pointf(200,0), Pointf(200,200), Pointf(0,200) };
def = this->add("bed_temperature", coInts);
def->label = L("Other layers");
def->tooltip = L("Bed temperature for layers after the first one. "
@ -392,7 +430,7 @@ PrintConfigDef::PrintConfigDef()
"from the XY coordinate).");
def->sidetext = L("mm");
def->cli = "extruder-offset=s@";
def->default_value = new ConfigOptionPoints { Pointf(0,0) };
def->default_value = new ConfigOptionPoints { Vec2d(0,0) };
def = this->add("extrusion_axis", coString);
def->label = L("Extrusion axis");
@ -906,16 +944,6 @@ PrintConfigDef::PrintConfigDef()
def->height = 50;
def->default_value = new ConfigOptionString("");
def = this->add("layer_height", coFloat);
def->label = L("Layer height");
def->category = L("Layers and Perimeters");
def->tooltip = L("This setting controls the height (and thus the total number) of the slices/layers. "
"Thinner layers give better accuracy but take more time to print.");
def->sidetext = L("mm");
def->cli = "layer-height=f";
def->min = 0;
def->default_value = new ConfigOptionFloat(0.3);
def = this->add("remaining_times", coBool);
def->label = L("Supports remaining times");
def->tooltip = L("Emit M73 P[percent printed] R[remaining time in minutes] at 1 minute"
@ -1036,13 +1064,6 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->default_value = new ConfigOptionFloats { 0. };
def = this->add("max_print_height", coFloat);
def->label = L("Max print height");
def->tooltip = L("Set this to the maximum height that can be reached by your extruder while printing.");
def->sidetext = L("mm");
def->cli = "max-print-height=f";
def->default_value = new ConfigOptionFloat(200.0);
def = this->add("max_print_speed", coFloat);
def->label = L("Max print speed");
def->tooltip = L("When setting other speed settings to 0 Slic3r will autocalculate the optimal speed "
@ -1137,25 +1158,37 @@ PrintConfigDef::PrintConfigDef()
def->cli = "nozzle-diameter=f@";
def->default_value = new ConfigOptionFloats { 0.5 };
def = this->add("octoprint_apikey", coString);
def->label = L("API Key");
def->tooltip = L("Slic3r can upload G-code files to OctoPrint. This field should contain "
"the API Key required for authentication.");
def->cli = "octoprint-apikey=s";
def = this->add("host_type", coEnum);
def->label = L("Host Type");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field must contain "
"the kind of the host.");
def->cli = "host-type=s";
def->enum_keys_map = &ConfigOptionEnum<PrintHostType>::get_enum_values();
def->enum_values.push_back("octoprint");
def->enum_values.push_back("duet");
def->enum_labels.push_back("OctoPrint");
def->enum_labels.push_back("Duet");
def->default_value = new ConfigOptionEnum<PrintHostType>(htOctoPrint);
def = this->add("printhost_apikey", coString);
def->label = L("API Key / Password");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
"the API Key or the password required for authentication.");
def->cli = "printhost-apikey=s";
def->default_value = new ConfigOptionString("");
def = this->add("octoprint_cafile", coString);
def = this->add("printhost_cafile", coString);
def->label = "HTTPS CA file";
def->tooltip = "Custom CA certificate file can be specified for HTTPS OctoPrint connections, in crt/pem format. "
"If left blank, the default OS CA certificate repository is used.";
def->cli = "octoprint-cafile=s";
def->cli = "printhost-cafile=s";
def->default_value = new ConfigOptionString("");
def = this->add("octoprint_host", coString);
def = this->add("print_host", coString);
def->label = L("Hostname, IP or URL");
def->tooltip = L("Slic3r can upload G-code files to OctoPrint. This field should contain "
"the hostname, IP address or URL of the OctoPrint instance.");
def->cli = "octoprint-host=s";
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
"the hostname, IP address or URL of the printer host instance.");
def->cli = "print-host=s";
def->default_value = new ConfigOptionString("");
def = this->add("only_retract_when_crossing_perimeters", coBool);
@ -2121,6 +2154,103 @@ PrintConfigDef::PrintConfigDef()
def->default_value = new ConfigOptionFloat(35.);
}
void PrintConfigDef::init_sla_params()
{
t_optiondef_map &Options = this->options;
ConfigOptionDef* def;
// SLA Printer settings
def = this->add("display_width", coFloat);
def->label = L("Display width");
def->tooltip = L("Width of the display");
def->cli = "display-width=f";
def->min = 1;
def->default_value = new ConfigOptionFloat(150.);
def = this->add("display_height", coFloat);
def->label = L("Display height");
def->tooltip = L("Height of the display");
def->cli = "display-height=f";
def->min = 1;
def->default_value = new ConfigOptionFloat(100.);
def = this->add("display_pixels_x", coInt);
def->full_label = L("Number of pixels in");
def->label = ("X");
def->tooltip = L("Number of pixels in X");
def->cli = "display-pixels-x=i";
def->min = 100;
def->default_value = new ConfigOptionInt(2000);
def = this->add("display_pixels_y", coInt);
def->label = ("Y");
def->tooltip = L("Number of pixels in Y");
def->cli = "display-pixels-y=i";
def->min = 100;
def->default_value = new ConfigOptionInt(1000);
def = this->add("printer_correction", coFloats);
def->full_label = L("Printer scaling correction");
def->tooltip = L("Printer scaling correction");
def->min = 0;
def->default_value = new ConfigOptionFloats( { 1., 1., 1. } );
// SLA Material settings.
def = this->add("initial_layer_height", coFloat);
def->label = L("Initial layer height");
def->tooltip = L("Initial layer height");
def->sidetext = L("mm");
def->cli = "initial-layer-height=f";
def->min = 0;
def->default_value = new ConfigOptionFloat(0.3);
def = this->add("exposure_time", coFloat);
def->label = L("Exposure time");
def->tooltip = L("Exposure time");
def->sidetext = L("s");
def->cli = "exposure-time=f";
def->min = 0;
def->default_value = new ConfigOptionFloat(10);
def = this->add("initial_exposure_time", coFloat);
def->label = L("Initial exposure time");
def->tooltip = L("Initial exposure time");
def->sidetext = L("s");
def->cli = "initial-exposure-time=f";
def->min = 0;
def->default_value = new ConfigOptionFloat(15);
def = this->add("material_correction_printing", coFloats);
def->full_label = L("Correction for expansion when printing");
def->tooltip = L("Correction for expansion when printing");
def->min = 0;
def->default_value = new ConfigOptionFloats( { 1. , 1., 1. } );
def = this->add("material_correction_curing", coFloats);
def->full_label = L("Correction for expansion after curing");
def->tooltip = L("Correction for expansion after curing");
def->min = 0;
def->default_value = new ConfigOptionFloats( { 1. , 1., 1. } );
def = this->add("material_notes", coString);
def->label = L("SLA print material notes");
def->tooltip = L("You can put your notes regarding the SLA print material here.");
def->cli = "material-notes=s";
def->multiline = true;
def->full_width = true;
def->height = 130;
def->default_value = new ConfigOptionString("");
def = this->add("default_sla_material_profile", coString);
def->label = L("Default SLA material profile");
def->tooltip = L("Default print profile associated with the current printer profile. "
"On selection of the current printer profile, this print profile will be activated.");
def->default_value = new ConfigOptionString();
def = this->add("sla_material_settings_id", coString);
def->default_value = new ConfigOptionString("");
}
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)
{
// handle legacy options
@ -2153,10 +2283,6 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
std::ostringstream oss;
oss << "0x0," << p.value(0) << "x0," << p.value(0) << "x" << p.value(1) << ",0x" << p.value(1);
value = oss.str();
// Maybe one day we will rename octoprint_host to print_host as it has been done in the upstream Slic3r.
// Commenting this out fixes github issue #869 for now.
// } else if (opt_key == "octoprint_host" && !value.empty()) {
// opt_key = "print_host";
} else if ((opt_key == "perimeter_acceleration" && value == "25")
|| (opt_key == "infill_acceleration" && value == "50")) {
/* For historical reasons, the world's full of configs having these very low values;
@ -2167,6 +2293,12 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
} else if (opt_key == "support_material_pattern" && value == "pillars") {
// Slic3r PE does not support the pillars. They never worked well.
value = "rectilinear";
} else if (opt_key == "octoprint_host") {
opt_key = "print_host";
} else if (opt_key == "octoprint_cafile") {
opt_key = "printhost_cafile";
} else if (opt_key == "octoprint_apikey") {
opt_key = "printhost_apikey";
}
// Ignore the following obsolete configuration keys:
@ -2176,9 +2308,6 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
"standby_temperature", "scale", "rotate", "duplicate", "duplicate_grid",
"start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start",
"seal_position", "vibration_limit", "bed_size",
// Maybe one day we will rename octoprint_host to print_host as it has been done in the upstream Slic3r.
// Commenting this out fixes github issue #869 for now.
// "octoprint_host",
"print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe"
};
@ -2188,7 +2317,6 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
}
if (! print_config_def.has(opt_key)) {
//printf("Unknown option %s\n", opt_key.c_str());
opt_key = "";
return;
}
@ -2446,4 +2574,8 @@ StaticPrintConfig::StaticCache<class Slic3r::PrintConfig> PrintConfig::s_c
StaticPrintConfig::StaticCache<class Slic3r::HostConfig> HostConfig::s_cache_HostConfig;
StaticPrintConfig::StaticCache<class Slic3r::FullPrintConfig> FullPrintConfig::s_cache_FullPrintConfig;
StaticPrintConfig::StaticCache<class Slic3r::SLAMaterialConfig> SLAMaterialConfig::s_cache_SLAMaterialConfig;
StaticPrintConfig::StaticCache<class Slic3r::SLAPrinterConfig> SLAPrinterConfig::s_cache_SLAPrinterConfig;
StaticPrintConfig::StaticCache<class Slic3r::SLAFullPrintConfig> SLAFullPrintConfig::s_cache_SLAFullPrintConfig;
}

View file

@ -22,11 +22,23 @@
namespace Slic3r {
enum PrinterTechnology
{
// Fused Filament Fabrication
ptFFF,
// Stereolitography
ptSLA,
};
enum GCodeFlavor {
gcfRepRap, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlin, gcfSailfish, gcfMach3, gcfMachinekit,
gcfSmoothie, gcfNoExtrusion,
};
enum PrintHostType {
htOctoPrint, htDuet,
};
enum InfillPattern {
ipRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral,
@ -44,7 +56,16 @@ enum FilamentType {
ftPLA, ftABS, ftPET, ftHIPS, ftFLEX, ftSCAFF, ftEDGE, ftNGEN, ftPVA
};
template<> inline t_config_enum_values& ConfigOptionEnum<GCodeFlavor>::get_enum_values() {
template<> inline const t_config_enum_values& ConfigOptionEnum<PrinterTechnology>::get_enum_values() {
static t_config_enum_values keys_map;
if (keys_map.empty()) {
keys_map["FFF"] = ptFFF;
keys_map["SLA"] = ptSLA;
}
return keys_map;
}
template<> inline const t_config_enum_values& ConfigOptionEnum<GCodeFlavor>::get_enum_values() {
static t_config_enum_values keys_map;
if (keys_map.empty()) {
keys_map["reprap"] = gcfRepRap;
@ -61,7 +82,16 @@ template<> inline t_config_enum_values& ConfigOptionEnum<GCodeFlavor>::get_enum_
return keys_map;
}
template<> inline t_config_enum_values& ConfigOptionEnum<InfillPattern>::get_enum_values() {
template<> inline const t_config_enum_values& ConfigOptionEnum<PrintHostType>::get_enum_values() {
static t_config_enum_values keys_map;
if (keys_map.empty()) {
keys_map["octoprint"] = htOctoPrint;
keys_map["duet"] = htDuet;
}
return keys_map;
}
template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::get_enum_values() {
static t_config_enum_values keys_map;
if (keys_map.empty()) {
keys_map["rectilinear"] = ipRectilinear;
@ -81,7 +111,7 @@ template<> inline t_config_enum_values& ConfigOptionEnum<InfillPattern>::get_enu
return keys_map;
}
template<> inline t_config_enum_values& ConfigOptionEnum<SupportMaterialPattern>::get_enum_values() {
template<> inline const t_config_enum_values& ConfigOptionEnum<SupportMaterialPattern>::get_enum_values() {
static t_config_enum_values keys_map;
if (keys_map.empty()) {
keys_map["rectilinear"] = smpRectilinear;
@ -91,7 +121,7 @@ template<> inline t_config_enum_values& ConfigOptionEnum<SupportMaterialPattern>
return keys_map;
}
template<> inline t_config_enum_values& ConfigOptionEnum<SeamPosition>::get_enum_values() {
template<> inline const t_config_enum_values& ConfigOptionEnum<SeamPosition>::get_enum_values() {
static t_config_enum_values keys_map;
if (keys_map.empty()) {
keys_map["random"] = spRandom;
@ -102,7 +132,7 @@ template<> inline t_config_enum_values& ConfigOptionEnum<SeamPosition>::get_enum
return keys_map;
}
template<> inline t_config_enum_values& ConfigOptionEnum<FilamentType>::get_enum_values() {
template<> inline const t_config_enum_values& ConfigOptionEnum<FilamentType>::get_enum_values() {
static t_config_enum_values keys_map;
if (keys_map.empty()) {
keys_map["PLA"] = ftPLA;
@ -126,6 +156,11 @@ public:
PrintConfigDef();
static void handle_legacy(t_config_option_key &opt_key, std::string &value);
private:
void init_common_params();
void init_fff_params();
void init_sla_params();
};
// The one and only global definition of SLic3r configuration options.
@ -801,18 +836,20 @@ class HostConfig : public StaticPrintConfig
{
STATIC_PRINT_CONFIG_CACHE(HostConfig)
public:
ConfigOptionString octoprint_host;
ConfigOptionString octoprint_apikey;
ConfigOptionString octoprint_cafile;
ConfigOptionEnum<PrintHostType> host_type;
ConfigOptionString print_host;
ConfigOptionString printhost_apikey;
ConfigOptionString printhost_cafile;
ConfigOptionString serial_port;
ConfigOptionInt serial_speed;
protected:
void initialize(StaticCacheBase &cache, const char *base_ptr)
{
OPT_PTR(octoprint_host);
OPT_PTR(octoprint_apikey);
OPT_PTR(octoprint_cafile);
OPT_PTR(host_type);
OPT_PTR(print_host);
OPT_PTR(printhost_apikey);
OPT_PTR(printhost_cafile);
OPT_PTR(serial_port);
OPT_PTR(serial_speed);
}
@ -844,6 +881,73 @@ protected:
}
};
class SLAMaterialConfig : public StaticPrintConfig
{
STATIC_PRINT_CONFIG_CACHE(SLAMaterialConfig)
public:
ConfigOptionFloat layer_height;
ConfigOptionFloat initial_layer_height;
ConfigOptionFloat exposure_time;
ConfigOptionFloat initial_exposure_time;
ConfigOptionFloats material_correction_printing;
ConfigOptionFloats material_correction_curing;
protected:
void initialize(StaticCacheBase &cache, const char *base_ptr)
{
OPT_PTR(layer_height);
OPT_PTR(initial_layer_height);
OPT_PTR(exposure_time);
OPT_PTR(initial_exposure_time);
OPT_PTR(material_correction_printing);
OPT_PTR(material_correction_curing);
}
};
class SLAPrinterConfig : public StaticPrintConfig
{
STATIC_PRINT_CONFIG_CACHE(SLAPrinterConfig)
public:
ConfigOptionEnum<PrinterTechnology> printer_technology;
ConfigOptionPoints bed_shape;
ConfigOptionFloat max_print_height;
ConfigOptionFloat display_width;
ConfigOptionFloat display_height;
ConfigOptionInt display_pixels_x;
ConfigOptionInt display_pixels_y;
ConfigOptionFloats printer_correction;
protected:
void initialize(StaticCacheBase &cache, const char *base_ptr)
{
OPT_PTR(printer_technology);
OPT_PTR(bed_shape);
OPT_PTR(max_print_height);
OPT_PTR(display_width);
OPT_PTR(display_height);
OPT_PTR(display_pixels_x);
OPT_PTR(display_pixels_y);
OPT_PTR(printer_correction);
}
};
class SLAFullPrintConfig : public SLAPrinterConfig, public SLAMaterialConfig
{
STATIC_PRINT_CONFIG_CACHE_DERIVED(SLAFullPrintConfig)
SLAFullPrintConfig() : SLAPrinterConfig(0), SLAMaterialConfig(0) { initialize_cache(); *this = s_cache_SLAFullPrintConfig.defaults(); }
public:
// Validate the SLAFullPrintConfig. Returns an empty string on success, otherwise an error message is returned.
// std::string validate();
protected:
// Protected constructor to be called to initialize ConfigCache::m_default.
SLAFullPrintConfig(int) : SLAPrinterConfig(0), SLAMaterialConfig(0) {}
void initialize(StaticCacheBase &cache, const char *base_ptr)
{
this->SLAPrinterConfig ::initialize(cache, base_ptr);
this->SLAMaterialConfig::initialize(cache, base_ptr);
}
};
#undef STATIC_PRINT_CONFIG_CACHE
#undef STATIC_PRINT_CONFIG_CACHE_BASE
#undef STATIC_PRINT_CONFIG_CACHE_DERIVED

View file

@ -38,6 +38,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding
typed_slices(false),
_print(print),
_model_object(model_object),
size(Vec3crd::Zero()),
layer_height_profile_valid(false)
{
// Compute the translation to be applied to our meshes so that we work with smaller coordinates
@ -50,8 +51,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding
// (copies are expressed in G-code coordinates and this translation is not publicly exposed).
this->_copies_shift = Point::new_scale(modobj_bbox.min(0), modobj_bbox.min(1));
// Scale the object size and store it
Pointf3 size = modobj_bbox.size();
this->size = Point3::new_scale(size(0), size(1), size(2));
this->size = (modobj_bbox.size() * (1. / SCALING_FACTOR)).cast<coord_t>();
}
this->reload_model_instances();
@ -59,7 +59,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding
this->layer_height_profile = model_object->layer_height_profile;
}
bool PrintObject::add_copy(const Pointf &point)
bool PrintObject::add_copy(const Vec2d &point)
{
Points points = this->_copies;
points.push_back(Point::new_scale(point(0), point(1)));
@ -1121,7 +1121,7 @@ SlicingParameters PrintObject::slicing_parameters() const
{
return SlicingParameters::create_from_config(
this->print()->config, this->config,
unscale(this->size(2)), this->print()->object_extruders());
unscale<double>(this->size(2)), this->print()->object_extruders());
}
bool PrintObject::update_layer_height_profile(std::vector<coordf_t> &layer_height_profile) const
@ -1335,7 +1335,7 @@ std::vector<ExPolygons> PrintObject::_slice_region(size_t region_id, const std::
// consider the first one
this->model_object()->instances.front()->transform_mesh(&mesh, true);
// align mesh to Z = 0 (it should be already aligned actually) and apply XY shift
mesh.translate(- float(unscale(this->_copies_shift(0))), - float(unscale(this->_copies_shift(1))), -float(this->model_object()->bounding_box().min(2)));
mesh.translate(- unscale<float>(this->_copies_shift(0)), - unscale<float>(this->_copies_shift(1)), - float(this->model_object()->bounding_box().min(2)));
// perform actual slicing
TriangleMeshSlicer mslicer(&mesh);
mslicer.slice(z, &layers);

View file

@ -3,7 +3,7 @@
#include <boost/nowide/cstdio.hpp>
#define COORD(x) ((float)unscale((x))*10)
#define COORD(x) (unscale<float>((x))*10)
namespace Slic3r {
@ -58,8 +58,8 @@ SVG::draw(const Line &line, std::string stroke, coordf_t stroke_width)
void SVG::draw(const ThickLine &line, const std::string &fill, const std::string &stroke, coordf_t stroke_width)
{
Pointf dir(line.b(0)-line.a(0), line.b(1)-line.a(1));
Pointf perp(-dir(1), dir(0));
Vec2d dir(line.b(0)-line.a(0), line.b(1)-line.a(1));
Vec2d perp(-dir(1), dir(0));
coordf_t len = sqrt(perp(0)*perp(0) + perp(1)*perp(1));
coordf_t da = coordf_t(0.5)*line.a_width/len;
coordf_t db = coordf_t(0.5)*line.b_width/len;

View file

@ -561,15 +561,15 @@ int generate_layer_height_texture(
void *data, int rows, int cols, bool level_of_detail_2nd_level)
{
// https://github.com/aschn/gnuplot-colorbrewer
std::vector<Point3> palette_raw;
palette_raw.push_back(Point3(0x01A, 0x098, 0x050));
palette_raw.push_back(Point3(0x066, 0x0BD, 0x063));
palette_raw.push_back(Point3(0x0A6, 0x0D9, 0x06A));
palette_raw.push_back(Point3(0x0D9, 0x0F1, 0x0EB));
palette_raw.push_back(Point3(0x0FE, 0x0E6, 0x0EB));
palette_raw.push_back(Point3(0x0FD, 0x0AE, 0x061));
palette_raw.push_back(Point3(0x0F4, 0x06D, 0x043));
palette_raw.push_back(Point3(0x0D7, 0x030, 0x027));
std::vector<Vec3crd> palette_raw;
palette_raw.push_back(Vec3crd(0x01A, 0x098, 0x050));
palette_raw.push_back(Vec3crd(0x066, 0x0BD, 0x063));
palette_raw.push_back(Vec3crd(0x0A6, 0x0D9, 0x06A));
palette_raw.push_back(Vec3crd(0x0D9, 0x0F1, 0x0EB));
palette_raw.push_back(Vec3crd(0x0FE, 0x0E6, 0x0EB));
palette_raw.push_back(Vec3crd(0x0FD, 0x0AE, 0x061));
palette_raw.push_back(Vec3crd(0x0F4, 0x06D, 0x043));
palette_raw.push_back(Vec3crd(0x0D7, 0x030, 0x027));
// Clear the main texture and the 2nd LOD level.
// memset(data, 0, rows * cols * (level_of_detail_2nd_level ? 5 : 4));
@ -600,14 +600,14 @@ int generate_layer_height_texture(
int idx1 = clamp(0, int(palette_raw.size() - 1), int(floor(idxf)));
int idx2 = std::min(int(palette_raw.size() - 1), idx1 + 1);
coordf_t t = idxf - coordf_t(idx1);
const Point3 &color1 = palette_raw[idx1];
const Point3 &color2 = palette_raw[idx2];
const Vec3crd &color1 = palette_raw[idx1];
const Vec3crd &color2 = palette_raw[idx2];
coordf_t z = cell_to_z * coordf_t(cell);
assert(z >= lo && z <= hi);
// Intensity profile to visualize the layers.
coordf_t intensity = cos(M_PI * 0.7 * (mid - z) / h);
// Color mapping from layer height to RGB.
Pointf3 color(
Vec3d color(
intensity * lerp(coordf_t(color1(0)), coordf_t(color2(0)), t),
intensity * lerp(coordf_t(color1(1)), coordf_t(color2(1)), t),
intensity * lerp(coordf_t(color1(2)), coordf_t(color2(2)), t));
@ -636,10 +636,10 @@ int generate_layer_height_texture(
int idx1 = clamp(0, int(palette_raw.size() - 1), int(floor(idxf)));
int idx2 = std::min(int(palette_raw.size() - 1), idx1 + 1);
coordf_t t = idxf - coordf_t(idx1);
const Point3 &color1 = palette_raw[idx1];
const Point3 &color2 = palette_raw[idx2];
const Vec3crd &color1 = palette_raw[idx1];
const Vec3crd &color2 = palette_raw[idx2];
// Color mapping from layer height to RGB.
Pointf3 color(
Vec3d color(
lerp(coordf_t(color1(0)), coordf_t(color2(0)), t),
lerp(coordf_t(color1(1)), coordf_t(color2(1)), t),
lerp(coordf_t(color1(2)), coordf_t(color2(2)), t));

View file

@ -15,8 +15,8 @@ void SlicingAdaptive::clear()
std::pair<float, float> face_z_span(const stl_facet *f)
{
return std::pair<float, float>(
std::min(std::min(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z),
std::max(std::max(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z));
std::min(std::min(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2)),
std::max(std::max(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2)));
}
void SlicingAdaptive::prepare()
@ -40,7 +40,7 @@ void SlicingAdaptive::prepare()
// 3) Generate Z components of the facet normals.
m_face_normal_z.assign(m_faces.size(), 0.f);
for (size_t iface = 0; iface < m_faces.size(); ++ iface)
m_face_normal_z[iface] = m_faces[iface]->normal.z;
m_face_normal_z[iface] = m_faces[iface]->normal(2);
}
float SlicingAdaptive::cusp_height(float z, float cusp_value, int &current_facet)

View file

@ -2057,8 +2057,8 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
const Point &p1 = *(it-1);
const Point &p2 = *it;
// Intersection of a ray (p1, p2) with a circle placed at center_last, with radius of circle_distance.
const Pointf v_seg(coordf_t(p2(0)) - coordf_t(p1(0)), coordf_t(p2(1)) - coordf_t(p1(1)));
const Pointf v_cntr(coordf_t(p1(0) - center_last(0)), coordf_t(p1(1) - center_last(1)));
const Vec2d v_seg(coordf_t(p2(0)) - coordf_t(p1(0)), coordf_t(p2(1)) - coordf_t(p1(1)));
const Vec2d v_cntr(coordf_t(p1(0) - center_last(0)), coordf_t(p1(1) - center_last(1)));
coordf_t a = v_seg.squaredNorm();
coordf_t b = 2. * v_seg.dot(v_cntr);
coordf_t c = v_cntr.squaredNorm() - circle_distance * circle_distance;

View file

@ -1,6 +1,9 @@
#include "TriangleMesh.hpp"
#include "ClipperUtils.hpp"
#include "Geometry.hpp"
#include "qhull/src/libqhullcpp/Qhull.h"
#include "qhull/src/libqhullcpp/QhullFacetList.h"
#include "qhull/src/libqhullcpp/QhullVertexSet.h"
#include <cmath>
#include <deque>
#include <queue>
@ -15,6 +18,8 @@
#include <tbb/parallel_for.h>
#include <Eigen/Dense>
#if 0
#define DEBUG
#define _DEBUG
@ -30,13 +35,7 @@
namespace Slic3r {
TriangleMesh::TriangleMesh()
: repaired(false)
{
stl_initialize(&this->stl);
}
TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Point3>& facets )
TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& facets )
: repaired(false)
{
stl_initialize(&this->stl);
@ -51,51 +50,22 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Point3>& fa
for (int i = 0; i < stl.stats.number_of_facets; i++) {
stl_facet facet;
const Pointf3& ref_f1 = points[facets[i](0)];
facet.vertex[0].x = ref_f1(0);
facet.vertex[0].y = ref_f1(1);
facet.vertex[0].z = ref_f1(2);
const Pointf3& ref_f2 = points[facets[i](1)];
facet.vertex[1].x = ref_f2(0);
facet.vertex[1].y = ref_f2(1);
facet.vertex[1].z = ref_f2(2);
const Pointf3& ref_f3 = points[facets[i](2)];
facet.vertex[2].x = ref_f3(0);
facet.vertex[2].y = ref_f3(1);
facet.vertex[2].z = ref_f3(2);
facet.vertex[0] = points[facets[i](0)].cast<float>();
facet.vertex[1] = points[facets[i](1)].cast<float>();
facet.vertex[2] = points[facets[i](2)].cast<float>();
facet.extra[0] = 0;
facet.extra[1] = 0;
float normal[3];
stl_normal normal;
stl_calculate_normal(normal, &facet);
stl_normalize_vector(normal);
facet.normal.x = normal[0];
facet.normal.y = normal[1];
facet.normal.z = normal[2];
facet.normal = normal;
stl.facet_start[i] = facet;
}
stl_get_size(&stl);
}
TriangleMesh::TriangleMesh(const TriangleMesh &other) :
repaired(false)
{
stl_initialize(&this->stl);
*this = other;
}
TriangleMesh::TriangleMesh(TriangleMesh &&other) :
repaired(false)
{
stl_initialize(&this->stl);
this->swap(other);
}
TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other)
{
stl_close(&this->stl);
@ -123,42 +93,8 @@ TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other)
return *this;
}
TriangleMesh& TriangleMesh::operator=(TriangleMesh &&other)
void TriangleMesh::repair()
{
this->swap(other);
return *this;
}
void
TriangleMesh::swap(TriangleMesh &other)
{
std::swap(this->stl, other.stl);
std::swap(this->repaired, other.repaired);
}
TriangleMesh::~TriangleMesh() {
stl_close(&this->stl);
}
void
TriangleMesh::ReadSTLFile(const char* input_file) {
stl_open(&stl, input_file);
}
void
TriangleMesh::write_ascii(const char* output_file)
{
stl_write_ascii(&this->stl, output_file, "");
}
void
TriangleMesh::write_binary(const char* output_file)
{
stl_write_binary(&this->stl, output_file, "");
}
void
TriangleMesh::repair() {
if (this->repaired) return;
// admesh fails when repairing empty meshes
@ -255,13 +191,7 @@ void TriangleMesh::check_topology()
}
}
bool TriangleMesh::is_manifold() const
{
return this->stl.stats.connected_facets_3_edge == this->stl.stats.number_of_facets;
}
void
TriangleMesh::reset_repair_stats() {
void TriangleMesh::reset_repair_stats() {
this->stl.stats.degenerate_facets = 0;
this->stl.stats.edges_fixed = 0;
this->stl.stats.facets_removed = 0;
@ -271,8 +201,7 @@ TriangleMesh::reset_repair_stats() {
this->stl.stats.normals_fixed = 0;
}
bool
TriangleMesh::needed_repair() const
bool TriangleMesh::needed_repair() const
{
return this->stl.stats.degenerate_facets > 0
|| this->stl.stats.edges_fixed > 0
@ -282,14 +211,8 @@ TriangleMesh::needed_repair() const
|| this->stl.stats.backwards_edges > 0;
}
size_t
TriangleMesh::facets_count() const
void TriangleMesh::WriteOBJFile(char* output_file)
{
return this->stl.stats.number_of_facets;
}
void
TriangleMesh::WriteOBJFile(char* output_file) {
stl_generate_shared_vertices(&stl);
stl_write_obj(&stl, output_file);
}
@ -300,13 +223,9 @@ void TriangleMesh::scale(float factor)
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::scale(const Pointf3 &versor)
void TriangleMesh::scale(const Vec3d &versor)
{
float fversor[3];
fversor[0] = versor(0);
fversor[1] = versor(1);
fversor[2] = versor(2);
stl_scale_versor(&this->stl, fversor);
stl_scale_versor(&this->stl, versor.cast<float>());
stl_invalidate_shared_vertices(&this->stl);
}
@ -336,21 +255,6 @@ void TriangleMesh::rotate(float angle, const Axis &axis)
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::rotate_x(float angle)
{
this->rotate(angle, X);
}
void TriangleMesh::rotate_y(float angle)
{
this->rotate(angle, Y);
}
void TriangleMesh::rotate_z(float angle)
{
this->rotate(angle, Z);
}
void TriangleMesh::mirror(const Axis &axis)
{
if (axis == X) {
@ -363,21 +267,6 @@ void TriangleMesh::mirror(const Axis &axis)
stl_invalidate_shared_vertices(&this->stl);
}
void TriangleMesh::mirror_x()
{
this->mirror(X);
}
void TriangleMesh::mirror_y()
{
this->mirror(Y);
}
void TriangleMesh::mirror_z()
{
this->mirror(Z);
}
void TriangleMesh::transform(const float* matrix3x4)
{
if (matrix3x4 == nullptr)
@ -390,10 +279,9 @@ void TriangleMesh::transform(const float* matrix3x4)
void TriangleMesh::align_to_origin()
{
this->translate(
-(this->stl.stats.min.x),
-(this->stl.stats.min.y),
-(this->stl.stats.min.z)
);
- this->stl.stats.min(0),
- this->stl.stats.min(1),
- this->stl.stats.min(2));
}
void TriangleMesh::rotate(double angle, Point* center)
@ -476,14 +364,14 @@ size_t TriangleMesh::number_of_patches() const
return num_bodies;
}
TriangleMeshPtrs
TriangleMesh::split() const
TriangleMeshPtrs TriangleMesh::split() const
{
TriangleMeshPtrs meshes;
std::set<int> seen_facets;
TriangleMeshPtrs meshes;
std::vector<unsigned char> facet_visited(this->stl.stats.number_of_facets, false);
// we need neighbors
if (!this->repaired) CONFESS("split() requires repair()");
if (!this->repaired)
CONFESS("split() requires repair()");
// loop while we have remaining facets
for (;;) {
@ -491,25 +379,26 @@ TriangleMesh::split() const
std::queue<int> facet_queue;
std::deque<int> facets;
for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) {
if (seen_facets.find(facet_idx) == seen_facets.end()) {
if (! facet_visited[facet_idx]) {
// if facet was not seen put it into queue and start searching
facet_queue.push(facet_idx);
break;
}
}
if (facet_queue.empty()) break;
while (!facet_queue.empty()) {
if (facet_queue.empty())
break;
while (! facet_queue.empty()) {
int facet_idx = facet_queue.front();
facet_queue.pop();
if (seen_facets.find(facet_idx) != seen_facets.end()) continue;
facets.emplace_back(facet_idx);
for (int j = 0; j <= 2; j++) {
facet_queue.push(this->stl.neighbors_start[facet_idx].neighbor[j]);
if (! facet_visited[facet_idx]) {
facets.emplace_back(facet_idx);
for (int j = 0; j < 3; ++ j)
facet_queue.push(this->stl.neighbors_start[facet_idx].neighbor[j]);
facet_visited[facet_idx] = true;
}
seen_facets.insert(facet_idx);
}
TriangleMesh* mesh = new TriangleMesh;
meshes.emplace_back(mesh);
mesh->stl.stats.type = inmemory;
@ -518,19 +407,17 @@ TriangleMesh::split() const
stl_clear_error(&mesh->stl);
stl_allocate(&mesh->stl);
int first = 1;
for (std::deque<int>::const_iterator facet = facets.begin(); facet != facets.end(); ++facet) {
bool first = true;
for (std::deque<int>::const_iterator facet = facets.begin(); facet != facets.end(); ++ facet) {
mesh->stl.facet_start[facet - facets.begin()] = this->stl.facet_start[*facet];
stl_facet_stats(&mesh->stl, this->stl.facet_start[*facet], first);
first = 0;
}
}
return meshes;
}
void
TriangleMesh::merge(const TriangleMesh &mesh)
void TriangleMesh::merge(const TriangleMesh &mesh)
{
// reset stats and metadata
int number_of_facets = this->stl.stats.number_of_facets;
@ -561,9 +448,9 @@ ExPolygons TriangleMesh::horizontal_projection() const
stl_facet* facet = &this->stl.facet_start[i];
Polygon p;
p.points.resize(3);
p.points[0] = Point::new_scale(facet->vertex[0].x, facet->vertex[0].y);
p.points[1] = Point::new_scale(facet->vertex[1].x, facet->vertex[1].y);
p.points[2] = Point::new_scale(facet->vertex[2].x, facet->vertex[2].y);
p.points[0] = Point::new_scale(facet->vertex[0](0), facet->vertex[0](1));
p.points[1] = Point::new_scale(facet->vertex[1](0), facet->vertex[1](1));
p.points[2] = Point::new_scale(facet->vertex[2](0), facet->vertex[2](1));
p.make_counter_clockwise(); // do this after scaling, as winding order might change while doing that
pp.emplace_back(p);
}
@ -578,28 +465,142 @@ Polygon TriangleMesh::convex_hull()
Points pp;
pp.reserve(this->stl.stats.shared_vertices);
for (int i = 0; i < this->stl.stats.shared_vertices; ++ i) {
stl_vertex* v = &this->stl.v_shared[i];
pp.emplace_back(Point::new_scale(v->x, v->y));
const stl_vertex &v = this->stl.v_shared[i];
pp.emplace_back(Point::new_scale(v(0), v(1)));
}
return Slic3r::Geometry::convex_hull(pp);
}
BoundingBoxf3
TriangleMesh::bounding_box() const
BoundingBoxf3 TriangleMesh::bounding_box() const
{
BoundingBoxf3 bb;
bb.defined = true;
bb.min(0) = this->stl.stats.min.x;
bb.min(1) = this->stl.stats.min.y;
bb.min(2) = this->stl.stats.min.z;
bb.max(0) = this->stl.stats.max.x;
bb.max(1) = this->stl.stats.max.y;
bb.max(2) = this->stl.stats.max.z;
bb.min = this->stl.stats.min.cast<double>();
bb.max = this->stl.stats.max.cast<double>();
return bb;
}
void
TriangleMesh::require_shared_vertices()
BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d& t) const
{
bool has_shared = (stl.v_shared != nullptr);
if (!has_shared)
stl_generate_shared_vertices(&stl);
unsigned int vertices_count = (stl.stats.shared_vertices > 0) ? (unsigned int)stl.stats.shared_vertices : 3 * (unsigned int)stl.stats.number_of_facets;
if (vertices_count == 0)
return BoundingBoxf3();
Eigen::MatrixXd src_vertices(3, vertices_count);
if (stl.stats.shared_vertices > 0)
{
stl_vertex* vertex_ptr = stl.v_shared;
for (int i = 0; i < stl.stats.shared_vertices; ++i)
{
src_vertices(0, i) = (double)(*vertex_ptr)(0);
src_vertices(1, i) = (double)(*vertex_ptr)(1);
src_vertices(2, i) = (double)(*vertex_ptr)(2);
vertex_ptr += 1;
}
}
else
{
stl_facet* facet_ptr = stl.facet_start;
unsigned int v_id = 0;
while (facet_ptr < stl.facet_start + stl.stats.number_of_facets)
{
for (int i = 0; i < 3; ++i)
{
src_vertices(0, v_id) = (double)facet_ptr->vertex[i](0);
src_vertices(1, v_id) = (double)facet_ptr->vertex[i](1);
src_vertices(2, v_id) = (double)facet_ptr->vertex[i](2);
}
facet_ptr += 1;
++v_id;
}
}
if (!has_shared && (stl.stats.shared_vertices > 0))
stl_invalidate_shared_vertices(&stl);
Eigen::MatrixXd dst_vertices(3, vertices_count);
dst_vertices = t * src_vertices.colwise().homogeneous();
Vec3d v_min(dst_vertices(0, 0), dst_vertices(1, 0), dst_vertices(2, 0));
Vec3d v_max = v_min;
for (int i = 1; i < vertices_count; ++i)
{
for (int j = 0; j < 3; ++j)
{
v_min(j) = std::min(v_min(j), dst_vertices(j, i));
v_max(j) = std::max(v_max(j), dst_vertices(j, i));
}
}
return BoundingBoxf3(v_min, v_max);
}
TriangleMesh TriangleMesh::convex_hull_3d() const
{
// Helper struct for qhull:
struct PointForQHull{
PointForQHull(float x_p, float y_p, float z_p) : x((realT)x_p), y((realT)y_p), z((realT)z_p) {}
realT x, y, z;
};
std::vector<PointForQHull> src_vertices;
// We will now fill the vector with input points for computation:
stl_facet* facet_ptr = stl.facet_start;
while (facet_ptr < stl.facet_start + stl.stats.number_of_facets)
{
for (int i = 0; i < 3; ++i)
{
const stl_vertex& v = facet_ptr->vertex[i];
src_vertices.emplace_back(v(0), v(1), v(2));
}
facet_ptr += 1;
}
// The qhull call:
orgQhull::Qhull qhull;
qhull.disableOutputStream(); // we want qhull to be quiet
try
{
qhull.runQhull("", 3, (int)src_vertices.size(), (const realT*)(src_vertices.data()), "Qt");
}
catch (...)
{
std::cout << "Unable to create convex hull" << std::endl;
return TriangleMesh();
}
// Let's collect results:
Pointf3s dst_vertices;
std::vector<Vec3crd> facets;
auto facet_list = qhull.facetList().toStdVector();
for (const orgQhull::QhullFacet& facet : facet_list)
{ // iterate through facets
orgQhull::QhullVertexSet vertices = facet.vertices();
for (int i = 0; i < 3; ++i)
{ // iterate through facet's vertices
orgQhull::QhullPoint p = vertices[i].point();
const float* coords = p.coordinates();
dst_vertices.emplace_back(coords[0], coords[1], coords[2]);
}
unsigned int size = (unsigned int)dst_vertices.size();
facets.emplace_back(size - 3, size - 2, size - 1);
}
TriangleMesh output_mesh(dst_vertices, facets);
output_mesh.repair();
return output_mesh;
}
void TriangleMesh::require_shared_vertices()
{
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - start";
if (!this->repaired)
@ -619,11 +620,8 @@ TriangleMeshSlicer::TriangleMeshSlicer(TriangleMesh* _mesh) :
facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1);
v_scaled_shared.assign(_mesh->stl.v_shared, _mesh->stl.v_shared + _mesh->stl.stats.shared_vertices);
// Scale the copied vertices.
for (int i = 0; i < this->mesh->stl.stats.shared_vertices; ++ i) {
this->v_scaled_shared[i].x /= float(SCALING_FACTOR);
this->v_scaled_shared[i].y /= float(SCALING_FACTOR);
this->v_scaled_shared[i].z /= float(SCALING_FACTOR);
}
for (int i = 0; i < this->mesh->stl.stats.shared_vertices; ++ i)
this->v_scaled_shared[i] *= float(1. / SCALING_FACTOR);
// Create a mapping from triangle edge into face.
struct EdgeToFace {
@ -697,8 +695,7 @@ TriangleMeshSlicer::TriangleMeshSlicer(TriangleMesh* _mesh) :
}
}
void
TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons>* layers) const
void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons>* layers) const
{
BOOST_LOG_TRIVIAL(debug) << "TriangleMeshSlicer::slice";
@ -779,14 +776,14 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLin
const stl_facet &facet = this->mesh->stl.facet_start[facet_idx];
// find facet extents
const float min_z = fminf(facet.vertex[0].z, fminf(facet.vertex[1].z, facet.vertex[2].z));
const float max_z = fmaxf(facet.vertex[0].z, fmaxf(facet.vertex[1].z, facet.vertex[2].z));
const float min_z = fminf(facet.vertex[0](2), fminf(facet.vertex[1](2), facet.vertex[2](2)));
const float max_z = fmaxf(facet.vertex[0](2), fmaxf(facet.vertex[1](2), facet.vertex[2](2)));
#ifdef SLIC3R_DEBUG
printf("\n==> FACET %d (%f,%f,%f - %f,%f,%f - %f,%f,%f):\n", facet_idx,
facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0].z,
facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1].z,
facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2].z);
facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0](2),
facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1](2),
facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2](2));
printf("z: min = %.2f, max = %.2f\n", min_z, max_z);
#endif
@ -806,18 +803,18 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLin
if (il.edge_type == feHorizontal) {
// Insert all three edges of the face.
const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex;
const bool reverse = this->mesh->stl.facet_start[facet_idx].normal.z < 0;
const bool reverse = this->mesh->stl.facet_start[facet_idx].normal(2) < 0;
for (int j = 0; j < 3; ++ j) {
int a_id = vertices[j % 3];
int b_id = vertices[(j+1) % 3];
if (reverse)
std::swap(a_id, b_id);
const stl_vertex *a = &this->v_scaled_shared[a_id];
const stl_vertex *b = &this->v_scaled_shared[b_id];
il.a(0) = a->x;
il.a(1) = a->y;
il.b(0) = b->x;
il.b(1) = b->y;
const stl_vertex &a = this->v_scaled_shared[a_id];
const stl_vertex &b = this->v_scaled_shared[b_id];
il.a(0) = a(0);
il.a(1) = a(1);
il.b(0) = b(0);
il.b(1) = b(1);
il.a_id = a_id;
il.b_id = b_id;
(*lines)[layer_idx].emplace_back(il);
@ -863,66 +860,63 @@ bool TriangleMeshSlicer::slice_facet(
// Reorder vertices so that the first one is the one with lowest Z.
// This is needed to get all intersection lines in a consistent order
// (external on the right of the line)
int i = (facet.vertex[1].z == min_z) ? 1 : ((facet.vertex[2].z == min_z) ? 2 : 0);
int i = (facet.vertex[1](2) == min_z) ? 1 : ((facet.vertex[2](2) == min_z) ? 2 : 0);
for (int j = i; j - i < 3; ++ j) { // loop through facet edges
int edge_id = this->facets_edges[facet_idx * 3 + (j % 3)];
const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex;
int a_id = vertices[j % 3];
int b_id = vertices[(j+1) % 3];
const stl_vertex *a = &this->v_scaled_shared[a_id];
const stl_vertex *b = &this->v_scaled_shared[b_id];
const stl_vertex &a = this->v_scaled_shared[a_id];
const stl_vertex &b = this->v_scaled_shared[b_id];
// Is edge or face aligned with the cutting plane?
if (a->z == slice_z && b->z == slice_z) {
if (a(2) == slice_z && b(2) == slice_z) {
// Edge is horizontal and belongs to the current layer.
const stl_vertex &v0 = this->v_scaled_shared[vertices[0]];
const stl_vertex &v1 = this->v_scaled_shared[vertices[1]];
const stl_vertex &v2 = this->v_scaled_shared[vertices[2]];
bool swap = false;
if (min_z == max_z) {
// All three vertices are aligned with slice_z.
line_out->edge_type = feHorizontal;
if (this->mesh->stl.facet_start[facet_idx].normal.z < 0) {
if (this->mesh->stl.facet_start[facet_idx].normal(2) < 0) {
// If normal points downwards this is a bottom horizontal facet so we reverse its point order.
std::swap(a, b);
std::swap(a_id, b_id);
swap = true;
}
} else if (v0.z < slice_z || v1.z < slice_z || v2.z < slice_z) {
} else if (v0(2) < slice_z || v1(2) < slice_z || v2(2) < slice_z) {
// Two vertices are aligned with the cutting plane, the third vertex is below the cutting plane.
line_out->edge_type = feTop;
std::swap(a, b);
std::swap(a_id, b_id);
swap = true;
} else {
// Two vertices are aligned with the cutting plane, the third vertex is above the cutting plane.
line_out->edge_type = feBottom;
}
line_out->a(0) = a->x;
line_out->a(1) = a->y;
line_out->b(0) = b->x;
line_out->b(1) = b->y;
line_out->a_id = a_id;
line_out->b_id = b_id;
line_out->a = to_2d(swap ? b : a).cast<coord_t>();
line_out->b = to_2d(swap ? a : b).cast<coord_t>();
line_out->a_id = swap ? b_id : a_id;
line_out->b_id = swap ? a_id : b_id;
return true;
}
if (a->z == slice_z) {
if (a(2) == slice_z) {
// Only point a alings with the cutting plane.
points_on_layer[num_points_on_layer ++] = num_points;
IntersectionPoint &point = points[num_points ++];
point(0) = a->x;
point(1) = a->y;
point(0) = a(0);
point(1) = a(1);
point.point_id = a_id;
} else if (b->z == slice_z) {
} else if (b(2) == slice_z) {
// Only point b alings with the cutting plane.
points_on_layer[num_points_on_layer ++] = num_points;
IntersectionPoint &point = points[num_points ++];
point(0) = b->x;
point(1) = b->y;
point(0) = b(0);
point(1) = b(1);
point.point_id = b_id;
} else if ((a->z < slice_z && b->z > slice_z) || (b->z < slice_z && a->z > slice_z)) {
} else if ((a(2) < slice_z && b(2) > slice_z) || (b(2) < slice_z && a(2) > slice_z)) {
// A general case. The face edge intersects the cutting plane. Calculate the intersection point.
IntersectionPoint &point = points[num_points ++];
point(0) = b->x + (a->x - b->x) * (slice_z - b->z) / (a->z - b->z);
point(1) = b->y + (a->y - b->y) * (slice_z - b->z) / (a->z - b->z);
point(0) = b(0) + (a(0) - b(0)) * (slice_z - b(2)) / (a(2) - b(2));
point(1) = b(1) + (a(1) - b(1)) * (slice_z - b(2)) / (a(2) - b(2));
point.edge_id = edge_id;
}
}
@ -1389,8 +1383,8 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
stl_facet* facet = &this->mesh->stl.facet_start[facet_idx];
// find facet extents
float min_z = std::min(facet->vertex[0].z, std::min(facet->vertex[1].z, facet->vertex[2].z));
float max_z = std::max(facet->vertex[0].z, std::max(facet->vertex[1].z, facet->vertex[2].z));
float min_z = std::min(facet->vertex[0](2), std::min(facet->vertex[1](2), facet->vertex[2](2)));
float max_z = std::max(facet->vertex[0](2), std::max(facet->vertex[1](2), facet->vertex[2](2)));
// intersect facet with cutting plane
IntersectionLine line;
@ -1417,47 +1411,47 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
// look for the vertex on whose side of the slicing plane there are no other vertices
int isolated_vertex;
if ( (facet->vertex[0].z > z) == (facet->vertex[1].z > z) ) {
if ( (facet->vertex[0](2) > z) == (facet->vertex[1](2) > z) ) {
isolated_vertex = 2;
} else if ( (facet->vertex[1].z > z) == (facet->vertex[2].z > z) ) {
} else if ( (facet->vertex[1](2) > z) == (facet->vertex[2](2) > z) ) {
isolated_vertex = 0;
} else {
isolated_vertex = 1;
}
// get vertices starting from the isolated one
stl_vertex* v0 = &facet->vertex[isolated_vertex];
stl_vertex* v1 = &facet->vertex[(isolated_vertex+1) % 3];
stl_vertex* v2 = &facet->vertex[(isolated_vertex+2) % 3];
const stl_vertex &v0 = facet->vertex[isolated_vertex];
const stl_vertex &v1 = facet->vertex[(isolated_vertex+1) % 3];
const stl_vertex &v2 = facet->vertex[(isolated_vertex+2) % 3];
// intersect v0-v1 and v2-v0 with cutting plane and make new vertices
stl_vertex v0v1, v2v0;
v0v1.x = v1->x + (v0->x - v1->x) * (z - v1->z) / (v0->z - v1->z);
v0v1.y = v1->y + (v0->y - v1->y) * (z - v1->z) / (v0->z - v1->z);
v0v1.z = z;
v2v0.x = v2->x + (v0->x - v2->x) * (z - v2->z) / (v0->z - v2->z);
v2v0.y = v2->y + (v0->y - v2->y) * (z - v2->z) / (v0->z - v2->z);
v2v0.z = z;
v0v1(0) = v1(0) + (v0(0) - v1(0)) * (z - v1(2)) / (v0(2) - v1(2));
v0v1(1) = v1(1) + (v0(1) - v1(1)) * (z - v1(2)) / (v0(2) - v1(2));
v0v1(2) = z;
v2v0(0) = v2(0) + (v0(0) - v2(0)) * (z - v2(2)) / (v0(2) - v2(2));
v2v0(1) = v2(1) + (v0(1) - v2(1)) * (z - v2(2)) / (v0(2) - v2(2));
v2v0(2) = z;
// build the triangular facet
stl_facet triangle;
triangle.normal = facet->normal;
triangle.vertex[0] = *v0;
triangle.vertex[0] = v0;
triangle.vertex[1] = v0v1;
triangle.vertex[2] = v2v0;
// build the facets forming a quadrilateral on the other side
stl_facet quadrilateral[2];
quadrilateral[0].normal = facet->normal;
quadrilateral[0].vertex[0] = *v1;
quadrilateral[0].vertex[1] = *v2;
quadrilateral[0].vertex[0] = v1;
quadrilateral[0].vertex[1] = v2;
quadrilateral[0].vertex[2] = v0v1;
quadrilateral[1].normal = facet->normal;
quadrilateral[1].vertex[0] = *v2;
quadrilateral[1].vertex[0] = v2;
quadrilateral[1].vertex[1] = v2v0;
quadrilateral[1].vertex[2] = v0v1;
if (v0->z > z) {
if (v0(2) > z) {
if (upper != NULL) stl_add_facet(&upper->stl, &triangle);
if (lower != NULL) {
stl_add_facet(&lower->stl, &quadrilateral[0]);
@ -1489,13 +1483,11 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
Polygon p = *polygon;
p.reverse();
stl_facet facet;
facet.normal.x = 0;
facet.normal.y = 0;
facet.normal.z = -1;
facet.normal = stl_normal(0, 0, -1.f);
for (size_t i = 0; i <= 2; ++i) {
facet.vertex[i].x = unscale(p.points[i](0));
facet.vertex[i].y = unscale(p.points[i](1));
facet.vertex[i].z = z;
facet.vertex[i](0) = unscale<float>(p.points[i](0));
facet.vertex[i](1) = unscale<float>(p.points[i](1));
facet.vertex[i](2) = z;
}
stl_add_facet(&upper->stl, &facet);
}
@ -1515,13 +1507,11 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
// convert triangles to facets and append them to mesh
for (Polygons::const_iterator polygon = triangles.begin(); polygon != triangles.end(); ++polygon) {
stl_facet facet;
facet.normal.x = 0;
facet.normal.y = 0;
facet.normal.z = 1;
facet.normal = stl_normal(0, 0, 1.f);
for (size_t i = 0; i <= 2; ++i) {
facet.vertex[i].x = unscale(polygon->points[i](0));
facet.vertex[i].y = unscale(polygon->points[i](1));
facet.vertex[i].z = z;
facet.vertex[i](0) = unscale<float>(polygon->points[i](0));
facet.vertex[i](1) = unscale<float>(polygon->points[i](1));
facet.vertex[i](2) = z;
}
stl_add_facet(&lower->stl, &facet);
}
@ -1534,19 +1524,19 @@ 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) {
Pointf3 pv[8] = {
Pointf3(x, y, 0), Pointf3(x, 0, 0), Pointf3(0, 0, 0),
Pointf3(0, y, 0), Pointf3(x, y, z), Pointf3(0, y, z),
Pointf3(0, 0, z), Pointf3(x, 0, 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),
Vec3d(0, 0, z), Vec3d(x, 0, z)
};
Point3 fv[12] = {
Point3(0, 1, 2), Point3(0, 2, 3), Point3(4, 5, 6),
Point3(4, 6, 7), Point3(0, 4, 7), Point3(0, 7, 1),
Point3(1, 7, 6), Point3(1, 6, 2), Point3(2, 6, 5),
Point3(2, 5, 3), Point3(4, 0, 3), Point3(4, 3, 5)
Vec3crd fv[12] = {
Vec3crd(0, 1, 2), Vec3crd(0, 2, 3), Vec3crd(4, 5, 6),
Vec3crd(4, 6, 7), Vec3crd(0, 4, 7), Vec3crd(0, 7, 1),
Vec3crd(1, 7, 6), Vec3crd(1, 6, 2), Vec3crd(2, 6, 5),
Vec3crd(2, 5, 3), Vec3crd(4, 0, 3), Vec3crd(4, 3, 5)
};
std::vector<Point3> facets(&fv[0], &fv[0]+12);
std::vector<Vec3crd> facets(&fv[0], &fv[0]+12);
Pointf3s vertices(&pv[0], &pv[0]+8);
TriangleMesh mesh(vertices ,facets);
@ -1558,11 +1548,11 @@ TriangleMesh make_cube(double x, double y, double z) {
// Default is 360 sides, angle fa is in radians.
TriangleMesh make_cylinder(double r, double h, double fa) {
Pointf3s vertices;
std::vector<Point3> facets;
std::vector<Vec3crd> facets;
// 2 special vertices, top and bottom center, rest are relative to this
vertices.emplace_back(Pointf3(0.0, 0.0, 0.0));
vertices.emplace_back(Pointf3(0.0, 0.0, h));
vertices.emplace_back(Vec3d(0.0, 0.0, 0.0));
vertices.emplace_back(Vec3d(0.0, 0.0, h));
// adjust via rounding to get an even multiple for any provided angle.
double angle = (2*PI / floor(2*PI / fa));
@ -1572,24 +1562,23 @@ TriangleMesh make_cylinder(double r, double h, double fa) {
// top and bottom.
// Special case: Last line shares 2 vertices with the first line.
unsigned id = vertices.size() - 1;
vertices.emplace_back(Pointf3(sin(0) * r , cos(0) * r, 0));
vertices.emplace_back(Pointf3(sin(0) * r , cos(0) * r, h));
vertices.emplace_back(Vec3d(sin(0) * r , cos(0) * r, 0));
vertices.emplace_back(Vec3d(sin(0) * r , cos(0) * r, h));
for (double i = 0; i < 2*PI; i+=angle) {
Pointf p(0, r);
p.rotate(i);
vertices.emplace_back(Pointf3(p(0), p(1), 0.));
vertices.emplace_back(Pointf3(p(0), p(1), h));
Vec2d p = Eigen::Rotation2Dd(i) * Eigen::Vector2d(0, r);
vertices.emplace_back(Vec3d(p(0), p(1), 0.));
vertices.emplace_back(Vec3d(p(0), p(1), h));
id = vertices.size() - 1;
facets.emplace_back(Point3( 0, id - 1, id - 3)); // top
facets.emplace_back(Point3(id, 1, id - 2)); // bottom
facets.emplace_back(Point3(id, id - 2, id - 3)); // upper-right of side
facets.emplace_back(Point3(id, id - 3, id - 1)); // bottom-left of side
facets.emplace_back(Vec3crd( 0, id - 1, id - 3)); // top
facets.emplace_back(Vec3crd(id, 1, id - 2)); // bottom
facets.emplace_back(Vec3crd(id, id - 2, id - 3)); // upper-right of side
facets.emplace_back(Vec3crd(id, id - 3, id - 1)); // bottom-left of side
}
// Connect the last set of vertices with the first.
facets.emplace_back(Point3( 2, 0, id - 1));
facets.emplace_back(Point3( 1, 3, id));
facets.emplace_back(Point3(id, 3, 2));
facets.emplace_back(Point3(id, 2, id - 1));
facets.emplace_back(Vec3crd( 2, 0, id - 1));
facets.emplace_back(Vec3crd( 1, 3, id));
facets.emplace_back(Vec3crd(id, 3, 2));
facets.emplace_back(Vec3crd(id, 2, id - 1));
TriangleMesh mesh(vertices, facets);
return mesh;
@ -1600,7 +1589,7 @@ TriangleMesh make_cylinder(double r, double h, double fa) {
// Default angle is 1 degree.
TriangleMesh make_sphere(double rho, double fa) {
Pointf3s vertices;
std::vector<Point3> facets;
std::vector<Vec3crd> facets;
// Algorithm:
// Add points one-by-one to the sphere grid and form facets using relative coordinates.
@ -1619,17 +1608,16 @@ TriangleMesh make_sphere(double rho, double fa) {
// special case: first ring connects to 0,0,0
// insert and form facets.
vertices.emplace_back(Pointf3(0.0, 0.0, -rho));
vertices.emplace_back(Vec3d(0.0, 0.0, -rho));
size_t id = vertices.size();
for (size_t i = 0; i < ring.size(); i++) {
// Fixed scaling
const double z = -rho + increment*rho*2.0;
// radius of the circle for this step.
const double r = sqrt(abs(rho*rho - z*z));
Pointf b(0, r);
b.rotate(ring[i]);
vertices.emplace_back(Pointf3(b(0), b(1), z));
facets.emplace_back((i == 0) ? Point3(1, 0, ring.size()) : Point3(id, 0, id - 1));
Vec2d b = Eigen::Rotation2Dd(ring[i]) * Eigen::Vector2d(0, r);
vertices.emplace_back(Vec3d(b(0), b(1), z));
facets.emplace_back((i == 0) ? Vec3crd(1, 0, ring.size()) : Vec3crd(id, 0, id - 1));
++ id;
}
@ -1639,16 +1627,15 @@ TriangleMesh make_sphere(double rho, double fa) {
const double r = sqrt(abs(rho*rho - z*z));
for (size_t i = 0; i < ring.size(); i++) {
Pointf b(0, r);
b.rotate(ring[i]);
vertices.emplace_back(Pointf3(b(0), b(1), z));
Vec2d b = Eigen::Rotation2Dd(ring[i]) * Eigen::Vector2d(0, r);
vertices.emplace_back(Vec3d(b(0), b(1), z));
if (i == 0) {
// wrap around
facets.emplace_back(Point3(id + ring.size() - 1 , id, id - 1));
facets.emplace_back(Point3(id, id - ring.size(), id - 1));
facets.emplace_back(Vec3crd(id + ring.size() - 1 , id, id - 1));
facets.emplace_back(Vec3crd(id, id - ring.size(), id - 1));
} else {
facets.emplace_back(Point3(id , id - ring.size(), (id - 1) - ring.size()));
facets.emplace_back(Point3(id, id - 1 - ring.size() , id - 1));
facets.emplace_back(Vec3crd(id , id - ring.size(), (id - 1) - ring.size()));
facets.emplace_back(Vec3crd(id, id - 1 - ring.size() , id - 1));
}
id++;
}
@ -1657,13 +1644,13 @@ TriangleMesh make_sphere(double rho, double fa) {
// special case: last ring connects to 0,0,rho*2.0
// only form facets.
vertices.emplace_back(Pointf3(0.0, 0.0, rho));
vertices.emplace_back(Vec3d(0.0, 0.0, rho));
for (size_t i = 0; i < ring.size(); i++) {
if (i == 0) {
// third vertex is on the other side of the ring.
facets.emplace_back(Point3(id, id - ring.size(), id - 1));
facets.emplace_back(Vec3crd(id, id - ring.size(), id - 1));
} else {
facets.emplace_back(Point3(id, id - ring.size() + i, id - ring.size() + (i - 1)));
facets.emplace_back(Vec3crd(id, id - ring.size() + i, id - ring.size() + (i - 1)));
}
}
id++;

View file

@ -20,33 +20,33 @@ typedef std::vector<TriangleMesh*> TriangleMeshPtrs;
class TriangleMesh
{
public:
TriangleMesh();
TriangleMesh(const Pointf3s &points, const std::vector<Point3> &facets);
TriangleMesh(const TriangleMesh &other);
TriangleMesh(TriangleMesh &&other);
TriangleMesh() : repaired(false) { stl_initialize(&this->stl); }
TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd> &facets);
TriangleMesh(const TriangleMesh &other) : repaired(false) { stl_initialize(&this->stl); *this = other; }
TriangleMesh(TriangleMesh &&other) : repaired(false) { stl_initialize(&this->stl); this->swap(other); }
~TriangleMesh() { stl_close(&this->stl); }
TriangleMesh& operator=(const TriangleMesh &other);
TriangleMesh& operator=(TriangleMesh &&other);
void swap(TriangleMesh &other);
~TriangleMesh();
void ReadSTLFile(const char* input_file);
void write_ascii(const char* output_file);
void write_binary(const char* output_file);
TriangleMesh& operator=(TriangleMesh &&other) { this->swap(other); return *this; }
void swap(TriangleMesh &other) { std::swap(this->stl, other.stl); std::swap(this->repaired, other.repaired); }
void ReadSTLFile(const char* input_file) { stl_open(&stl, input_file); }
void write_ascii(const char* output_file) { stl_write_ascii(&this->stl, output_file, ""); }
void write_binary(const char* output_file) { stl_write_binary(&this->stl, output_file, ""); }
void repair();
float volume();
void check_topology();
bool is_manifold() const;
bool is_manifold() const { return this->stl.stats.connected_facets_3_edge == this->stl.stats.number_of_facets; }
void WriteOBJFile(char* output_file);
void scale(float factor);
void scale(const Pointf3 &versor);
void scale(const Vec3d &versor);
void translate(float x, float y, float z);
void rotate(float angle, const Axis &axis);
void rotate_x(float angle);
void rotate_y(float angle);
void rotate_z(float angle);
void rotate_x(float angle) { this->rotate(angle, X); }
void rotate_y(float angle) { this->rotate(angle, Y); }
void rotate_z(float angle) { this->rotate(angle, Z); }
void mirror(const Axis &axis);
void mirror_x();
void mirror_y();
void mirror_z();
void mirror_x() { this->mirror(X); }
void mirror_y() { this->mirror(Y); }
void mirror_z() { this->mirror(Z); }
void transform(const float* matrix3x4);
void align_to_origin();
void rotate(double angle, Point* center);
@ -55,9 +55,13 @@ public:
ExPolygons horizontal_projection() const;
Polygon convex_hull();
BoundingBoxf3 bounding_box() const;
// Returns the bbox of this TriangleMesh transformed by the given transformation
BoundingBoxf3 transformed_bounding_box(const Transform3d& t) const;
// Returns the convex hull of this TriangleMesh
TriangleMesh convex_hull_3d() const;
void reset_repair_stats();
bool needed_repair() const;
size_t facets_count() const;
size_t facets_count() const { return this->stl.stats.number_of_facets; }
// Returns true, if there are two and more connected patches in the mesh.
// Returns false, if one or zero connected patch is in the mesh.
@ -66,7 +70,7 @@ public:
// Count disconnected triangle patches.
size_t number_of_patches() const;
stl_file stl;
mutable stl_file stl;
bool repaired;
private:

View file

@ -45,7 +45,6 @@ typedef double coordf_t;
//FIXME Better to use an inline function with an explicit return type.
//inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); }
#define scale_(val) ((val) / SCALING_FACTOR)
#define unscale(val) ((val) * SCALING_FACTOR)
#define SCALED_EPSILON scale_(EPSILON)
/* Implementation of CONFESS("foo"): */
#ifdef _MSC_VER
@ -102,6 +101,9 @@ inline std::string debug_out_path(const char *name, ...)
namespace Slic3r {
template<typename T, typename Q>
inline T unscale(Q v) { return T(v) * T(SCALING_FACTOR); }
enum Axis { X=0, Y, Z, E, F, NUM_AXES };
template <class T>