Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/xs/src
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2016-09-13 14:30:00 +0300
committerbubnikv <bubnikv@gmail.com>2016-09-13 14:30:00 +0300
commit620c6c7378c4799980f63794669548c104b9bcea (patch)
treefc7aea3342539018bb19d27abd1144956eb00b4d /xs/src
parenta5b7f14dfa291039fd6971a356efd011fab84440 (diff)
Ported from the playground branch. Various documentation and optimization.
Diffstat (limited to 'xs/src')
-rw-r--r--xs/src/libslic3r/BoundingBox.cpp40
-rw-r--r--xs/src/libslic3r/BoundingBox.hpp10
-rw-r--r--xs/src/libslic3r/ClipperUtils.cpp27
-rw-r--r--xs/src/libslic3r/ClipperUtils.hpp5
-rw-r--r--xs/src/libslic3r/Config.cpp15
-rw-r--r--xs/src/libslic3r/Config.hpp92
-rw-r--r--xs/src/libslic3r/ExPolygon.cpp16
-rw-r--r--xs/src/libslic3r/ExPolygon.hpp5
-rw-r--r--xs/src/libslic3r/ExPolygonCollection.cpp5
-rw-r--r--xs/src/libslic3r/ExPolygonCollection.hpp2
-rw-r--r--xs/src/libslic3r/ExtrusionSimulator.cpp8
-rw-r--r--xs/src/libslic3r/ExtrusionSimulator.hpp1
-rw-r--r--xs/src/libslic3r/Fill/FillRectilinear2.cpp4
-rw-r--r--xs/src/libslic3r/GCode.hpp7
-rw-r--r--xs/src/libslic3r/Layer.cpp4
-rw-r--r--xs/src/libslic3r/LayerRegion.cpp1
-rw-r--r--xs/src/libslic3r/Model.cpp2
-rw-r--r--xs/src/libslic3r/Model.hpp59
-rw-r--r--xs/src/libslic3r/MultiPoint.cpp16
-rw-r--r--xs/src/libslic3r/MultiPoint.hpp4
-rw-r--r--xs/src/libslic3r/PerimeterGenerator.cpp6
-rw-r--r--xs/src/libslic3r/PerimeterGenerator.hpp40
-rw-r--r--xs/src/libslic3r/Point.cpp20
-rw-r--r--xs/src/libslic3r/Point.hpp2
-rw-r--r--xs/src/libslic3r/Polygon.cpp32
-rw-r--r--xs/src/libslic3r/Polygon.hpp7
-rw-r--r--xs/src/libslic3r/Print.cpp3
-rw-r--r--xs/src/libslic3r/Print.hpp5
-rw-r--r--xs/src/libslic3r/PrintConfig.cpp26
-rw-r--r--xs/src/libslic3r/PrintConfig.hpp49
-rw-r--r--xs/src/libslic3r/PrintObject.cpp2
-rw-r--r--xs/src/libslic3r/SVG.cpp77
-rw-r--r--xs/src/libslic3r/SVG.hpp30
-rw-r--r--xs/src/libslic3r/Surface.cpp28
-rw-r--r--xs/src/libslic3r/Surface.hpp4
-rw-r--r--xs/src/libslic3r/libslic3r.h10
36 files changed, 574 insertions, 90 deletions
diff --git a/xs/src/libslic3r/BoundingBox.cpp b/xs/src/libslic3r/BoundingBox.cpp
index 1116d2dcb..c16d92f4e 100644
--- a/xs/src/libslic3r/BoundingBox.cpp
+++ b/xs/src/libslic3r/BoundingBox.cpp
@@ -68,6 +68,26 @@ BoundingBox::polygon() const
return p;
}
+BoundingBox BoundingBox::rotated(double angle) const
+{
+ BoundingBox out;
+ out.merge(this->min.rotated(angle));
+ out.merge(this->max.rotated(angle));
+ out.merge(Point(this->min.x, this->max.y).rotated(angle));
+ out.merge(Point(this->max.x, this->min.y).rotated(angle));
+ return out;
+}
+
+BoundingBox BoundingBox::rotated(double angle, const Point &center) const
+{
+ BoundingBox out;
+ out.merge(this->min.rotated(angle, center));
+ out.merge(this->max.rotated(angle, center));
+ out.merge(Point(this->min.x, this->max.y).rotated(angle, center));
+ out.merge(Point(this->max.x, this->min.y).rotated(angle, center));
+ return out;
+}
+
template <class PointClass> void
BoundingBoxBase<PointClass>::scale(double factor)
{
@@ -163,6 +183,26 @@ BoundingBox3Base<PointClass>::size() const
}
template Pointf3 BoundingBox3Base<Pointf3>::size() const;
+template <class PointClass> double
+BoundingBoxBase<PointClass>::radius() const
+{
+ double x = this->max.x - this->min.x;
+ double y = this->max.y - this->min.y;
+ return 0.5 * sqrt(x*x+y*y);
+}
+template double BoundingBoxBase<Point>::radius() const;
+template double BoundingBoxBase<Pointf>::radius() const;
+
+template <class PointClass> double
+BoundingBox3Base<PointClass>::radius() const
+{
+ double x = this->max.x - this->min.x;
+ double y = this->max.y - this->min.y;
+ double z = this->max.z - this->min.z;
+ return 0.5 * sqrt(x*x+y*y+z*z);
+}
+template double BoundingBox3Base<Pointf3>::radius() const;
+
template <class PointClass> void
BoundingBoxBase<PointClass>::translate(coordf_t x, coordf_t y)
{
diff --git a/xs/src/libslic3r/BoundingBox.hpp b/xs/src/libslic3r/BoundingBox.hpp
index 136ba1f8c..b4f101976 100644
--- a/xs/src/libslic3r/BoundingBox.hpp
+++ b/xs/src/libslic3r/BoundingBox.hpp
@@ -28,6 +28,7 @@ class BoundingBoxBase
void merge(const BoundingBoxBase<PointClass> &bb);
void scale(double factor);
PointClass size() const;
+ double radius() const;
void translate(coordf_t x, coordf_t y);
void offset(coordf_t delta);
PointClass center() const;
@@ -44,6 +45,7 @@ class BoundingBox3Base : public BoundingBoxBase<PointClass>
void merge(const std::vector<PointClass> &points);
void merge(const BoundingBox3Base<PointClass> &bb);
PointClass size() const;
+ double radius() const;
void translate(coordf_t x, coordf_t y, coordf_t z);
void offset(coordf_t delta);
PointClass center() const;
@@ -54,6 +56,10 @@ class BoundingBox : public BoundingBoxBase<Point>
public:
void polygon(Polygon* polygon) const;
Polygon polygon() const;
+ BoundingBox rotated(double angle) const;
+ BoundingBox rotated(double angle, const Point &center) const;
+ void rotate(double angle) { (*this) = this->rotated(angle); }
+ void rotate(double angle, const Point &center) { (*this) = this->rotated(angle, center); }
BoundingBox() : BoundingBoxBase<Point>() {};
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {};
@@ -100,7 +106,9 @@ inline bool empty(const BoundingBoxBase<VT> &bb)
template<typename VT>
inline bool empty(const BoundingBox3Base<VT> &bb)
{
- return bb.min.x > bb.max.x || bb.min.y > bb.max.y || bb.min.z > bb.max.z;}
+ return bb.min.x > bb.max.x || bb.min.y > bb.max.y || bb.min.z > bb.max.z;
}
+} // namespace Slic3r
+
#endif
diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp
index a1297e574..af4070f58 100644
--- a/xs/src/libslic3r/ClipperUtils.cpp
+++ b/xs/src/libslic3r/ClipperUtils.cpp
@@ -1,6 +1,12 @@
#include "ClipperUtils.hpp"
#include "Geometry.hpp"
+// #define CLIPPER_UTILS_DEBUG
+
+#ifdef CLIPPER_UTILS_DEBUG
+#include "SVG.hpp"
+#endif /* CLIPPER_UTILS_DEBUG */
+
namespace Slic3r {
//-----------------------------------------------------------
@@ -226,6 +232,19 @@ void
offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
{
+#ifdef CLIPPER_UTILS_DEBUG
+ BoundingBox bbox = get_extents(polygons);
+ coordf_t stroke_width = scale_(0.005);
+ static int iRun = 0;
+ ++ iRun;
+ char path[2048];
+ sprintf(path, "out\\offset2-%d.svg", iRun);
+ bool flipY = false;
+ SVG svg(path, bbox, scale_(1.), flipY);
+ for (Slic3r::Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++ it)
+ svg.draw(it->lines(), "gray", stroke_width);
+#endif /* CLIPPER_UTILS_DEBUG */
+
// read input
ClipperLib::Paths input;
Slic3rMultiPoints_to_ClipperPaths(polygons, &input);
@@ -245,12 +264,18 @@ offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float
ClipperLib::Paths output1;
co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
co.Execute(output1, (delta1*scale));
+#ifdef CLIPPER_UTILS_DEBUG
+ svg.draw(output1, 1./CLIPPER_OFFSET_SCALE, "red", stroke_width);
+#endif /* CLIPPER_UTILS_DEBUG */
// perform second offset
co.Clear();
co.AddPaths(output1, joinType, ClipperLib::etClosedPolygon);
co.Execute(*retval, (delta2*scale));
-
+#ifdef CLIPPER_UTILS_DEBUG
+ svg.draw(*retval, 1./CLIPPER_OFFSET_SCALE, "green", stroke_width);
+#endif /* CLIPPER_UTILS_DEBUG */
+
// unscale output
scaleClipperPolygons(*retval, 1/scale);
}
diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/xs/src/libslic3r/ClipperUtils.hpp
index e7396af76..ccdf75588 100644
--- a/xs/src/libslic3r/ClipperUtils.hpp
+++ b/xs/src/libslic3r/ClipperUtils.hpp
@@ -14,6 +14,11 @@ using ClipperLib::jtSquare;
namespace Slic3r {
+// Factor to convert from coord_t (which is int32) to an int64 type used by the Clipper library.
+//FIXME Vojtech: Better to use a power of 2 coefficient and to use bit shifts for scaling.
+// How about 2^17=131072?
+// By the way, is the scalling needed at all? Cura runs all the computation with a fixed point precision of 1um, while Slic3r scales to 1nm,
+// further scaling by 10e5 brings us to
#define CLIPPER_OFFSET_SCALE 100000.0
//-----------------------------------------------------------
diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp
index 9194548c7..b26a519bc 100644
--- a/xs/src/libslic3r/Config.cpp
+++ b/xs/src/libslic3r/Config.cpp
@@ -39,8 +39,8 @@ ConfigDef::add(const t_config_option_key &opt_key, ConfigOptionType type)
const ConfigOptionDef*
ConfigDef::get(const t_config_option_key &opt_key) const
{
- if (this->options.count(opt_key) == 0) return NULL;
- return &const_cast<ConfigDef*>(this)->options[opt_key];
+ t_optiondef_map::iterator it = const_cast<ConfigDef*>(this)->options.find(opt_key);
+ return (it == this->options.end()) ? NULL : &it->second;
}
bool
@@ -113,6 +113,8 @@ ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str)
return opt->deserialize(str);
}
+// Return an absolute value of a possibly relative config variable.
+// For example, return absolute infill extrusion width, either from an absolute value, or relative to the layer height.
double
ConfigBase::get_abs_value(const t_config_option_key &opt_key) {
ConfigOption* opt = this->option(opt_key, false);
@@ -130,6 +132,8 @@ ConfigBase::get_abs_value(const t_config_option_key &opt_key) {
}
}
+// Return an absolute value of a possibly relative config variable.
+// For example, return absolute infill extrusion width, either from an absolute value, or relative to a provided value.
double
ConfigBase::get_abs_value(const t_config_option_key &opt_key, double ratio_over) {
// get stored option value
@@ -180,6 +184,7 @@ DynamicConfig& DynamicConfig::operator= (DynamicConfig other)
void
DynamicConfig::swap(DynamicConfig &other)
{
+ std::swap(this->def, other.def);
std::swap(this->options, other.options);
}
@@ -197,7 +202,8 @@ DynamicConfig::DynamicConfig (const DynamicConfig& other) {
ConfigOption*
DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) {
- if (this->options.count(opt_key) == 0) {
+ t_options_map::iterator it = options.find(opt_key);
+ if (it == options.end()) {
if (create) {
const ConfigOptionDef* optdef = this->def->get(opt_key);
assert(optdef != NULL);
@@ -239,7 +245,7 @@ DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) {
return NULL;
}
}
- return this->options[opt_key];
+ return it->second;
}
template<class T>
@@ -273,7 +279,6 @@ StaticConfig::set_defaults()
t_config_option_keys keys = this->keys();
for (t_config_option_keys::const_iterator it = keys.begin(); it != keys.end(); ++it) {
const ConfigOptionDef* def = this->def->get(*it);
-
if (def->default_value != NULL)
this->option(*it)->set(*def->default_value);
}
diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp
index 99cc02fb0..ac6b03a49 100644
--- a/xs/src/libslic3r/Config.hpp
+++ b/xs/src/libslic3r/Config.hpp
@@ -14,9 +14,11 @@
namespace Slic3r {
+// Name of the configuration option.
typedef std::string t_config_option_key;
typedef std::vector<std::string> t_config_option_keys;
+// A generic value of a configuration option.
class ConfigOption {
public:
virtual ~ConfigOption() {};
@@ -31,6 +33,7 @@ class ConfigOption {
friend bool operator!= (const ConfigOption &a, const ConfigOption &b);
};
+// Value of a single valued option (bool, int, float, string, point, enum)
template <class T>
class ConfigOptionSingle : public ConfigOption {
public:
@@ -44,12 +47,14 @@ class ConfigOptionSingle : public ConfigOption {
};
};
+// Value of a vector valued option (bools, ints, floats, strings, points)
class ConfigOptionVectorBase : public ConfigOption {
public:
virtual ~ConfigOptionVectorBase() {};
virtual std::vector<std::string> vserialize() const = 0;
};
+// Value of a vector valued option (bools, ints, floats, strings, points), template
template <class T>
class ConfigOptionVector : public ConfigOptionVectorBase
{
@@ -436,6 +441,7 @@ class ConfigOptionBools : public ConfigOptionVector<bool>
};
};
+// Map from an enum name to an enum integer value.
typedef std::map<std::string,int> t_config_enum_values;
template <class T>
@@ -461,11 +467,14 @@ class ConfigOptionEnum : public ConfigOptionSingle<T>
return true;
};
+ // Map from an enum name to an enum integer value.
+ //FIXME The map is called often, it shall be initialized statically.
static t_config_enum_values get_enum_values();
};
-/* We use this one in DynamicConfig objects, otherwise it's better to use
- the specialized ConfigOptionEnum<T> containers. */
+// Generic enum configuration value.
+// We use this one in DynamicConfig objects when creating a config value object for ConfigOptionType == coEnum.
+// In the StaticConfig, it is better to use the specialized ConfigOptionEnum<T> containers.
class ConfigOptionEnumGeneric : public ConfigOptionInt
{
public:
@@ -485,57 +494,117 @@ class ConfigOptionEnumGeneric : public ConfigOptionInt
};
};
+// Type of a configuration value.
enum ConfigOptionType {
coNone,
+ // single float
coFloat,
+ // vector of floats
coFloats,
+ // single int
coInt,
+ // vector of ints
coInts,
+ // single string
coString,
+ // vector of strings
coStrings,
+ // percent value. Currently only used for infill.
coPercent,
+ // a fraction or an absolute value
coFloatOrPercent,
+ // single 2d point. Currently not used.
coPoint,
+ // vector of 2d points. Currently used for the definition of the print bed and for the extruder offsets.
coPoints,
+ // single boolean value
coBool,
+ // vector of boolean values
coBools,
+ // a generic enum
coEnum,
};
+// Definition of a configuration value for the purpose of GUI presentation, editing, value mapping and config file handling.
class ConfigOptionDef
{
public:
+ // What type? bool, int, string etc.
ConfigOptionType type;
+ // Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor.
ConfigOption* default_value;
+
+ // Usually empty.
+ // Special values - "i_enum_open", "f_enum_open" to provide combo box for int or float selection,
+ // "select_open" - to open a selection dialog (currently only a serial port selection).
std::string gui_type;
+ // Usually empty. Otherwise "serialized" or "show_value"
+ // The flags may be combined.
+ // "serialized" - vector valued option is entered in a single edit field. Values are separated by a semicolon.
+ // "show_value" - even if enum_values / enum_labels are set, still display the value, not the enum label.
std::string gui_flags;
+ // Label of the GUI input field.
+ // In case the GUI input fields are grouped in some views, the label defines a short label of a grouped value,
+ // while full_label contains a label of a stand-alone field.
+ // The full label is shown, when adding an override parameter for an object or a modified object.
std::string label;
std::string full_label;
+ // Category of a configuration field, from the GUI perspective.
+ // One of: "Layers and Perimeters", "Infill", "Support material", "Speed", "Extruders", "Advanced", "Extrusion Width"
std::string category;
+ // A tooltip text shown in the GUI.
std::string tooltip;
+ // Text right from the input field, usually a unit of measurement.
std::string sidetext;
+ // Format of this parameter on a command line.
std::string cli;
+ // Set for type == coFloatOrPercent.
+ // It provides a link to a configuration value, of which this option provides a ratio.
+ // For example,
+ // For example external_perimeter_speed may be defined as a fraction of perimeter_speed.
t_config_option_key ratio_over;
+ // True for multiline strings.
bool multiline;
+ // For text input: If true, the GUI text box spans the complete page width.
bool full_width;
+ // Not editable. Currently only used for the display of the number of threads.
bool readonly;
+ // Height of a multiline GUI text box.
int height;
+ // Optional width of an input field.
int width;
+ // <min, max> limit of a numeric input.
+ // If not set, the <min, max> is set to <INT_MIN, INT_MAX>
+ // By setting min=0, only nonnegative input is allowed.
int min;
int max;
+ // Legacy names for this configuration option.
+ // Used when parsing legacy configuration file.
std::vector<t_config_option_key> aliases;
+ // Sometimes a single value may well define multiple values in a "beginner" mode.
+ // Currently used for aliasing "solid_layers" to "top_solid_layers", "bottom_solid_layers".
std::vector<t_config_option_key> shortcut;
+ // Definition of values / labels for a combo box.
+ // Mostly used for enums (when type == coEnum), but may be used for ints resp. floats, if gui_type is set to "i_enum_open" resp. "f_enum_open".
std::vector<std::string> enum_values;
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;
-
+
ConfigOptionDef() : type(coNone), default_value(NULL),
multiline(false), full_width(false), readonly(false),
height(-1), width(-1), min(INT_MIN), max(INT_MAX) {};
};
+// Map from a config option name to its definition.
+// The definition does not carry an actual value of the config option, only its constant default value.
+// t_config_option_key is std::string
typedef std::map<t_config_option_key,ConfigOptionDef> t_optiondef_map;
+// Definition of configuration values for the purpose of GUI presentation, editing, value mapping and config file handling.
+// The configuration definition is static: It does not carry the actual configuration values,
+// but it carries the defaults of the configuration values.
class ConfigDef
{
public:
@@ -545,9 +614,14 @@ class ConfigDef
const ConfigOptionDef* get(const t_config_option_key &opt_key) const;
};
+// An abstract configuration store.
class ConfigBase
{
public:
+ // Definition of configuration values for the purpose of GUI presentation, editing, value mapping and config file handling.
+ // The configuration definition is static: It does not carry the actual configuration values,
+ // but it carries the defaults of the configuration values.
+ // ConfigBase does not own ConfigDef, it only references it.
const ConfigDef* def;
ConfigBase() : def(NULL) {};
@@ -562,11 +636,14 @@ class ConfigBase
t_config_option_keys diff(ConfigBase &other);
std::string serialize(const t_config_option_key &opt_key) const;
bool set_deserialize(const t_config_option_key &opt_key, std::string str);
+
double get_abs_value(const t_config_option_key &opt_key);
double get_abs_value(const t_config_option_key &opt_key, double ratio_over);
void setenv_();
};
+// Configuration store with dynamic number of configuration values.
+// In Slic3r, the dynamic config is mostly used at the user interface layer.
class DynamicConfig : public virtual ConfigBase
{
public:
@@ -585,13 +662,20 @@ class DynamicConfig : public virtual ConfigBase
t_options_map options;
};
+// Configuration store with a static definition of configuration values.
+// In Slic3r, the static configuration stores are during the slicing / g-code generation for efficiency reasons,
+// because the configuration values could be accessed directly.
class StaticConfig : public virtual ConfigBase
{
public:
StaticConfig() : ConfigBase() {};
+ // Gets list of config option names for each config option of this->def, which has a static counter-part defined by the derived object
+ // and which could be resolved by this->optptr(key) call.
t_config_option_keys keys() const;
- //virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) = 0;
+ // Set all statically defined config options to their defaults defined by this->def.
void set_defaults();
+ // The derived class has to implement optptr to resolve a static configuration value.
+ // virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) = 0;
};
}
diff --git a/xs/src/libslic3r/ExPolygon.cpp b/xs/src/libslic3r/ExPolygon.cpp
index 1347f4a94..2220772b8 100644
--- a/xs/src/libslic3r/ExPolygon.cpp
+++ b/xs/src/libslic3r/ExPolygon.cpp
@@ -514,4 +514,20 @@ ExPolygon::dump_perl() const
return ret.str();
}
+BoundingBox get_extents(const ExPolygon &expolygon)
+{
+ return get_extents(expolygon.contour);
+}
+
+BoundingBox get_extents(const ExPolygons &expolygons)
+{
+ BoundingBox bbox;
+ if (! expolygons.empty()) {
+ bbox = get_extents(expolygons.front());
+ for (size_t i = 1; i < expolygons.size(); ++ i)
+ bbox.merge(get_extents(expolygons[i]));
+ }
+ return bbox;
}
+
+} // namespace Slic3r
diff --git a/xs/src/libslic3r/ExPolygon.hpp b/xs/src/libslic3r/ExPolygon.hpp
index 53a3fce1d..4bb8cf8e4 100644
--- a/xs/src/libslic3r/ExPolygon.hpp
+++ b/xs/src/libslic3r/ExPolygon.hpp
@@ -72,7 +72,10 @@ inline Polygons to_polygons(ExPolygons &&src)
}
#endif
-}
+extern BoundingBox get_extents(const ExPolygon &expolygon);
+extern BoundingBox get_extents(const ExPolygons &expolygons);
+
+} // namespace Slic3r
// start Boost
#include <boost/polygon/polygon.hpp>
diff --git a/xs/src/libslic3r/ExPolygonCollection.cpp b/xs/src/libslic3r/ExPolygonCollection.cpp
index 10e036210..eb5cceb0e 100644
--- a/xs/src/libslic3r/ExPolygonCollection.cpp
+++ b/xs/src/libslic3r/ExPolygonCollection.cpp
@@ -128,4 +128,9 @@ ExPolygonCollection::append(const ExPolygons &expp)
this->expolygons.insert(this->expolygons.end(), expp.begin(), expp.end());
}
+BoundingBox get_extents(const ExPolygonCollection &expolygon)
+{
+ return get_extents(expolygon.expolygons);
+}
+
}
diff --git a/xs/src/libslic3r/ExPolygonCollection.hpp b/xs/src/libslic3r/ExPolygonCollection.hpp
index ec3cb9522..4c181cd6a 100644
--- a/xs/src/libslic3r/ExPolygonCollection.hpp
+++ b/xs/src/libslic3r/ExPolygonCollection.hpp
@@ -34,6 +34,8 @@ class ExPolygonCollection
void append(const ExPolygons &expolygons);
};
+extern BoundingBox get_extents(const ExPolygonCollection &expolygon);
+
}
#endif
diff --git a/xs/src/libslic3r/ExtrusionSimulator.cpp b/xs/src/libslic3r/ExtrusionSimulator.cpp
index 2dbef9a25..83422cdee 100644
--- a/xs/src/libslic3r/ExtrusionSimulator.cpp
+++ b/xs/src/libslic3r/ExtrusionSimulator.cpp
@@ -1,7 +1,7 @@
// Optimize the extrusion simulator to the bones.
-#pragma GCC optimize ("O3")
-#undef SLIC3R_DEBUG
-#define NDEBUG
+//#pragma GCC optimize ("O3")
+//#undef SLIC3R_DEBUG
+//#define NDEBUG
#include <cmath>
#include <cassert>
@@ -640,7 +640,7 @@ struct Cell
// Height of the covered part in excess to the expected layer height.
float excess_height;
- bool operator<(const Cell &c2) {
+ bool operator<(const Cell &c2) const {
return this->excess_height < c2.excess_height;
}
};
diff --git a/xs/src/libslic3r/ExtrusionSimulator.hpp b/xs/src/libslic3r/ExtrusionSimulator.hpp
index f64a3b7d3..8b956ec11 100644
--- a/xs/src/libslic3r/ExtrusionSimulator.hpp
+++ b/xs/src/libslic3r/ExtrusionSimulator.hpp
@@ -2,7 +2,6 @@
#define slic3r_ExtrusionSimulator_hpp_
#include "libslic3r.h"
-#include "Config.hpp"
#include "ExtrusionEntity.hpp"
#include "BoundingBox.hpp"
diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp
index 4e741ab08..b521cc696 100644
--- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp
+++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp
@@ -23,6 +23,10 @@
// We want our version of assert.
#include "../libslic3r.h"
+#ifndef myassert
+#define myassert assert
+#endif
+
namespace Slic3r {
#ifndef clamp
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index d6d661b5c..afd3051bd 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -78,6 +78,9 @@ class GCode {
Wipe wipe;
AvoidCrossingPerimeters avoid_crossing_perimeters;
bool enable_loop_clipping;
+ // If enabled, the G-code generator will put following comments at the ends
+ // of the G-code lines: _EXTRUDE_SET_SPEED, _WIPE, _BRIDGE_FAN_START, _BRIDGE_FAN_END
+ // Those comments are received and consumed (removed from the G-code) by the CoolingBuffer.pm Perl module.
bool enable_cooling_markers;
// Markers for the Pressure Equalizer to recognize the extrusion type.
// The Pressure Equalizer removes the markers from the final G-code.
@@ -89,6 +92,10 @@ class GCode {
// Distance Field structure to
EdgeGrid::Grid *_lower_layer_edge_grid;
bool first_layer; // this flag triggers first layer speeds
+ // Used by the CoolingBuffer.pm Perl module to calculate time spent per layer change.
+ // This value is not quite precise. First it only accouts for extrusion moves and travel moves,
+ // it does not account for wipe, retract / unretract moves.
+ // second it does not account for the velocity profiles of the printer.
float elapsed_time; // seconds
double volumetric_speed;
// Support for the extrusion role markers. Which marker is active?
diff --git a/xs/src/libslic3r/Layer.cpp b/xs/src/libslic3r/Layer.cpp
index dc931923c..a392f732e 100644
--- a/xs/src/libslic3r/Layer.cpp
+++ b/xs/src/libslic3r/Layer.cpp
@@ -162,6 +162,10 @@ Layer::any_bottom_region_slice_contains(const T &item) const
}
template bool Layer::any_bottom_region_slice_contains<Polyline>(const Polyline &item) const;
+
+// Here the perimeters are created cummulatively for all layer regions sharing the same parameters influencing the perimeters.
+// The perimeter paths and the thin fills (ExtrusionEntityCollection) are assigned to the first compatible layer region.
+// The resulting fill surface is split back among the originating regions.
void
Layer::make_perimeters()
{
diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp
index 50f6ebbea..d713b7c1f 100644
--- a/xs/src/libslic3r/LayerRegion.cpp
+++ b/xs/src/libslic3r/LayerRegion.cpp
@@ -77,6 +77,7 @@ LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection*
);
if (this->layer()->lower_layer != NULL)
+ // Cummulative sum of polygons over all the regions.
g.lower_slices = &this->layer()->lower_layer->slices;
g.layer_id = this->layer()->id();
diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp
index 9eaf5e2f7..adc464bf7 100644
--- a/xs/src/libslic3r/Model.cpp
+++ b/xs/src/libslic3r/Model.cpp
@@ -772,7 +772,7 @@ ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
void
ModelInstance::transform_polygon(Polygon* polygon) const
{
- polygon->rotate(this->rotation, Point(0,0)); // rotate around polygon origin
+ polygon->rotate(this->rotation); // rotate around polygon origin
polygon->scale(this->scaling_factor); // scale around polygon origin
}
diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp
index f10707457..cb0ab05f2 100644
--- a/xs/src/libslic3r/Model.hpp
+++ b/xs/src/libslic3r/Model.hpp
@@ -27,10 +27,18 @@ typedef std::vector<ModelObject*> ModelObjectPtrs;
typedef std::vector<ModelVolume*> ModelVolumePtrs;
typedef std::vector<ModelInstance*> ModelInstancePtrs;
+// The print bed content.
+// Description of a triangular model with multiple materials, multiple instances with various affine transformations
+// and with multiple modifier meshes.
+// A model groups multiple objects, each object having possibly multiple instances,
+// all objects may share mutliple materials.
class Model
{
- public:
+public:
+ // Materials are owned by a model and referenced by objects through t_model_material_id.
+ // Single material may be shared by multiple models.
ModelMaterialMap materials;
+ // Objects are owned by a model. Each model may have multiple instances, each instance having its own transformation (shift, scale, rotation).
ModelObjectPtrs objects;
Model();
@@ -63,34 +71,48 @@ class Model
void duplicate_objects_grid(size_t x, size_t y, coordf_t dist);
};
+// Material, which may be shared across multiple ModelObjects of a single Model.
class ModelMaterial
{
friend class Model;
- public:
+public:
+ // Attributes are defined by the AMF file format, but they don't seem to be used by Slic3r for any purpose.
t_model_material_attributes attributes;
+ // Dynamic configuration storage for the object specific configuration values, overriding the global configuration.
DynamicPrintConfig config;
Model* get_model() const { return this->model; };
void apply(const t_model_material_attributes &attributes);
- private:
+private:
+ // Parent, owning this material.
Model* model;
ModelMaterial(Model *model);
ModelMaterial(Model *model, const ModelMaterial &other);
};
+// A printable object, possibly having multiple print volumes (each with its own set of parameters and materials),
+// and possibly having multiple modifier volumes, each modifier volume with its set of parameters and materials.
+// Each ModelObject may be instantiated mutliple times, each instance having different placement on the print bed,
+// different rotation and different uniform scaling.
class ModelObject
{
friend class Model;
- public:
+public:
std::string name;
std::string input_file;
+ // Instances of this ModelObject. Each instance defines a shift on the print bed, rotation around the Z axis and a uniform scaling.
+ // Instances are owned by this ModelObject.
ModelInstancePtrs instances;
+ // Printable and modifier volumes, each with its material ID and a set of override parameters.
+ // ModelVolumes are owned by this ModelObject.
ModelVolumePtrs volumes;
+ // Configuration parameters specific to a single ModelObject, overriding the global Slic3r settings.
DynamicPrintConfig config;
+ // Variation of a layer thickness for spans of Z coordinates.
t_layer_height_ranges layer_height_ranges;
-
+
/* This vector accumulates the total translation applied to the object by the
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
@@ -134,7 +156,8 @@ class ModelObject
void split(ModelObjectPtrs* new_objects);
void update_bounding_box(); // this is a private method but we expose it until we need to expose it via XS
- private:
+private:
+ // Parent object, owning this ModelObject.
Model* model;
ModelObject(Model *model);
@@ -144,15 +167,22 @@ class ModelObject
~ModelObject();
};
+// An object STL, or a modifier volume, over which a different set of parameters shall be applied.
+// ModelVolume instances are owned by a ModelObject.
class ModelVolume
{
friend class ModelObject;
- public:
+public:
std::string name;
+ // The triangular model.
TriangleMesh mesh;
+ // Configuration parameters specific to an object model geometry or a modifier volume,
+ // overriding the global Slic3r settings and the ModelObject settings.
DynamicPrintConfig config;
+ // Is it an object to be printed, or a modifier volume?
bool modifier;
+ // A parent object owning this modifier volume.
ModelObject* get_object() const { return this->object; };
t_model_material_id material_id() const;
void material_id(t_model_material_id material_id);
@@ -161,7 +191,8 @@ class ModelVolume
ModelMaterial* assign_unique_material();
- private:
+private:
+ // Parent object owning this ModelVolume.
ModelObject* object;
t_model_material_id _material_id;
@@ -169,19 +200,25 @@ class ModelVolume
ModelVolume(ModelObject *object, const ModelVolume &other);
};
+// A single instance of a ModelObject.
+// Knows the affine transformation of an object.
class ModelInstance
{
friend class ModelObject;
- public:
- double rotation; // in radians around mesh center point
+public:
+ double rotation; // Rotation around the Z axis, in radians around mesh center point
double scaling_factor;
Pointf offset; // in unscaled coordinates
ModelObject* get_object() const { return this->object; };
+
+ // To be called on an external mesh
void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const;
+ // To be called on an external polygon. It does not translate the polygon, only rotates and scales.
void transform_polygon(Polygon* polygon) const;
- private:
+private:
+ // Parent object, owning this instance.
ModelObject* object;
ModelInstance(ModelObject *object);
diff --git a/xs/src/libslic3r/MultiPoint.cpp b/xs/src/libslic3r/MultiPoint.cpp
index 5be53e5da..e253f9bba 100644
--- a/xs/src/libslic3r/MultiPoint.cpp
+++ b/xs/src/libslic3r/MultiPoint.cpp
@@ -33,8 +33,8 @@ MultiPoint::translate(const Point &vector)
void
MultiPoint::rotate(double angle)
{
- double s = sin(angle);
- double c = cos(angle);
+ double s = sin(angle);
+ double c = cos(angle);
for (Points::iterator it = points.begin(); it != points.end(); ++it) {
double cur_x = (double)it->x;
double cur_y = (double)it->y;
@@ -46,8 +46,13 @@ MultiPoint::rotate(double angle)
void
MultiPoint::rotate(double angle, const Point &center)
{
+ double s = sin(angle);
+ double c = cos(angle);
for (Points::iterator it = points.begin(); it != points.end(); ++it) {
- (*it).rotate(angle, center);
+ double dx = double(it->x - center.x);
+ double dy = double(it->y - center.y);
+ it->x = (coord_t)round(double(center.x) + c * dx - s * dy);
+ it->y = (coord_t)round(double(center.y) + c * dy + s * dx);
}
}
@@ -202,4 +207,9 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
return results;
}
+BoundingBox get_extents(const MultiPoint &mp)
+{
+ return mp.bounding_box();
+}
+
}
diff --git a/xs/src/libslic3r/MultiPoint.hpp b/xs/src/libslic3r/MultiPoint.hpp
index 7cf41a870..66b36d720 100644
--- a/xs/src/libslic3r/MultiPoint.hpp
+++ b/xs/src/libslic3r/MultiPoint.hpp
@@ -47,6 +47,8 @@ class MultiPoint
static Points _douglas_peucker(const Points &points, const double tolerance);
};
-}
+extern BoundingBox get_extents(const MultiPoint &mp);
+
+} // namespace Slic3r
#endif
diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp
index e9153923f..f1108fcbd 100644
--- a/xs/src/libslic3r/PerimeterGenerator.cpp
+++ b/xs/src/libslic3r/PerimeterGenerator.cpp
@@ -534,12 +534,6 @@ PerimeterGenerator::_variable_width(const ThickPolylines &polylines, ExtrusionRo
}
bool
-PerimeterGeneratorLoop::is_external() const
-{
- return this->depth == 0;
-}
-
-bool
PerimeterGeneratorLoop::is_internal_contour() const
{
if (this->is_contour) {
diff --git a/xs/src/libslic3r/PerimeterGenerator.hpp b/xs/src/libslic3r/PerimeterGenerator.hpp
index eb3fa0fcb..0e7fbd3e4 100644
--- a/xs/src/libslic3r/PerimeterGenerator.hpp
+++ b/xs/src/libslic3r/PerimeterGenerator.hpp
@@ -11,25 +11,33 @@
namespace Slic3r {
-class PerimeterGeneratorLoop;
-typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
-
+// Hierarchy of perimeters.
class PerimeterGeneratorLoop {
- public:
+public:
+ // Polygon of this contour.
Polygon polygon;
+ // Is it a contour or a hole?
+ // Contours are CCW oriented, holes are CW oriented.
bool is_contour;
+ // Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
unsigned short depth;
+ // Children contour, may be both CCW and CW oriented (outer contours or holes).
std::vector<PerimeterGeneratorLoop> children;
PerimeterGeneratorLoop(Polygon polygon, unsigned short depth)
: polygon(polygon), is_contour(false), depth(depth)
{};
- bool is_external() const;
+ // External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
+ bool is_external() const { return this->depth == 0; }
+ // An island, which may have holes, but it does not have another internal island.
bool is_internal_contour() const;
};
+typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
+
class PerimeterGenerator {
- public:
+public:
+ // Inputs:
const SurfaceCollection* slices;
const ExPolygonCollection* lower_slices;
double layer_height;
@@ -41,14 +49,26 @@ class PerimeterGenerator {
PrintRegionConfig* config;
PrintObjectConfig* object_config;
PrintConfig* print_config;
+ // Outputs:
ExtrusionEntityCollection* loops;
ExtrusionEntityCollection* gap_fill;
SurfaceCollection* fill_surfaces;
- PerimeterGenerator(const SurfaceCollection* slices, double layer_height, Flow flow,
- PrintRegionConfig* config, PrintObjectConfig* object_config,
- PrintConfig* print_config, ExtrusionEntityCollection* loops,
- ExtrusionEntityCollection* gap_fill, SurfaceCollection* fill_surfaces)
+ PerimeterGenerator(
+ // Input:
+ const SurfaceCollection* slices,
+ double layer_height,
+ Flow flow,
+ PrintRegionConfig* config,
+ PrintObjectConfig* object_config,
+ PrintConfig* print_config,
+ // Output:
+ // Loops with the external thin walls
+ ExtrusionEntityCollection* loops,
+ // Gaps without the thin walls
+ ExtrusionEntityCollection* gap_fill,
+ // Infills without the gap fills
+ SurfaceCollection* fill_surfaces)
: slices(slices), lower_slices(NULL), layer_height(layer_height),
layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow),
overhang_flow(flow), solid_infill_flow(flow),
diff --git a/xs/src/libslic3r/Point.cpp b/xs/src/libslic3r/Point.cpp
index 2a1668950..6dbcc6f00 100644
--- a/xs/src/libslic3r/Point.cpp
+++ b/xs/src/libslic3r/Point.cpp
@@ -94,6 +94,12 @@ Point::nearest_point_index(const Points &points) const
return this->nearest_point_index(p);
}
+template<typename T>
+inline T sqr(const T x)
+{
+ return x * x;
+}
+
int
Point::nearest_point_index(const PointConstPtrs &points) const
{
@@ -103,12 +109,12 @@ Point::nearest_point_index(const PointConstPtrs &points) const
for (PointConstPtrs::const_iterator it = points.begin(); it != points.end(); ++it) {
/* If the X distance of the candidate is > than the total distance of the
best previous candidate, we know we don't want it */
- double d = pow(this->x - (*it)->x, 2);
+ double d = sqr<double>(this->x - (*it)->x);
if (distance != -1 && d > distance) continue;
/* If the Y distance of the candidate is > than the total distance of the
best previous candidate, we know we don't want it */
- d += pow(this->y - (*it)->y, 2);
+ d += sqr<double>(this->y - (*it)->y);
if (distance != -1 && d > distance) continue;
idx = it - points.begin();
@@ -129,10 +135,10 @@ Point::nearest_waypoint_index(const Points &points, const Point &dest) const
for (Points::const_iterator p = points.begin(); p != points.end(); ++p) {
// distance from this to candidate
- double d = pow(this->x - p->x, 2) + pow(this->y - p->y, 2);
+ double d = sqr<double>(this->x - p->x) + sqr<double>(this->y - p->y);
// distance from candidate to dest
- d += pow(p->x - dest.x, 2) + pow(p->y - dest.y, 2);
+ d += sqr<double>(p->x - dest.x) + sqr<double>(p->y - dest.y);
// if the total distance is greater than current min distance, ignore it
if (distance != -1 && d > distance) continue;
@@ -278,8 +284,10 @@ Point::projection_onto(const Line &line) const
If theta is outside the interval [0,1], then one of the Line_Segment's endpoints
must be closest to calling Point.
*/
- double theta = ( (double)(line.b.x - this->x)*(double)(line.b.x - line.a.x) + (double)(line.b.y- this->y)*(double)(line.b.y - line.a.y) )
- / ( (double)pow(line.b.x - line.a.x, 2) + (double)pow(line.b.y - line.a.y, 2) );
+ double lx = (double)(line.b.x - line.a.x);
+ double ly = (double)(line.b.y - line.a.y);
+ double theta = ( (double)(line.b.x - this->x)*lx + (double)(line.b.y- this->y)*ly )
+ / ( sqr<double>(lx) + sqr<double>(ly) );
if (0.0 <= theta && theta <= 1.0)
return theta * line.a + (1.0-theta) * line.b;
diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp
index 9c23252cb..58747690a 100644
--- a/xs/src/libslic3r/Point.hpp
+++ b/xs/src/libslic3r/Point.hpp
@@ -44,6 +44,8 @@ class Point
void translate(const Vector &vector);
void rotate(double angle);
void rotate(double angle, const Point &center);
+ Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
+ Point rotated(double angle, const Point &center) const { Point res(*this); res.rotate(angle, center); return res; }
bool coincides_with(const Point &point) const { return this->x == point.x && this->y == point.y; }
bool coincides_with_epsilon(const Point &point) const;
int nearest_point_index(const Points &points) const;
diff --git a/xs/src/libslic3r/Polygon.cpp b/xs/src/libslic3r/Polygon.cpp
index 102838809..ac5185a0b 100644
--- a/xs/src/libslic3r/Polygon.cpp
+++ b/xs/src/libslic3r/Polygon.cpp
@@ -1,3 +1,4 @@
+#include "BoundingBox.hpp"
#include "ClipperUtils.hpp"
#include "Polygon.hpp"
#include "Polyline.hpp"
@@ -59,6 +60,7 @@ Polygon::split_at_vertex(const Point &point) const
return Polyline();
}
+// Split a closed polygon into an open polyline, with the split point duplicated at both ends.
Polyline
Polygon::split_at_index(int index) const
{
@@ -71,6 +73,7 @@ Polygon::split_at_index(int index) const
return polyline;
}
+// Split a closed polygon into an open polyline, with the split point duplicated at both ends.
Polyline
Polygon::split_at_first_point() const
{
@@ -131,6 +134,8 @@ Polygon::is_valid() const
return this->points.size() >= 3;
}
+// Does an unoriented polygon contain a point?
+// Tested by counting intersections along a horizontal line.
bool
Polygon::contains(const Point &point) const
{
@@ -139,9 +144,20 @@ Polygon::contains(const Point &point) const
Points::const_iterator i = this->points.begin();
Points::const_iterator j = this->points.end() - 1;
for (; i != this->points.end(); j = i++) {
+ //FIXME this test is not numerically robust. Particularly, it does not handle horizontal segments at y == point.y well.
+ // Does the ray with y == point.y intersect this line segment?
+#if 1
if ( ((i->y > point.y) != (j->y > point.y))
&& ((double)point.x < (double)(j->x - i->x) * (double)(point.y - i->y) / (double)(j->y - i->y) + (double)i->x) )
result = !result;
+#else
+ if ((i->y > point.y) != (j->y > point.y)) {
+ // Orientation predicated relative to i-th point.
+ double orient = (double)(point.x - i->x) * (double)(j->y - i->y) - (double)(point.y - i->y) * (double)(j->x - i->x);
+ if ((i->y > j->y) ? (orient > 0.) : (orient < 0.))
+ result = !result;
+ }
+#endif
}
return result;
}
@@ -265,4 +281,20 @@ Polygon::convex_points(double angle) const
return points;
}
+BoundingBox get_extents(const Polygon &poly)
+{
+ return poly.bounding_box();
+}
+
+BoundingBox get_extents(const Polygons &polygons)
+{
+ BoundingBox bb;
+ if (! polygons.empty()) {
+ bb = polygons.front().bounding_box();
+ for (size_t i = 1; i < polygons.size(); ++ i)
+ bb.merge(polygons[i]);
+ }
+ return bb;
+}
+
}
diff --git a/xs/src/libslic3r/Polygon.hpp b/xs/src/libslic3r/Polygon.hpp
index ccde4a740..9f0bc6028 100644
--- a/xs/src/libslic3r/Polygon.hpp
+++ b/xs/src/libslic3r/Polygon.hpp
@@ -25,7 +25,9 @@ class Polygon : public MultiPoint {
Point last_point() const;
virtual Lines lines() const;
Polyline split_at_vertex(const Point &point) const;
+ // Split a closed polygon into an open polyline, with the split point duplicated at both ends.
Polyline split_at_index(int index) const;
+ // Split a closed polygon into an open polyline, with the split point duplicated at both ends.
Polyline split_at_first_point() const;
Points equally_spaced_points(double distance) const;
double area() const;
@@ -34,6 +36,8 @@ class Polygon : public MultiPoint {
bool make_counter_clockwise();
bool make_clockwise();
bool is_valid() const;
+ // Does an unoriented polygon contain a point?
+ // Tested by counting intersections along a horizontal line.
bool contains(const Point &point) const;
Polygons simplify(double tolerance) const;
void simplify(double tolerance, Polygons &polygons) const;
@@ -44,6 +48,9 @@ class Polygon : public MultiPoint {
Points convex_points(double angle = PI) const;
};
+extern BoundingBox get_extents(const Polygon &poly);
+extern BoundingBox get_extents(const Polygons &polygons);
+
}
// start Boost
diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp
index 8d114f6e2..185c59aad 100644
--- a/xs/src/libslic3r/Print.cpp
+++ b/xs/src/libslic3r/Print.cpp
@@ -639,7 +639,7 @@ Print::validate() const
if (!object_height.empty() && object_height.back() > scale_(this->config.extruder_clearance_height.value))
throw PrintValidationException("Some objects are too tall and cannot be printed without extruder collisions.");
}
- }
+ } // end if (this->config.complete_objects)
if (this->config.spiral_vase) {
size_t total_copies_count = 0;
@@ -837,6 +837,7 @@ Print::auto_assign_extruders(ModelObject* model_object) const
size_t extruders = this->config.nozzle_diameter.values.size();
for (ModelVolumePtrs::const_iterator v = model_object->volumes.begin(); v != model_object->volumes.end(); ++v) {
if (!(*v)->material_id().empty()) {
+ //FIXME Vojtech: This assigns an extruder ID even to a modifier volume, if it has a material assigned.
size_t extruder_id = (v - model_object->volumes.begin()) + 1;
if (!(*v)->config.has("extruder"))
(*v)->config.opt<ConfigOptionInt>("extruder", true)->value = extruder_id;
diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp
index fcf6d0a79..a2a5ba7b4 100644
--- a/xs/src/libslic3r/Print.hpp
+++ b/xs/src/libslic3r/Print.hpp
@@ -20,7 +20,7 @@ class Print;
class PrintObject;
class ModelObject;
-
+// Print step IDs for keeping track of the print state.
enum PrintStep {
psSkirt, psBrim,
};
@@ -34,6 +34,7 @@ class PrintValidationException : public std::runtime_error {
PrintValidationException(const std::string &error) : std::runtime_error(error) {};
};
+// To be instantiated over PrintStep or PrintObjectStep enums.
template <class StepType>
class PrintState
{
@@ -120,6 +121,7 @@ class PrintObject
size_t layer_count() const;
void clear_layers();
Layer* get_layer(int idx);
+ // print_z: top of the layer; slice_z: center of the layer.
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
void delete_layer(int idx);
@@ -152,6 +154,7 @@ class PrintObject
typedef std::vector<PrintObject*> PrintObjectPtrs;
typedef std::vector<PrintRegion*> PrintRegionPtrs;
+// The complete print tray with possibly multiple objects.
class Print
{
public:
diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp
index 47609aaff..e3bc4bad9 100644
--- a/xs/src/libslic3r/PrintConfig.cpp
+++ b/xs/src/libslic3r/PrintConfig.cpp
@@ -885,11 +885,37 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("random");
def->enum_values.push_back("nearest");
def->enum_values.push_back("aligned");
+// def->enum_values.push_back("preferred");
def->enum_labels.push_back("Random");
def->enum_labels.push_back("Nearest");
def->enum_labels.push_back("Aligned");
+// def->enum_labels.push_back("Preferred Direction");
def->default_value = new ConfigOptionEnum<SeamPosition>(spAligned);
+#if 0
+ def = this->add("seam_preferred_direction", coFloat);
+// def->gui_type = "slider";
+ def->label = "Direction";
+ def->sidetext = "°";
+ def->full_label = "Preferred direction of the seam";
+ def->tooltip = "Seam preferred direction";
+ def->cli = "seam-preferred-direction=f";
+ def->min = 0;
+ def->max = 360;
+ def->default_value = new ConfigOptionFloat(0);
+
+ def = this->add("seam_preferred_direction_jitter", coFloat);
+// def->gui_type = "slider";
+ def->label = "Jitter";
+ def->sidetext = "°";
+ def->full_label = "Seam preferred direction jitter";
+ def->tooltip = "Preferred direction of the seam - jitter";
+ def->cli = "seam-preferred-direction-jitter=f";
+ def->min = 0;
+ def->max = 360;
+ def->default_value = new ConfigOptionFloat(30);
+#endif
+
def = this->add("serial_port", coString);
def->gui_type = "select_open";
def->label = "";
diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp
index 3f6eb8e06..d8c57cb57 100644
--- a/xs/src/libslic3r/PrintConfig.hpp
+++ b/xs/src/libslic3r/PrintConfig.hpp
@@ -1,3 +1,20 @@
+// Configuration store of Slic3r.
+//
+// The configuration store is either static or dynamic.
+// DynamicPrintConfig is used mainly at the user interface. while the StaticPrintConfig is used
+// during the slicing and the g-code generation.
+//
+// The classes derived from StaticPrintConfig form a following hierarchy.
+// Virtual inheritance is used for some of the parent objects.
+//
+// FullPrintConfig
+// PrintObjectConfig
+// PrintRegionConfig
+// PrintConfig
+// GCodeConfig
+// HostConfig
+//
+
#ifndef slic3r_PrintConfig_hpp_
#define slic3r_PrintConfig_hpp_
@@ -22,7 +39,7 @@ enum SupportMaterialPattern {
};
enum SeamPosition {
- spRandom, spNearest, spAligned
+ spRandom, spNearest, spAligned //, spPreferred
};
template<> inline t_config_enum_values ConfigOptionEnum<GCodeFlavor>::get_enum_values() {
@@ -65,17 +82,23 @@ template<> inline t_config_enum_values ConfigOptionEnum<SeamPosition>::get_enum_
keys_map["random"] = spRandom;
keys_map["nearest"] = spNearest;
keys_map["aligned"] = spAligned;
+// keys_map["preferred"] = spPreferred;
return keys_map;
}
+// Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs.
+// Does not store the actual values, but defines default values.
class PrintConfigDef : public ConfigDef
{
public:
PrintConfigDef();
};
+// The one and only global definition of SLic3r configuration options.
+// This definition is constant.
extern PrintConfigDef print_config_def;
+// Slic3r configuration storage with print_config_def assigned.
class PrintConfigBase : public virtual ConfigBase
{
public:
@@ -86,6 +109,12 @@ class PrintConfigBase : public virtual ConfigBase
double min_object_distance() const;
};
+// Slic3r dynamic configuration, used to override the configuration
+// per object, per modification volume or per printing material.
+// The dynamic configuration is also used to store user modifications of the print global parameters,
+// so the modified configuration values may be diffed against the active configuration
+// to invalidate the proper slicing resp. g-code generation processing steps.
+// This object is mapped to Perl as Slic3r::Config.
class DynamicPrintConfig : public PrintConfigBase, public DynamicConfig
{
public:
@@ -93,12 +122,14 @@ class DynamicPrintConfig : public PrintConfigBase, public DynamicConfig
void normalize();
};
+
class StaticPrintConfig : public PrintConfigBase, public StaticConfig
{
public:
StaticPrintConfig() : PrintConfigBase(), StaticConfig() {};
};
+// This object is mapped to Perl as Slic3r::Config::PrintObject.
class PrintObjectConfig : public virtual StaticPrintConfig
{
public:
@@ -110,6 +141,8 @@ class PrintObjectConfig : public virtual StaticPrintConfig
ConfigOptionFloat layer_height;
ConfigOptionInt raft_layers;
ConfigOptionEnum<SeamPosition> seam_position;
+// ConfigOptionFloat seam_preferred_direction;
+// ConfigOptionFloat seam_preferred_direction_jitter;
ConfigOptionBool support_material;
ConfigOptionInt support_material_angle;
ConfigOptionFloat support_material_contact_distance;
@@ -130,7 +163,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
if (initialize)
this->set_defaults();
}
-
+
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
OPT_PTR(dont_support_bridges);
OPT_PTR(extrusion_width);
@@ -140,6 +173,8 @@ class PrintObjectConfig : public virtual StaticPrintConfig
OPT_PTR(layer_height);
OPT_PTR(raft_layers);
OPT_PTR(seam_position);
+// OPT_PTR(seam_preferred_direction);
+// OPT_PTR(seam_preferred_direction_jitter);
OPT_PTR(support_material);
OPT_PTR(support_material_angle);
OPT_PTR(support_material_contact_distance);
@@ -160,6 +195,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
};
};
+// This object is mapped to Perl as Slic3r::Config::PrintRegion.
class PrintRegionConfig : public virtual StaticPrintConfig
{
public:
@@ -200,7 +236,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
if (initialize)
this->set_defaults();
}
-
+
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
OPT_PTR(bottom_solid_layers);
OPT_PTR(bridge_flow_ratio);
@@ -239,6 +275,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
};
};
+// This object is mapped to Perl as Slic3r::Config::GCode.
class GCodeConfig : public virtual StaticPrintConfig
{
public:
@@ -315,6 +352,7 @@ class GCodeConfig : public virtual StaticPrintConfig
};
};
+// This object is mapped to Perl as Slic3r::Config::Print.
class PrintConfig : public GCodeConfig
{
public:
@@ -373,7 +411,7 @@ class PrintConfig : public GCodeConfig
if (initialize)
this->set_defaults();
}
-
+
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
OPT_PTR(avoid_crossing_perimeters);
OPT_PTR(bed_shape);
@@ -446,7 +484,7 @@ class HostConfig : public virtual StaticPrintConfig
if (initialize)
this->set_defaults();
}
-
+
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
OPT_PTR(octoprint_host);
OPT_PTR(octoprint_apikey);
@@ -457,6 +495,7 @@ class HostConfig : public virtual StaticPrintConfig
};
};
+// This object is mapped to Perl as Slic3r::Config::Full.
class FullPrintConfig
: public PrintObjectConfig, public PrintRegionConfig, public PrintConfig, public HostConfig
{
diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp
index 23d9e74e1..016403059 100644
--- a/xs/src/libslic3r/PrintObject.cpp
+++ b/xs/src/libslic3r/PrintObject.cpp
@@ -270,6 +270,8 @@ PrintObject::invalidate_state_by_config_options(const std::vector<t_config_optio
steps.insert(posPerimeters);
steps.insert(posInfill);
} else if (*opt_key == "seam_position"
+ || *opt_key == "seam_preferred_direction"
+ || *opt_key == "seam_preferred_direction_jitter"
|| *opt_key == "support_material_speed"
|| *opt_key == "bridge_speed"
|| *opt_key == "external_perimeter_speed"
diff --git a/xs/src/libslic3r/SVG.cpp b/xs/src/libslic3r/SVG.cpp
index 259c6eacf..af4947e51 100644
--- a/xs/src/libslic3r/SVG.cpp
+++ b/xs/src/libslic3r/SVG.cpp
@@ -1,12 +1,12 @@
#include "SVG.hpp"
#include <iostream>
-#define COORD(x) ((float)unscale(x)*10)
+#define COORD(x) ((float)unscale((x))*10)
namespace Slic3r {
SVG::SVG(const char* filename)
- : arrows(false), fill("grey"), stroke("black"), filename(filename)
+ : arrows(false), fill("grey"), stroke("black"), filename(filename), flipY(false)
{
this->f = fopen(filename, "w");
fprintf(this->f,
@@ -19,12 +19,12 @@ SVG::SVG(const char* filename)
);
}
-SVG::SVG(const char* filename, const BoundingBox &bbox)
- : arrows(false), fill("grey"), stroke("black"), filename(filename), origin(bbox.min)
+SVG::SVG(const char* filename, const BoundingBox &bbox, const coord_t bbox_offset, bool aflipY)
+ : arrows(false), fill("grey"), stroke("black"), filename(filename), origin(bbox.min - Point(bbox_offset, bbox_offset)), flipY(aflipY)
{
this->f = fopen(filename, "w");
- float w = COORD(bbox.max.x - bbox.min.x);
- float h = COORD(bbox.max.y - bbox.min.y);
+ float w = COORD(bbox.max.x - bbox.min.x + 2 * bbox_offset);
+ float h = COORD(bbox.max.y - bbox.min.y + 2 * bbox_offset);
fprintf(this->f,
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
@@ -36,7 +36,7 @@ SVG::SVG(const char* filename, const BoundingBox &bbox)
}
void
-SVG::draw(const Line &line, std::string stroke, coord_t stroke_width)
+SVG::draw(const Line &line, std::string stroke, coordf_t stroke_width)
{
fprintf(this->f,
" <line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke: %s; stroke-width: %f\"",
@@ -46,7 +46,7 @@ SVG::draw(const Line &line, std::string stroke, coord_t stroke_width)
fprintf(this->f, "/>\n");
}
-void SVG::draw(const ThickLine &line, const std::string &fill, const std::string &stroke, coord_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.x-line.a.x, line.b.y-line.a.y);
Pointf perp(-dir.y, dir.x);
@@ -68,10 +68,10 @@ void SVG::draw(const ThickLine &line, const std::string &fill, const std::string
}
void
-SVG::draw(const Lines &lines, std::string stroke)
+SVG::draw(const Lines &lines, std::string stroke, coordf_t stroke_width)
{
for (Lines::const_iterator it = lines.begin(); it != lines.end(); ++it)
- this->draw(*it, stroke);
+ this->draw(*it, stroke, stroke_width);
}
void
@@ -91,7 +91,7 @@ SVG::draw(const ExPolygon &expolygon, std::string fill)
for (Polygons::const_iterator p = pp.begin(); p != pp.end(); ++p) {
d += this->get_path_d(*p, true) + " ";
}
- this->path(d, true);
+ this->path(d, true, 0);
}
void
@@ -105,7 +105,7 @@ void
SVG::draw(const Polygon &polygon, std::string fill)
{
this->fill = fill;
- this->path(this->get_path_d(polygon, true), !fill.empty());
+ this->path(this->get_path_d(polygon, true), !fill.empty(), 0);
}
void
@@ -116,34 +116,34 @@ SVG::draw(const Polygons &polygons, std::string fill)
}
void
-SVG::draw(const Polyline &polyline, std::string stroke, coord_t stroke_width)
+SVG::draw(const Polyline &polyline, std::string stroke, coordf_t stroke_width)
{
this->stroke = stroke;
this->path(this->get_path_d(polyline, false), false, stroke_width);
}
void
-SVG::draw(const Polylines &polylines, std::string stroke, coord_t stroke_width)
+SVG::draw(const Polylines &polylines, std::string stroke, coordf_t stroke_width)
{
for (Polylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it)
this->draw(*it, fill, stroke_width);
}
-void SVG::draw(const ThickLines &thicklines, const std::string &fill, const std::string &stroke, coord_t stroke_width)
+void SVG::draw(const ThickLines &thicklines, const std::string &fill, const std::string &stroke, coordf_t stroke_width)
{
for (ThickLines::const_iterator it = thicklines.begin(); it != thicklines.end(); ++it)
this->draw(*it, fill, stroke, stroke_width);
}
void
-SVG::draw(const ThickPolylines &polylines, const std::string &stroke, coord_t stroke_width)
+SVG::draw(const ThickPolylines &polylines, const std::string &stroke, coordf_t stroke_width)
{
for (ThickPolylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it)
this->draw((Polyline)*it, stroke, stroke_width);
}
void
-SVG::draw(const ThickPolylines &thickpolylines, const std::string &fill, const std::string &stroke, coord_t stroke_width)
+SVG::draw(const ThickPolylines &thickpolylines, const std::string &fill, const std::string &stroke, coordf_t stroke_width)
{
for (ThickPolylines::const_iterator it = thickpolylines.begin(); it != thickpolylines.end(); ++ it)
draw(it->thicklines(), fill, stroke, stroke_width);
@@ -168,8 +168,36 @@ SVG::draw(const Points &points, std::string fill, coord_t radius)
this->draw(*it, fill, radius);
}
+void
+SVG::draw(const ClipperLib::Path &polygon, double scale, std::string stroke, coordf_t stroke_width)
+{
+ this->stroke = stroke;
+ this->path(this->get_path_d(polygon, scale, true), false, stroke_width);
+}
+
+void
+SVG::draw(const ClipperLib::Paths &polygons, double scale, std::string stroke, coordf_t stroke_width)
+{
+ for (ClipperLib::Paths::const_iterator it = polygons.begin(); it != polygons.end(); ++ it)
+ draw(*it, scale, stroke, stroke_width);
+}
+
+void
+SVG::draw_outline(const Polygon &polygon, std::string stroke, coordf_t stroke_width)
+{
+ this->stroke = stroke;
+ this->path(this->get_path_d(polygon, true), false, stroke_width);
+}
+
+void
+SVG::draw_outline(const Polygons &polygons, std::string stroke, coordf_t stroke_width)
+{
+ for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++ it)
+ draw_outline(*it, stroke, stroke_width);
+}
+
void
-SVG::path(const std::string &d, bool fill, coord_t stroke_width)
+SVG::path(const std::string &d, bool fill, coordf_t stroke_width)
{
float lineWidth = 0.f;
if (! fill)
@@ -199,6 +227,19 @@ SVG::get_path_d(const MultiPoint &mp, bool closed) const
return d.str();
}
+std::string
+SVG::get_path_d(const ClipperLib::Path &path, double scale, bool closed) const
+{
+ std::ostringstream d;
+ d << "M ";
+ for (ClipperLib::Path::const_iterator p = path.begin(); p != path.end(); ++p) {
+ d << COORD(scale * p->X - origin.x) << " ";
+ d << COORD(scale * p->Y - origin.y) << " ";
+ }
+ if (closed) d << "z";
+ return d.str();
+}
+
void
SVG::Close()
{
diff --git a/xs/src/libslic3r/SVG.hpp b/xs/src/libslic3r/SVG.hpp
index aa08c0e20..5388b1b03 100644
--- a/xs/src/libslic3r/SVG.hpp
+++ b/xs/src/libslic3r/SVG.hpp
@@ -2,6 +2,7 @@
#define slic3r_SVG_hpp_
#include "libslic3r.h"
+#include "clipper.hpp"
#include "ExPolygon.hpp"
#include "Line.hpp"
#include "TriangleMesh.hpp"
@@ -14,34 +15,43 @@ class SVG
bool arrows;
std::string fill, stroke;
Point origin;
+ bool flipY;
SVG(const char* filename);
- SVG(const char* filename, const BoundingBox &bbox);
+ SVG(const char* filename, const BoundingBox &bbox, const coord_t bbox_offset = scale_(1.), bool flipY = false);
~SVG() { if (f != NULL) Close(); }
- void draw(const Line &line, std::string stroke = "black", coord_t stroke_width = 0);
- void draw(const ThickLine &line, const std::string &fill, const std::string &stroke, coord_t stroke_width = 0);
- void draw(const Lines &lines, std::string stroke = "black");
+ void draw(const Line &line, std::string stroke = "black", coordf_t stroke_width = 0);
+ void draw(const ThickLine &line, const std::string &fill, const std::string &stroke, coordf_t stroke_width = 0);
+ void draw(const Lines &lines, std::string stroke = "black", coordf_t stroke_width = 0);
void draw(const IntersectionLines &lines, std::string stroke = "black");
void draw(const ExPolygon &expolygon, std::string fill = "grey");
void draw(const ExPolygons &expolygons, std::string fill = "grey");
void draw(const Polygon &polygon, std::string fill = "grey");
+ void draw_outline(const Polygon &polygon, std::string stroke = "black", coordf_t stroke_width = 0);
void draw(const Polygons &polygons, std::string fill = "grey");
- void draw(const Polyline &polyline, std::string stroke = "black", coord_t stroke_width = 0);
- void draw(const Polylines &polylines, std::string stroke = "black", coord_t stroke_width = 0);
- void draw(const ThickLines &thicklines, const std::string &fill = "lime", const std::string &stroke = "black", coord_t stroke_width = 0);
- void draw(const ThickPolylines &polylines, const std::string &stroke = "black", coord_t stroke_width = 0);
- void draw(const ThickPolylines &thickpolylines, const std::string &fill, const std::string &stroke, coord_t stroke_width);
+ void draw_outline(const Polygons &polygons, std::string stroke = "black", coordf_t stroke_width = 0);
+ void draw(const Polyline &polyline, std::string stroke = "black", coordf_t stroke_width = 0);
+ void draw(const Polylines &polylines, std::string stroke = "black", coordf_t stroke_width = 0);
+ void draw(const ThickLines &thicklines, const std::string &fill = "lime", const std::string &stroke = "black", coordf_t stroke_width = 0);
+ void draw(const ThickPolylines &polylines, const std::string &stroke = "black", coordf_t stroke_width = 0);
+ void draw(const ThickPolylines &thickpolylines, const std::string &fill, const std::string &stroke, coordf_t stroke_width);
void draw(const Point &point, std::string fill = "black", coord_t radius = 0);
void draw(const Points &points, std::string fill = "black", coord_t radius = 0);
+
+ // Support for rendering the ClipperLib paths
+ void draw(const ClipperLib::Path &polygon, double scale, std::string fill = "grey", coordf_t stroke_width = 0);
+ void draw(const ClipperLib::Paths &polygons, double scale, std::string fill = "grey", coordf_t stroke_width = 0);
+
void Close();
private:
std::string filename;
FILE* f;
- void path(const std::string &d, bool fill, coord_t stroke_width = 0);
+ void path(const std::string &d, bool fill, coordf_t stroke_width);
std::string get_path_d(const MultiPoint &mp, bool closed = false) const;
+ std::string get_path_d(const ClipperLib::Path &mp, double scale, bool closed = false) const;
};
}
diff --git a/xs/src/libslic3r/Surface.cpp b/xs/src/libslic3r/Surface.cpp
index 4d2234e4d..5df2dd99a 100644
--- a/xs/src/libslic3r/Surface.cpp
+++ b/xs/src/libslic3r/Surface.cpp
@@ -1,3 +1,4 @@
+#include "BoundingBox.hpp"
#include "Surface.hpp"
namespace Slic3r {
@@ -54,4 +55,31 @@ Surface::is_bridge() const
|| this->surface_type == stInternalBridge;
}
+BoundingBox get_extents(const Surface &surface)
+{
+ return get_extents(surface.expolygon.contour);
+}
+
+BoundingBox get_extents(const Surfaces &surfaces)
+{
+ BoundingBox bbox;
+ if (! surfaces.empty()) {
+ bbox = get_extents(surfaces.front());
+ for (size_t i = 1; i < surfaces.size(); ++ i)
+ bbox.merge(get_extents(surfaces[i]));
+ }
+ return bbox;
+}
+
+BoundingBox get_extents(const SurfacesPtr &surfaces)
+{
+ BoundingBox bbox;
+ if (! surfaces.empty()) {
+ bbox = get_extents(*surfaces.front());
+ for (size_t i = 1; i < surfaces.size(); ++ i)
+ bbox.merge(get_extents(*surfaces[i]));
+ }
+ return bbox;
+}
+
}
diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp
index 21395bdc6..00286c207 100644
--- a/xs/src/libslic3r/Surface.hpp
+++ b/xs/src/libslic3r/Surface.hpp
@@ -34,6 +34,10 @@ class Surface
typedef std::vector<Surface> Surfaces;
typedef std::vector<Surface*> SurfacesPtr;
+extern BoundingBox get_extents(const Surface &surface);
+extern BoundingBox get_extents(const Surfaces &surfaces);
+extern BoundingBox get_extents(const SurfacesPtr &surfaces);
+
}
#endif
diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index a087455cf..680716bb8 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -8,12 +8,22 @@
#define SLIC3R_VERSION "1.3.0-dev"
+//FIXME This epsilon value is used for many non-related purposes:
+// For a threshold of a squared Euclidean distance,
+// for a trheshold in a difference of radians,
+// for a threshold of a cross product of two non-normalized vectors etc.
#define EPSILON 1e-4
+// Scaling factor for a conversion from coord_t to coordf_t: 10e-6
+// This scaling generates a following fixed point representation with for a 32bit integer:
+// 0..4294mm with 1nm resolution
#define SCALING_FACTOR 0.000001
+// RESOLUTION, SCALED_RESOLUTION: Used as an error threshold for a Douglas-Peucker polyline simplification algorithm.
#define RESOLUTION 0.0125
#define SCALED_RESOLUTION (RESOLUTION / SCALING_FACTOR)
#define PI 3.141592653589793238
+// When extruding a closed loop, the loop is interrupted and shortened a bit to reduce the seam.
#define LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER 0.15
+// Maximum perimeter length for the loop to apply the small perimeter speed.
#define SMALL_PERIMETER_LENGTH (6.5 / SCALING_FACTOR) * 2 * PI
#define INSET_OVERLAP_TOLERANCE 0.4
#define EXTERNAL_INFILL_MARGIN 3