Ported from the playground branch. Various documentation and optimization.
This commit is contained in:
parent
a5b7f14dfa
commit
620c6c7378
@ -68,6 +68,26 @@ BoundingBox::polygon() const
|
|||||||
return p;
|
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 ¢er) 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
|
template <class PointClass> void
|
||||||
BoundingBoxBase<PointClass>::scale(double factor)
|
BoundingBoxBase<PointClass>::scale(double factor)
|
||||||
{
|
{
|
||||||
@ -163,6 +183,26 @@ BoundingBox3Base<PointClass>::size() const
|
|||||||
}
|
}
|
||||||
template Pointf3 BoundingBox3Base<Pointf3>::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
|
template <class PointClass> void
|
||||||
BoundingBoxBase<PointClass>::translate(coordf_t x, coordf_t y)
|
BoundingBoxBase<PointClass>::translate(coordf_t x, coordf_t y)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,7 @@ class BoundingBoxBase
|
|||||||
void merge(const BoundingBoxBase<PointClass> &bb);
|
void merge(const BoundingBoxBase<PointClass> &bb);
|
||||||
void scale(double factor);
|
void scale(double factor);
|
||||||
PointClass size() const;
|
PointClass size() const;
|
||||||
|
double radius() const;
|
||||||
void translate(coordf_t x, coordf_t y);
|
void translate(coordf_t x, coordf_t y);
|
||||||
void offset(coordf_t delta);
|
void offset(coordf_t delta);
|
||||||
PointClass center() const;
|
PointClass center() const;
|
||||||
@ -44,6 +45,7 @@ class BoundingBox3Base : public BoundingBoxBase<PointClass>
|
|||||||
void merge(const std::vector<PointClass> &points);
|
void merge(const std::vector<PointClass> &points);
|
||||||
void merge(const BoundingBox3Base<PointClass> &bb);
|
void merge(const BoundingBox3Base<PointClass> &bb);
|
||||||
PointClass size() const;
|
PointClass size() const;
|
||||||
|
double radius() const;
|
||||||
void translate(coordf_t x, coordf_t y, coordf_t z);
|
void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||||
void offset(coordf_t delta);
|
void offset(coordf_t delta);
|
||||||
PointClass center() const;
|
PointClass center() const;
|
||||||
@ -54,6 +56,10 @@ class BoundingBox : public BoundingBoxBase<Point>
|
|||||||
public:
|
public:
|
||||||
void polygon(Polygon* polygon) const;
|
void polygon(Polygon* polygon) const;
|
||||||
Polygon polygon() const;
|
Polygon polygon() const;
|
||||||
|
BoundingBox rotated(double angle) const;
|
||||||
|
BoundingBox rotated(double angle, const Point ¢er) const;
|
||||||
|
void rotate(double angle) { (*this) = this->rotated(angle); }
|
||||||
|
void rotate(double angle, const Point ¢er) { (*this) = this->rotated(angle, center); }
|
||||||
|
|
||||||
BoundingBox() : BoundingBoxBase<Point>() {};
|
BoundingBox() : BoundingBoxBase<Point>() {};
|
||||||
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {};
|
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>
|
template<typename VT>
|
||||||
inline bool empty(const BoundingBox3Base<VT> &bb)
|
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
|
#endif
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
|
|
||||||
|
// #define CLIPPER_UTILS_DEBUG
|
||||||
|
|
||||||
|
#ifdef CLIPPER_UTILS_DEBUG
|
||||||
|
#include "SVG.hpp"
|
||||||
|
#endif /* CLIPPER_UTILS_DEBUG */
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
@ -226,6 +232,19 @@ void
|
|||||||
offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
|
offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
|
||||||
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
|
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
|
// read input
|
||||||
ClipperLib::Paths input;
|
ClipperLib::Paths input;
|
||||||
Slic3rMultiPoints_to_ClipperPaths(polygons, &input);
|
Slic3rMultiPoints_to_ClipperPaths(polygons, &input);
|
||||||
@ -245,12 +264,18 @@ offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float
|
|||||||
ClipperLib::Paths output1;
|
ClipperLib::Paths output1;
|
||||||
co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
|
co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
|
||||||
co.Execute(output1, (delta1*scale));
|
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
|
// perform second offset
|
||||||
co.Clear();
|
co.Clear();
|
||||||
co.AddPaths(output1, joinType, ClipperLib::etClosedPolygon);
|
co.AddPaths(output1, joinType, ClipperLib::etClosedPolygon);
|
||||||
co.Execute(*retval, (delta2*scale));
|
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
|
// unscale output
|
||||||
scaleClipperPolygons(*retval, 1/scale);
|
scaleClipperPolygons(*retval, 1/scale);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@ using ClipperLib::jtSquare;
|
|||||||
|
|
||||||
namespace Slic3r {
|
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
|
#define CLIPPER_OFFSET_SCALE 100000.0
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
@ -39,8 +39,8 @@ ConfigDef::add(const t_config_option_key &opt_key, ConfigOptionType type)
|
|||||||
const ConfigOptionDef*
|
const ConfigOptionDef*
|
||||||
ConfigDef::get(const t_config_option_key &opt_key) const
|
ConfigDef::get(const t_config_option_key &opt_key) const
|
||||||
{
|
{
|
||||||
if (this->options.count(opt_key) == 0) return NULL;
|
t_optiondef_map::iterator it = const_cast<ConfigDef*>(this)->options.find(opt_key);
|
||||||
return &const_cast<ConfigDef*>(this)->options[opt_key];
|
return (it == this->options.end()) ? NULL : &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -113,6 +113,8 @@ ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str)
|
|||||||
return opt->deserialize(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
|
double
|
||||||
ConfigBase::get_abs_value(const t_config_option_key &opt_key) {
|
ConfigBase::get_abs_value(const t_config_option_key &opt_key) {
|
||||||
ConfigOption* opt = this->option(opt_key, false);
|
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
|
double
|
||||||
ConfigBase::get_abs_value(const t_config_option_key &opt_key, double ratio_over) {
|
ConfigBase::get_abs_value(const t_config_option_key &opt_key, double ratio_over) {
|
||||||
// get stored option value
|
// get stored option value
|
||||||
@ -180,6 +184,7 @@ DynamicConfig& DynamicConfig::operator= (DynamicConfig other)
|
|||||||
void
|
void
|
||||||
DynamicConfig::swap(DynamicConfig &other)
|
DynamicConfig::swap(DynamicConfig &other)
|
||||||
{
|
{
|
||||||
|
std::swap(this->def, other.def);
|
||||||
std::swap(this->options, other.options);
|
std::swap(this->options, other.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +202,8 @@ DynamicConfig::DynamicConfig (const DynamicConfig& other) {
|
|||||||
|
|
||||||
ConfigOption*
|
ConfigOption*
|
||||||
DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) {
|
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) {
|
if (create) {
|
||||||
const ConfigOptionDef* optdef = this->def->get(opt_key);
|
const ConfigOptionDef* optdef = this->def->get(opt_key);
|
||||||
assert(optdef != NULL);
|
assert(optdef != NULL);
|
||||||
@ -239,7 +245,7 @@ DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this->options[opt_key];
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -273,7 +279,6 @@ StaticConfig::set_defaults()
|
|||||||
t_config_option_keys keys = this->keys();
|
t_config_option_keys keys = this->keys();
|
||||||
for (t_config_option_keys::const_iterator it = keys.begin(); it != keys.end(); ++it) {
|
for (t_config_option_keys::const_iterator it = keys.begin(); it != keys.end(); ++it) {
|
||||||
const ConfigOptionDef* def = this->def->get(*it);
|
const ConfigOptionDef* def = this->def->get(*it);
|
||||||
|
|
||||||
if (def->default_value != NULL)
|
if (def->default_value != NULL)
|
||||||
this->option(*it)->set(*def->default_value);
|
this->option(*it)->set(*def->default_value);
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,11 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
// Name of the configuration option.
|
||||||
typedef std::string t_config_option_key;
|
typedef std::string t_config_option_key;
|
||||||
typedef std::vector<std::string> t_config_option_keys;
|
typedef std::vector<std::string> t_config_option_keys;
|
||||||
|
|
||||||
|
// A generic value of a configuration option.
|
||||||
class ConfigOption {
|
class ConfigOption {
|
||||||
public:
|
public:
|
||||||
virtual ~ConfigOption() {};
|
virtual ~ConfigOption() {};
|
||||||
@ -31,6 +33,7 @@ class ConfigOption {
|
|||||||
friend bool operator!= (const ConfigOption &a, const ConfigOption &b);
|
friend bool operator!= (const ConfigOption &a, const ConfigOption &b);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Value of a single valued option (bool, int, float, string, point, enum)
|
||||||
template <class T>
|
template <class T>
|
||||||
class ConfigOptionSingle : public ConfigOption {
|
class ConfigOptionSingle : public ConfigOption {
|
||||||
public:
|
public:
|
||||||
@ -44,12 +47,14 @@ class ConfigOptionSingle : public ConfigOption {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Value of a vector valued option (bools, ints, floats, strings, points)
|
||||||
class ConfigOptionVectorBase : public ConfigOption {
|
class ConfigOptionVectorBase : public ConfigOption {
|
||||||
public:
|
public:
|
||||||
virtual ~ConfigOptionVectorBase() {};
|
virtual ~ConfigOptionVectorBase() {};
|
||||||
virtual std::vector<std::string> vserialize() const = 0;
|
virtual std::vector<std::string> vserialize() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Value of a vector valued option (bools, ints, floats, strings, points), template
|
||||||
template <class T>
|
template <class T>
|
||||||
class ConfigOptionVector : public ConfigOptionVectorBase
|
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;
|
typedef std::map<std::string,int> t_config_enum_values;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -461,11 +467,14 @@ class ConfigOptionEnum : public ConfigOptionSingle<T>
|
|||||||
return true;
|
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();
|
static t_config_enum_values get_enum_values();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* We use this one in DynamicConfig objects, otherwise it's better to use
|
// Generic enum configuration value.
|
||||||
the specialized ConfigOptionEnum<T> containers. */
|
// 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
|
class ConfigOptionEnumGeneric : public ConfigOptionInt
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -485,57 +494,117 @@ class ConfigOptionEnumGeneric : public ConfigOptionInt
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Type of a configuration value.
|
||||||
enum ConfigOptionType {
|
enum ConfigOptionType {
|
||||||
coNone,
|
coNone,
|
||||||
|
// single float
|
||||||
coFloat,
|
coFloat,
|
||||||
|
// vector of floats
|
||||||
coFloats,
|
coFloats,
|
||||||
|
// single int
|
||||||
coInt,
|
coInt,
|
||||||
|
// vector of ints
|
||||||
coInts,
|
coInts,
|
||||||
|
// single string
|
||||||
coString,
|
coString,
|
||||||
|
// vector of strings
|
||||||
coStrings,
|
coStrings,
|
||||||
|
// percent value. Currently only used for infill.
|
||||||
coPercent,
|
coPercent,
|
||||||
|
// a fraction or an absolute value
|
||||||
coFloatOrPercent,
|
coFloatOrPercent,
|
||||||
|
// single 2d point. Currently not used.
|
||||||
coPoint,
|
coPoint,
|
||||||
|
// vector of 2d points. Currently used for the definition of the print bed and for the extruder offsets.
|
||||||
coPoints,
|
coPoints,
|
||||||
|
// single boolean value
|
||||||
coBool,
|
coBool,
|
||||||
|
// vector of boolean values
|
||||||
coBools,
|
coBools,
|
||||||
|
// a generic enum
|
||||||
coEnum,
|
coEnum,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Definition of a configuration value for the purpose of GUI presentation, editing, value mapping and config file handling.
|
||||||
class ConfigOptionDef
|
class ConfigOptionDef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// What type? bool, int, string etc.
|
||||||
ConfigOptionType type;
|
ConfigOptionType type;
|
||||||
|
// Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor.
|
||||||
ConfigOption* default_value;
|
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;
|
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;
|
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 label;
|
||||||
std::string full_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;
|
std::string category;
|
||||||
|
// A tooltip text shown in the GUI.
|
||||||
std::string tooltip;
|
std::string tooltip;
|
||||||
|
// Text right from the input field, usually a unit of measurement.
|
||||||
std::string sidetext;
|
std::string sidetext;
|
||||||
|
// Format of this parameter on a command line.
|
||||||
std::string cli;
|
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;
|
t_config_option_key ratio_over;
|
||||||
|
// True for multiline strings.
|
||||||
bool multiline;
|
bool multiline;
|
||||||
|
// For text input: If true, the GUI text box spans the complete page width.
|
||||||
bool full_width;
|
bool full_width;
|
||||||
|
// Not editable. Currently only used for the display of the number of threads.
|
||||||
bool readonly;
|
bool readonly;
|
||||||
|
// Height of a multiline GUI text box.
|
||||||
int height;
|
int height;
|
||||||
|
// Optional width of an input field.
|
||||||
int width;
|
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 min;
|
||||||
int max;
|
int max;
|
||||||
|
// Legacy names for this configuration option.
|
||||||
|
// Used when parsing legacy configuration file.
|
||||||
std::vector<t_config_option_key> aliases;
|
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;
|
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_values;
|
||||||
std::vector<std::string> enum_labels;
|
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;
|
t_config_enum_values enum_keys_map;
|
||||||
|
|
||||||
ConfigOptionDef() : type(coNone), default_value(NULL),
|
ConfigOptionDef() : type(coNone), default_value(NULL),
|
||||||
multiline(false), full_width(false), readonly(false),
|
multiline(false), full_width(false), readonly(false),
|
||||||
height(-1), width(-1), min(INT_MIN), max(INT_MAX) {};
|
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;
|
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
|
class ConfigDef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -545,9 +614,14 @@ class ConfigDef
|
|||||||
const ConfigOptionDef* get(const t_config_option_key &opt_key) const;
|
const ConfigOptionDef* get(const t_config_option_key &opt_key) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An abstract configuration store.
|
||||||
class ConfigBase
|
class ConfigBase
|
||||||
{
|
{
|
||||||
public:
|
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;
|
const ConfigDef* def;
|
||||||
|
|
||||||
ConfigBase() : def(NULL) {};
|
ConfigBase() : def(NULL) {};
|
||||||
@ -562,11 +636,14 @@ class ConfigBase
|
|||||||
t_config_option_keys diff(ConfigBase &other);
|
t_config_option_keys diff(ConfigBase &other);
|
||||||
std::string serialize(const t_config_option_key &opt_key) const;
|
std::string serialize(const t_config_option_key &opt_key) const;
|
||||||
bool set_deserialize(const t_config_option_key &opt_key, std::string str);
|
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 get_abs_value(const t_config_option_key &opt_key, double ratio_over);
|
double get_abs_value(const t_config_option_key &opt_key, double ratio_over);
|
||||||
void setenv_();
|
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
|
class DynamicConfig : public virtual ConfigBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -585,13 +662,20 @@ class DynamicConfig : public virtual ConfigBase
|
|||||||
t_options_map options;
|
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
|
class StaticConfig : public virtual ConfigBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StaticConfig() : ConfigBase() {};
|
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;
|
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();
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -514,4 +514,20 @@ ExPolygon::dump_perl() const
|
|||||||
return ret.str();
|
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
|
||||||
|
@ -72,7 +72,10 @@ inline Polygons to_polygons(ExPolygons &&src)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
extern BoundingBox get_extents(const ExPolygon &expolygon);
|
||||||
|
extern BoundingBox get_extents(const ExPolygons &expolygons);
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
// start Boost
|
// start Boost
|
||||||
#include <boost/polygon/polygon.hpp>
|
#include <boost/polygon/polygon.hpp>
|
||||||
|
@ -128,4 +128,9 @@ ExPolygonCollection::append(const ExPolygons &expp)
|
|||||||
this->expolygons.insert(this->expolygons.end(), expp.begin(), expp.end());
|
this->expolygons.insert(this->expolygons.end(), expp.begin(), expp.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox get_extents(const ExPolygonCollection &expolygon)
|
||||||
|
{
|
||||||
|
return get_extents(expolygon.expolygons);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ class ExPolygonCollection
|
|||||||
void append(const ExPolygons &expolygons);
|
void append(const ExPolygons &expolygons);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern BoundingBox get_extents(const ExPolygonCollection &expolygon);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Optimize the extrusion simulator to the bones.
|
// Optimize the extrusion simulator to the bones.
|
||||||
#pragma GCC optimize ("O3")
|
//#pragma GCC optimize ("O3")
|
||||||
#undef SLIC3R_DEBUG
|
//#undef SLIC3R_DEBUG
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -640,7 +640,7 @@ struct Cell
|
|||||||
// Height of the covered part in excess to the expected layer height.
|
// Height of the covered part in excess to the expected layer height.
|
||||||
float excess_height;
|
float excess_height;
|
||||||
|
|
||||||
bool operator<(const Cell &c2) {
|
bool operator<(const Cell &c2) const {
|
||||||
return this->excess_height < c2.excess_height;
|
return this->excess_height < c2.excess_height;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#define slic3r_ExtrusionSimulator_hpp_
|
#define slic3r_ExtrusionSimulator_hpp_
|
||||||
|
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
#include "Config.hpp"
|
|
||||||
#include "ExtrusionEntity.hpp"
|
#include "ExtrusionEntity.hpp"
|
||||||
#include "BoundingBox.hpp"
|
#include "BoundingBox.hpp"
|
||||||
|
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
// We want our version of assert.
|
// We want our version of assert.
|
||||||
#include "../libslic3r.h"
|
#include "../libslic3r.h"
|
||||||
|
|
||||||
|
#ifndef myassert
|
||||||
|
#define myassert assert
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
#ifndef clamp
|
#ifndef clamp
|
||||||
|
@ -78,6 +78,9 @@ class GCode {
|
|||||||
Wipe wipe;
|
Wipe wipe;
|
||||||
AvoidCrossingPerimeters avoid_crossing_perimeters;
|
AvoidCrossingPerimeters avoid_crossing_perimeters;
|
||||||
bool enable_loop_clipping;
|
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;
|
bool enable_cooling_markers;
|
||||||
// Markers for the Pressure Equalizer to recognize the extrusion type.
|
// Markers for the Pressure Equalizer to recognize the extrusion type.
|
||||||
// The Pressure Equalizer removes the markers from the final G-code.
|
// The Pressure Equalizer removes the markers from the final G-code.
|
||||||
@ -89,6 +92,10 @@ class GCode {
|
|||||||
// Distance Field structure to
|
// Distance Field structure to
|
||||||
EdgeGrid::Grid *_lower_layer_edge_grid;
|
EdgeGrid::Grid *_lower_layer_edge_grid;
|
||||||
bool first_layer; // this flag triggers first layer speeds
|
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
|
float elapsed_time; // seconds
|
||||||
double volumetric_speed;
|
double volumetric_speed;
|
||||||
// Support for the extrusion role markers. Which marker is active?
|
// Support for the extrusion role markers. Which marker is active?
|
||||||
|
@ -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;
|
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
|
void
|
||||||
Layer::make_perimeters()
|
Layer::make_perimeters()
|
||||||
{
|
{
|
||||||
|
@ -77,6 +77,7 @@ LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection*
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (this->layer()->lower_layer != NULL)
|
if (this->layer()->lower_layer != NULL)
|
||||||
|
// Cummulative sum of polygons over all the regions.
|
||||||
g.lower_slices = &this->layer()->lower_layer->slices;
|
g.lower_slices = &this->layer()->lower_layer->slices;
|
||||||
|
|
||||||
g.layer_id = this->layer()->id();
|
g.layer_id = this->layer()->id();
|
||||||
|
@ -772,7 +772,7 @@ ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
|
|||||||
void
|
void
|
||||||
ModelInstance::transform_polygon(Polygon* polygon) const
|
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
|
polygon->scale(this->scaling_factor); // scale around polygon origin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,10 +27,18 @@ typedef std::vector<ModelObject*> ModelObjectPtrs;
|
|||||||
typedef std::vector<ModelVolume*> ModelVolumePtrs;
|
typedef std::vector<ModelVolume*> ModelVolumePtrs;
|
||||||
typedef std::vector<ModelInstance*> ModelInstancePtrs;
|
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
|
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;
|
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;
|
ModelObjectPtrs objects;
|
||||||
|
|
||||||
Model();
|
Model();
|
||||||
@ -63,34 +71,48 @@ class Model
|
|||||||
void duplicate_objects_grid(size_t x, size_t y, coordf_t dist);
|
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
|
class ModelMaterial
|
||||||
{
|
{
|
||||||
friend class Model;
|
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;
|
t_model_material_attributes attributes;
|
||||||
|
// Dynamic configuration storage for the object specific configuration values, overriding the global configuration.
|
||||||
DynamicPrintConfig config;
|
DynamicPrintConfig config;
|
||||||
|
|
||||||
Model* get_model() const { return this->model; };
|
Model* get_model() const { return this->model; };
|
||||||
void apply(const t_model_material_attributes &attributes);
|
void apply(const t_model_material_attributes &attributes);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Parent, owning this material.
|
||||||
Model* model;
|
Model* model;
|
||||||
|
|
||||||
ModelMaterial(Model *model);
|
ModelMaterial(Model *model);
|
||||||
ModelMaterial(Model *model, const ModelMaterial &other);
|
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
|
class ModelObject
|
||||||
{
|
{
|
||||||
friend class Model;
|
friend class Model;
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string input_file;
|
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;
|
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;
|
ModelVolumePtrs volumes;
|
||||||
|
// Configuration parameters specific to a single ModelObject, overriding the global Slic3r settings.
|
||||||
DynamicPrintConfig config;
|
DynamicPrintConfig config;
|
||||||
|
// Variation of a layer thickness for spans of Z coordinates.
|
||||||
t_layer_height_ranges layer_height_ranges;
|
t_layer_height_ranges layer_height_ranges;
|
||||||
|
|
||||||
/* This vector accumulates the total translation applied to the object by the
|
/* This vector accumulates the total translation applied to the object by the
|
||||||
center_around_origin() method. Callers might want to apply the same translation
|
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
|
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 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
|
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;
|
Model* model;
|
||||||
|
|
||||||
ModelObject(Model *model);
|
ModelObject(Model *model);
|
||||||
@ -144,15 +167,22 @@ class ModelObject
|
|||||||
~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
|
class ModelVolume
|
||||||
{
|
{
|
||||||
friend class ModelObject;
|
friend class ModelObject;
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
|
// The triangular model.
|
||||||
TriangleMesh mesh;
|
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;
|
DynamicPrintConfig config;
|
||||||
|
// Is it an object to be printed, or a modifier volume?
|
||||||
bool modifier;
|
bool modifier;
|
||||||
|
|
||||||
|
// A parent object owning this modifier volume.
|
||||||
ModelObject* get_object() const { return this->object; };
|
ModelObject* get_object() const { return this->object; };
|
||||||
t_model_material_id material_id() const;
|
t_model_material_id material_id() const;
|
||||||
void material_id(t_model_material_id material_id);
|
void material_id(t_model_material_id material_id);
|
||||||
@ -161,7 +191,8 @@ class ModelVolume
|
|||||||
|
|
||||||
ModelMaterial* assign_unique_material();
|
ModelMaterial* assign_unique_material();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Parent object owning this ModelVolume.
|
||||||
ModelObject* object;
|
ModelObject* object;
|
||||||
t_model_material_id _material_id;
|
t_model_material_id _material_id;
|
||||||
|
|
||||||
@ -169,19 +200,25 @@ class ModelVolume
|
|||||||
ModelVolume(ModelObject *object, const ModelVolume &other);
|
ModelVolume(ModelObject *object, const ModelVolume &other);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A single instance of a ModelObject.
|
||||||
|
// Knows the affine transformation of an object.
|
||||||
class ModelInstance
|
class ModelInstance
|
||||||
{
|
{
|
||||||
friend class ModelObject;
|
friend class ModelObject;
|
||||||
public:
|
public:
|
||||||
double rotation; // in radians around mesh center point
|
double rotation; // Rotation around the Z axis, in radians around mesh center point
|
||||||
double scaling_factor;
|
double scaling_factor;
|
||||||
Pointf offset; // in unscaled coordinates
|
Pointf offset; // in unscaled coordinates
|
||||||
|
|
||||||
ModelObject* get_object() const { return this->object; };
|
ModelObject* get_object() const { return this->object; };
|
||||||
|
|
||||||
|
// To be called on an external mesh
|
||||||
void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const;
|
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;
|
void transform_polygon(Polygon* polygon) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Parent object, owning this instance.
|
||||||
ModelObject* object;
|
ModelObject* object;
|
||||||
|
|
||||||
ModelInstance(ModelObject *object);
|
ModelInstance(ModelObject *object);
|
||||||
|
@ -33,8 +33,8 @@ MultiPoint::translate(const Point &vector)
|
|||||||
void
|
void
|
||||||
MultiPoint::rotate(double angle)
|
MultiPoint::rotate(double angle)
|
||||||
{
|
{
|
||||||
double s = sin(angle);
|
double s = sin(angle);
|
||||||
double c = cos(angle);
|
double c = cos(angle);
|
||||||
for (Points::iterator it = points.begin(); it != points.end(); ++it) {
|
for (Points::iterator it = points.begin(); it != points.end(); ++it) {
|
||||||
double cur_x = (double)it->x;
|
double cur_x = (double)it->x;
|
||||||
double cur_y = (double)it->y;
|
double cur_y = (double)it->y;
|
||||||
@ -46,8 +46,13 @@ MultiPoint::rotate(double angle)
|
|||||||
void
|
void
|
||||||
MultiPoint::rotate(double angle, const Point ¢er)
|
MultiPoint::rotate(double angle, const Point ¢er)
|
||||||
{
|
{
|
||||||
|
double s = sin(angle);
|
||||||
|
double c = cos(angle);
|
||||||
for (Points::iterator it = points.begin(); it != points.end(); ++it) {
|
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;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox get_extents(const MultiPoint &mp)
|
||||||
|
{
|
||||||
|
return mp.bounding_box();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,8 @@ class MultiPoint
|
|||||||
static Points _douglas_peucker(const Points &points, const double tolerance);
|
static Points _douglas_peucker(const Points &points, const double tolerance);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
extern BoundingBox get_extents(const MultiPoint &mp);
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -533,12 +533,6 @@ PerimeterGenerator::_variable_width(const ThickPolylines &polylines, ExtrusionRo
|
|||||||
return coll;
|
return coll;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
PerimeterGeneratorLoop::is_external() const
|
|
||||||
{
|
|
||||||
return this->depth == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PerimeterGeneratorLoop::is_internal_contour() const
|
PerimeterGeneratorLoop::is_internal_contour() const
|
||||||
{
|
{
|
||||||
|
@ -11,25 +11,33 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class PerimeterGeneratorLoop;
|
// Hierarchy of perimeters.
|
||||||
typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
|
|
||||||
|
|
||||||
class PerimeterGeneratorLoop {
|
class PerimeterGeneratorLoop {
|
||||||
public:
|
public:
|
||||||
|
// Polygon of this contour.
|
||||||
Polygon polygon;
|
Polygon polygon;
|
||||||
|
// Is it a contour or a hole?
|
||||||
|
// Contours are CCW oriented, holes are CW oriented.
|
||||||
bool is_contour;
|
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;
|
unsigned short depth;
|
||||||
|
// Children contour, may be both CCW and CW oriented (outer contours or holes).
|
||||||
std::vector<PerimeterGeneratorLoop> children;
|
std::vector<PerimeterGeneratorLoop> children;
|
||||||
|
|
||||||
PerimeterGeneratorLoop(Polygon polygon, unsigned short depth)
|
PerimeterGeneratorLoop(Polygon polygon, unsigned short depth)
|
||||||
: polygon(polygon), is_contour(false), depth(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;
|
bool is_internal_contour() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
|
||||||
|
|
||||||
class PerimeterGenerator {
|
class PerimeterGenerator {
|
||||||
public:
|
public:
|
||||||
|
// Inputs:
|
||||||
const SurfaceCollection* slices;
|
const SurfaceCollection* slices;
|
||||||
const ExPolygonCollection* lower_slices;
|
const ExPolygonCollection* lower_slices;
|
||||||
double layer_height;
|
double layer_height;
|
||||||
@ -41,14 +49,26 @@ class PerimeterGenerator {
|
|||||||
PrintRegionConfig* config;
|
PrintRegionConfig* config;
|
||||||
PrintObjectConfig* object_config;
|
PrintObjectConfig* object_config;
|
||||||
PrintConfig* print_config;
|
PrintConfig* print_config;
|
||||||
|
// Outputs:
|
||||||
ExtrusionEntityCollection* loops;
|
ExtrusionEntityCollection* loops;
|
||||||
ExtrusionEntityCollection* gap_fill;
|
ExtrusionEntityCollection* gap_fill;
|
||||||
SurfaceCollection* fill_surfaces;
|
SurfaceCollection* fill_surfaces;
|
||||||
|
|
||||||
PerimeterGenerator(const SurfaceCollection* slices, double layer_height, Flow flow,
|
PerimeterGenerator(
|
||||||
PrintRegionConfig* config, PrintObjectConfig* object_config,
|
// Input:
|
||||||
PrintConfig* print_config, ExtrusionEntityCollection* loops,
|
const SurfaceCollection* slices,
|
||||||
ExtrusionEntityCollection* gap_fill, SurfaceCollection* fill_surfaces)
|
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),
|
: slices(slices), lower_slices(NULL), layer_height(layer_height),
|
||||||
layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow),
|
layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow),
|
||||||
overhang_flow(flow), solid_infill_flow(flow),
|
overhang_flow(flow), solid_infill_flow(flow),
|
||||||
|
@ -94,6 +94,12 @@ Point::nearest_point_index(const Points &points) const
|
|||||||
return this->nearest_point_index(p);
|
return this->nearest_point_index(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline T sqr(const T x)
|
||||||
|
{
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Point::nearest_point_index(const PointConstPtrs &points) const
|
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) {
|
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
|
/* If the X distance of the candidate is > than the total distance of the
|
||||||
best previous candidate, we know we don't want it */
|
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 (distance != -1 && d > distance) continue;
|
||||||
|
|
||||||
/* If the Y distance of the candidate is > than the total distance of the
|
/* If the Y distance of the candidate is > than the total distance of the
|
||||||
best previous candidate, we know we don't want it */
|
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;
|
if (distance != -1 && d > distance) continue;
|
||||||
|
|
||||||
idx = it - points.begin();
|
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) {
|
for (Points::const_iterator p = points.begin(); p != points.end(); ++p) {
|
||||||
// distance from this to candidate
|
// 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
|
// 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 the total distance is greater than current min distance, ignore it
|
||||||
if (distance != -1 && d > distance) continue;
|
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
|
If theta is outside the interval [0,1], then one of the Line_Segment's endpoints
|
||||||
must be closest to calling Point.
|
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 lx = (double)(line.b.x - line.a.x);
|
||||||
/ ( (double)pow(line.b.x - line.a.x, 2) + (double)pow(line.b.y - line.a.y, 2) );
|
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)
|
if (0.0 <= theta && theta <= 1.0)
|
||||||
return theta * line.a + (1.0-theta) * line.b;
|
return theta * line.a + (1.0-theta) * line.b;
|
||||||
|
@ -44,6 +44,8 @@ class Point
|
|||||||
void translate(const Vector &vector);
|
void translate(const Vector &vector);
|
||||||
void rotate(double angle);
|
void rotate(double angle);
|
||||||
void rotate(double angle, const Point ¢er);
|
void rotate(double angle, const Point ¢er);
|
||||||
|
Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
|
||||||
|
Point rotated(double angle, const Point ¢er) 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(const Point &point) const { return this->x == point.x && this->y == point.y; }
|
||||||
bool coincides_with_epsilon(const Point &point) const;
|
bool coincides_with_epsilon(const Point &point) const;
|
||||||
int nearest_point_index(const Points &points) const;
|
int nearest_point_index(const Points &points) const;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "BoundingBox.hpp"
|
||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
#include "Polygon.hpp"
|
#include "Polygon.hpp"
|
||||||
#include "Polyline.hpp"
|
#include "Polyline.hpp"
|
||||||
@ -59,6 +60,7 @@ Polygon::split_at_vertex(const Point &point) const
|
|||||||
return Polyline();
|
return Polyline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split a closed polygon into an open polyline, with the split point duplicated at both ends.
|
||||||
Polyline
|
Polyline
|
||||||
Polygon::split_at_index(int index) const
|
Polygon::split_at_index(int index) const
|
||||||
{
|
{
|
||||||
@ -71,6 +73,7 @@ Polygon::split_at_index(int index) const
|
|||||||
return polyline;
|
return polyline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split a closed polygon into an open polyline, with the split point duplicated at both ends.
|
||||||
Polyline
|
Polyline
|
||||||
Polygon::split_at_first_point() const
|
Polygon::split_at_first_point() const
|
||||||
{
|
{
|
||||||
@ -131,6 +134,8 @@ Polygon::is_valid() const
|
|||||||
return this->points.size() >= 3;
|
return this->points.size() >= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Does an unoriented polygon contain a point?
|
||||||
|
// Tested by counting intersections along a horizontal line.
|
||||||
bool
|
bool
|
||||||
Polygon::contains(const Point &point) const
|
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 i = this->points.begin();
|
||||||
Points::const_iterator j = this->points.end() - 1;
|
Points::const_iterator j = this->points.end() - 1;
|
||||||
for (; i != this->points.end(); j = i++) {
|
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))
|
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) )
|
&& ((double)point.x < (double)(j->x - i->x) * (double)(point.y - i->y) / (double)(j->y - i->y) + (double)i->x) )
|
||||||
result = !result;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
@ -265,4 +281,20 @@ Polygon::convex_points(double angle) const
|
|||||||
return points;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,9 @@ class Polygon : public MultiPoint {
|
|||||||
Point last_point() const;
|
Point last_point() const;
|
||||||
virtual Lines lines() const;
|
virtual Lines lines() const;
|
||||||
Polyline split_at_vertex(const Point &point) 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;
|
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;
|
Polyline split_at_first_point() const;
|
||||||
Points equally_spaced_points(double distance) const;
|
Points equally_spaced_points(double distance) const;
|
||||||
double area() const;
|
double area() const;
|
||||||
@ -34,6 +36,8 @@ class Polygon : public MultiPoint {
|
|||||||
bool make_counter_clockwise();
|
bool make_counter_clockwise();
|
||||||
bool make_clockwise();
|
bool make_clockwise();
|
||||||
bool is_valid() const;
|
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;
|
bool contains(const Point &point) const;
|
||||||
Polygons simplify(double tolerance) const;
|
Polygons simplify(double tolerance) const;
|
||||||
void simplify(double tolerance, Polygons &polygons) const;
|
void simplify(double tolerance, Polygons &polygons) const;
|
||||||
@ -44,6 +48,9 @@ class Polygon : public MultiPoint {
|
|||||||
Points convex_points(double angle = PI) const;
|
Points convex_points(double angle = PI) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern BoundingBox get_extents(const Polygon &poly);
|
||||||
|
extern BoundingBox get_extents(const Polygons &polygons);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// start Boost
|
// start Boost
|
||||||
|
@ -639,7 +639,7 @@ Print::validate() const
|
|||||||
if (!object_height.empty() && object_height.back() > scale_(this->config.extruder_clearance_height.value))
|
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.");
|
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) {
|
if (this->config.spiral_vase) {
|
||||||
size_t total_copies_count = 0;
|
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();
|
size_t extruders = this->config.nozzle_diameter.values.size();
|
||||||
for (ModelVolumePtrs::const_iterator v = model_object->volumes.begin(); v != model_object->volumes.end(); ++v) {
|
for (ModelVolumePtrs::const_iterator v = model_object->volumes.begin(); v != model_object->volumes.end(); ++v) {
|
||||||
if (!(*v)->material_id().empty()) {
|
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;
|
size_t extruder_id = (v - model_object->volumes.begin()) + 1;
|
||||||
if (!(*v)->config.has("extruder"))
|
if (!(*v)->config.has("extruder"))
|
||||||
(*v)->config.opt<ConfigOptionInt>("extruder", true)->value = extruder_id;
|
(*v)->config.opt<ConfigOptionInt>("extruder", true)->value = extruder_id;
|
||||||
|
@ -20,7 +20,7 @@ class Print;
|
|||||||
class PrintObject;
|
class PrintObject;
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
|
|
||||||
|
// Print step IDs for keeping track of the print state.
|
||||||
enum PrintStep {
|
enum PrintStep {
|
||||||
psSkirt, psBrim,
|
psSkirt, psBrim,
|
||||||
};
|
};
|
||||||
@ -34,6 +34,7 @@ class PrintValidationException : public std::runtime_error {
|
|||||||
PrintValidationException(const std::string &error) : std::runtime_error(error) {};
|
PrintValidationException(const std::string &error) : std::runtime_error(error) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// To be instantiated over PrintStep or PrintObjectStep enums.
|
||||||
template <class StepType>
|
template <class StepType>
|
||||||
class PrintState
|
class PrintState
|
||||||
{
|
{
|
||||||
@ -120,6 +121,7 @@ class PrintObject
|
|||||||
size_t layer_count() const;
|
size_t layer_count() const;
|
||||||
void clear_layers();
|
void clear_layers();
|
||||||
Layer* get_layer(int idx);
|
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);
|
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
||||||
void delete_layer(int idx);
|
void delete_layer(int idx);
|
||||||
|
|
||||||
@ -152,6 +154,7 @@ class PrintObject
|
|||||||
typedef std::vector<PrintObject*> PrintObjectPtrs;
|
typedef std::vector<PrintObject*> PrintObjectPtrs;
|
||||||
typedef std::vector<PrintRegion*> PrintRegionPtrs;
|
typedef std::vector<PrintRegion*> PrintRegionPtrs;
|
||||||
|
|
||||||
|
// The complete print tray with possibly multiple objects.
|
||||||
class Print
|
class Print
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -885,11 +885,37 @@ PrintConfigDef::PrintConfigDef()
|
|||||||
def->enum_values.push_back("random");
|
def->enum_values.push_back("random");
|
||||||
def->enum_values.push_back("nearest");
|
def->enum_values.push_back("nearest");
|
||||||
def->enum_values.push_back("aligned");
|
def->enum_values.push_back("aligned");
|
||||||
|
// def->enum_values.push_back("preferred");
|
||||||
def->enum_labels.push_back("Random");
|
def->enum_labels.push_back("Random");
|
||||||
def->enum_labels.push_back("Nearest");
|
def->enum_labels.push_back("Nearest");
|
||||||
def->enum_labels.push_back("Aligned");
|
def->enum_labels.push_back("Aligned");
|
||||||
|
// def->enum_labels.push_back("Preferred Direction");
|
||||||
def->default_value = new ConfigOptionEnum<SeamPosition>(spAligned);
|
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 = this->add("serial_port", coString);
|
||||||
def->gui_type = "select_open";
|
def->gui_type = "select_open";
|
||||||
def->label = "";
|
def->label = "";
|
||||||
|
@ -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_
|
#ifndef slic3r_PrintConfig_hpp_
|
||||||
#define slic3r_PrintConfig_hpp_
|
#define slic3r_PrintConfig_hpp_
|
||||||
|
|
||||||
@ -22,7 +39,7 @@ enum SupportMaterialPattern {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum SeamPosition {
|
enum SeamPosition {
|
||||||
spRandom, spNearest, spAligned
|
spRandom, spNearest, spAligned //, spPreferred
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> inline t_config_enum_values ConfigOptionEnum<GCodeFlavor>::get_enum_values() {
|
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["random"] = spRandom;
|
||||||
keys_map["nearest"] = spNearest;
|
keys_map["nearest"] = spNearest;
|
||||||
keys_map["aligned"] = spAligned;
|
keys_map["aligned"] = spAligned;
|
||||||
|
// keys_map["preferred"] = spPreferred;
|
||||||
return keys_map;
|
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
|
class PrintConfigDef : public ConfigDef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PrintConfigDef();
|
PrintConfigDef();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The one and only global definition of SLic3r configuration options.
|
||||||
|
// This definition is constant.
|
||||||
extern PrintConfigDef print_config_def;
|
extern PrintConfigDef print_config_def;
|
||||||
|
|
||||||
|
// Slic3r configuration storage with print_config_def assigned.
|
||||||
class PrintConfigBase : public virtual ConfigBase
|
class PrintConfigBase : public virtual ConfigBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -86,6 +109,12 @@ class PrintConfigBase : public virtual ConfigBase
|
|||||||
double min_object_distance() const;
|
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
|
class DynamicPrintConfig : public PrintConfigBase, public DynamicConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -93,12 +122,14 @@ class DynamicPrintConfig : public PrintConfigBase, public DynamicConfig
|
|||||||
void normalize();
|
void normalize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class StaticPrintConfig : public PrintConfigBase, public StaticConfig
|
class StaticPrintConfig : public PrintConfigBase, public StaticConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StaticPrintConfig() : PrintConfigBase(), StaticConfig() {};
|
StaticPrintConfig() : PrintConfigBase(), StaticConfig() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This object is mapped to Perl as Slic3r::Config::PrintObject.
|
||||||
class PrintObjectConfig : public virtual StaticPrintConfig
|
class PrintObjectConfig : public virtual StaticPrintConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -110,6 +141,8 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
|||||||
ConfigOptionFloat layer_height;
|
ConfigOptionFloat layer_height;
|
||||||
ConfigOptionInt raft_layers;
|
ConfigOptionInt raft_layers;
|
||||||
ConfigOptionEnum<SeamPosition> seam_position;
|
ConfigOptionEnum<SeamPosition> seam_position;
|
||||||
|
// ConfigOptionFloat seam_preferred_direction;
|
||||||
|
// ConfigOptionFloat seam_preferred_direction_jitter;
|
||||||
ConfigOptionBool support_material;
|
ConfigOptionBool support_material;
|
||||||
ConfigOptionInt support_material_angle;
|
ConfigOptionInt support_material_angle;
|
||||||
ConfigOptionFloat support_material_contact_distance;
|
ConfigOptionFloat support_material_contact_distance;
|
||||||
@ -130,7 +163,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
|||||||
if (initialize)
|
if (initialize)
|
||||||
this->set_defaults();
|
this->set_defaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||||
OPT_PTR(dont_support_bridges);
|
OPT_PTR(dont_support_bridges);
|
||||||
OPT_PTR(extrusion_width);
|
OPT_PTR(extrusion_width);
|
||||||
@ -140,6 +173,8 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
|||||||
OPT_PTR(layer_height);
|
OPT_PTR(layer_height);
|
||||||
OPT_PTR(raft_layers);
|
OPT_PTR(raft_layers);
|
||||||
OPT_PTR(seam_position);
|
OPT_PTR(seam_position);
|
||||||
|
// OPT_PTR(seam_preferred_direction);
|
||||||
|
// OPT_PTR(seam_preferred_direction_jitter);
|
||||||
OPT_PTR(support_material);
|
OPT_PTR(support_material);
|
||||||
OPT_PTR(support_material_angle);
|
OPT_PTR(support_material_angle);
|
||||||
OPT_PTR(support_material_contact_distance);
|
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
|
class PrintRegionConfig : public virtual StaticPrintConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -200,7 +236,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
|
|||||||
if (initialize)
|
if (initialize)
|
||||||
this->set_defaults();
|
this->set_defaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||||
OPT_PTR(bottom_solid_layers);
|
OPT_PTR(bottom_solid_layers);
|
||||||
OPT_PTR(bridge_flow_ratio);
|
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
|
class GCodeConfig : public virtual StaticPrintConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -315,6 +352,7 @@ class GCodeConfig : public virtual StaticPrintConfig
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This object is mapped to Perl as Slic3r::Config::Print.
|
||||||
class PrintConfig : public GCodeConfig
|
class PrintConfig : public GCodeConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -373,7 +411,7 @@ class PrintConfig : public GCodeConfig
|
|||||||
if (initialize)
|
if (initialize)
|
||||||
this->set_defaults();
|
this->set_defaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||||
OPT_PTR(avoid_crossing_perimeters);
|
OPT_PTR(avoid_crossing_perimeters);
|
||||||
OPT_PTR(bed_shape);
|
OPT_PTR(bed_shape);
|
||||||
@ -446,7 +484,7 @@ class HostConfig : public virtual StaticPrintConfig
|
|||||||
if (initialize)
|
if (initialize)
|
||||||
this->set_defaults();
|
this->set_defaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||||
OPT_PTR(octoprint_host);
|
OPT_PTR(octoprint_host);
|
||||||
OPT_PTR(octoprint_apikey);
|
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
|
class FullPrintConfig
|
||||||
: public PrintObjectConfig, public PrintRegionConfig, public PrintConfig, public HostConfig
|
: public PrintObjectConfig, public PrintRegionConfig, public PrintConfig, public HostConfig
|
||||||
{
|
{
|
||||||
|
@ -270,6 +270,8 @@ PrintObject::invalidate_state_by_config_options(const std::vector<t_config_optio
|
|||||||
steps.insert(posPerimeters);
|
steps.insert(posPerimeters);
|
||||||
steps.insert(posInfill);
|
steps.insert(posInfill);
|
||||||
} else if (*opt_key == "seam_position"
|
} else if (*opt_key == "seam_position"
|
||||||
|
|| *opt_key == "seam_preferred_direction"
|
||||||
|
|| *opt_key == "seam_preferred_direction_jitter"
|
||||||
|| *opt_key == "support_material_speed"
|
|| *opt_key == "support_material_speed"
|
||||||
|| *opt_key == "bridge_speed"
|
|| *opt_key == "bridge_speed"
|
||||||
|| *opt_key == "external_perimeter_speed"
|
|| *opt_key == "external_perimeter_speed"
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#include "SVG.hpp"
|
#include "SVG.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#define COORD(x) ((float)unscale(x)*10)
|
#define COORD(x) ((float)unscale((x))*10)
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
SVG::SVG(const char* filename)
|
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");
|
this->f = fopen(filename, "w");
|
||||||
fprintf(this->f,
|
fprintf(this->f,
|
||||||
@ -19,12 +19,12 @@ SVG::SVG(const char* filename)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SVG::SVG(const char* filename, const BoundingBox &bbox)
|
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)
|
: arrows(false), fill("grey"), stroke("black"), filename(filename), origin(bbox.min - Point(bbox_offset, bbox_offset)), flipY(aflipY)
|
||||||
{
|
{
|
||||||
this->f = fopen(filename, "w");
|
this->f = fopen(filename, "w");
|
||||||
float w = COORD(bbox.max.x - bbox.min.x);
|
float w = COORD(bbox.max.x - bbox.min.x + 2 * bbox_offset);
|
||||||
float h = COORD(bbox.max.y - bbox.min.y);
|
float h = COORD(bbox.max.y - bbox.min.y + 2 * bbox_offset);
|
||||||
fprintf(this->f,
|
fprintf(this->f,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
"<?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"
|
"<!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
|
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,
|
fprintf(this->f,
|
||||||
" <line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke: %s; stroke-width: %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");
|
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 dir(line.b.x-line.a.x, line.b.y-line.a.y);
|
||||||
Pointf perp(-dir.y, dir.x);
|
Pointf perp(-dir.y, dir.x);
|
||||||
@ -68,10 +68,10 @@ void SVG::draw(const ThickLine &line, const std::string &fill, const std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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)
|
for (Lines::const_iterator it = lines.begin(); it != lines.end(); ++it)
|
||||||
this->draw(*it, stroke);
|
this->draw(*it, stroke, stroke_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -91,7 +91,7 @@ SVG::draw(const ExPolygon &expolygon, std::string fill)
|
|||||||
for (Polygons::const_iterator p = pp.begin(); p != pp.end(); ++p) {
|
for (Polygons::const_iterator p = pp.begin(); p != pp.end(); ++p) {
|
||||||
d += this->get_path_d(*p, true) + " ";
|
d += this->get_path_d(*p, true) + " ";
|
||||||
}
|
}
|
||||||
this->path(d, true);
|
this->path(d, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -105,7 +105,7 @@ void
|
|||||||
SVG::draw(const Polygon &polygon, std::string fill)
|
SVG::draw(const Polygon &polygon, std::string fill)
|
||||||
{
|
{
|
||||||
this->fill = 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
|
void
|
||||||
@ -116,34 +116,34 @@ SVG::draw(const Polygons &polygons, std::string fill)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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->stroke = stroke;
|
||||||
this->path(this->get_path_d(polyline, false), false, stroke_width);
|
this->path(this->get_path_d(polyline, false), false, stroke_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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)
|
for (Polylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it)
|
||||||
this->draw(*it, fill, stroke_width);
|
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)
|
for (ThickLines::const_iterator it = thicklines.begin(); it != thicklines.end(); ++it)
|
||||||
this->draw(*it, fill, stroke, stroke_width);
|
this->draw(*it, fill, stroke, stroke_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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)
|
for (ThickPolylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it)
|
||||||
this->draw((Polyline)*it, stroke, stroke_width);
|
this->draw((Polyline)*it, stroke, stroke_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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)
|
for (ThickPolylines::const_iterator it = thickpolylines.begin(); it != thickpolylines.end(); ++ it)
|
||||||
draw(it->thicklines(), fill, stroke, stroke_width);
|
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);
|
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
|
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;
|
float lineWidth = 0.f;
|
||||||
if (! fill)
|
if (! fill)
|
||||||
@ -199,6 +227,19 @@ SVG::get_path_d(const MultiPoint &mp, bool closed) const
|
|||||||
return d.str();
|
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
|
void
|
||||||
SVG::Close()
|
SVG::Close()
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define slic3r_SVG_hpp_
|
#define slic3r_SVG_hpp_
|
||||||
|
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
|
#include "clipper.hpp"
|
||||||
#include "ExPolygon.hpp"
|
#include "ExPolygon.hpp"
|
||||||
#include "Line.hpp"
|
#include "Line.hpp"
|
||||||
#include "TriangleMesh.hpp"
|
#include "TriangleMesh.hpp"
|
||||||
@ -14,34 +15,43 @@ class SVG
|
|||||||
bool arrows;
|
bool arrows;
|
||||||
std::string fill, stroke;
|
std::string fill, stroke;
|
||||||
Point origin;
|
Point origin;
|
||||||
|
bool flipY;
|
||||||
|
|
||||||
SVG(const char* filename);
|
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(); }
|
~SVG() { if (f != NULL) Close(); }
|
||||||
|
|
||||||
void draw(const Line &line, std::string stroke = "black", coord_t stroke_width = 0);
|
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, coord_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");
|
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 IntersectionLines &lines, std::string stroke = "black");
|
||||||
void draw(const ExPolygon &expolygon, std::string fill = "grey");
|
void draw(const ExPolygon &expolygon, std::string fill = "grey");
|
||||||
void draw(const ExPolygons &expolygons, std::string fill = "grey");
|
void draw(const ExPolygons &expolygons, std::string fill = "grey");
|
||||||
void draw(const Polygon &polygon, 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 Polygons &polygons, std::string fill = "grey");
|
||||||
void draw(const Polyline &polyline, std::string stroke = "black", coord_t stroke_width = 0);
|
void draw_outline(const Polygons &polygons, std::string stroke = "black", coordf_t stroke_width = 0);
|
||||||
void draw(const Polylines &polylines, std::string stroke = "black", coord_t stroke_width = 0);
|
void draw(const Polyline &polyline, std::string stroke = "black", coordf_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 Polylines &polylines, std::string stroke = "black", coordf_t stroke_width = 0);
|
||||||
void draw(const ThickPolylines &polylines, const std::string &stroke = "black", coord_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 &thickpolylines, const std::string &fill, const std::string &stroke, coord_t stroke_width);
|
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 Point &point, std::string fill = "black", coord_t radius = 0);
|
||||||
void draw(const Points &points, 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();
|
void Close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string filename;
|
std::string filename;
|
||||||
FILE* f;
|
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 MultiPoint &mp, bool closed = false) const;
|
||||||
|
std::string get_path_d(const ClipperLib::Path &mp, double scale, bool closed = false) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "BoundingBox.hpp"
|
||||||
#include "Surface.hpp"
|
#include "Surface.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -54,4 +55,31 @@ Surface::is_bridge() const
|
|||||||
|| this->surface_type == stInternalBridge;
|
|| 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,10 @@ class Surface
|
|||||||
typedef std::vector<Surface> Surfaces;
|
typedef std::vector<Surface> Surfaces;
|
||||||
typedef std::vector<Surface*> SurfacesPtr;
|
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
|
#endif
|
||||||
|
@ -8,12 +8,22 @@
|
|||||||
|
|
||||||
#define SLIC3R_VERSION "1.3.0-dev"
|
#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
|
#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
|
#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 RESOLUTION 0.0125
|
||||||
#define SCALED_RESOLUTION (RESOLUTION / SCALING_FACTOR)
|
#define SCALED_RESOLUTION (RESOLUTION / SCALING_FACTOR)
|
||||||
#define PI 3.141592653589793238
|
#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
|
#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 SMALL_PERIMETER_LENGTH (6.5 / SCALING_FACTOR) * 2 * PI
|
||||||
#define INSET_OVERLAP_TOLERANCE 0.4
|
#define INSET_OVERLAP_TOLERANCE 0.4
|
||||||
#define EXTERNAL_INFILL_MARGIN 3
|
#define EXTERNAL_INFILL_MARGIN 3
|
||||||
|
@ -19,13 +19,15 @@
|
|||||||
Clone<Polygon> polygon();
|
Clone<Polygon> polygon();
|
||||||
Clone<Point> size();
|
Clone<Point> size();
|
||||||
Clone<Point> center();
|
Clone<Point> center();
|
||||||
|
double radius();
|
||||||
Clone<Point> min_point() %code{% RETVAL = THIS->min; %};
|
Clone<Point> min_point() %code{% RETVAL = THIS->min; %};
|
||||||
Clone<Point> max_point() %code{% RETVAL = THIS->max; %};
|
Clone<Point> max_point() %code{% RETVAL = THIS->max; %};
|
||||||
long x_min() %code{% RETVAL = THIS->min.x; %};
|
long x_min() %code{% RETVAL = THIS->min.x; %};
|
||||||
long x_max() %code{% RETVAL = THIS->max.x; %};
|
long x_max() %code{% RETVAL = THIS->max.x; %};
|
||||||
long y_min() %code{% RETVAL = THIS->min.y; %};
|
long y_min() %code{% RETVAL = THIS->min.y; %};
|
||||||
long y_max() %code{% RETVAL = THIS->max.y; %};
|
long y_max() %code{% RETVAL = THIS->max.y; %};
|
||||||
|
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%d,%d;%d,%d", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %};
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
BoundingBox*
|
BoundingBox*
|
||||||
@ -51,6 +53,7 @@ new_from_points(CLASS, points)
|
|||||||
void translate(double x, double y);
|
void translate(double x, double y);
|
||||||
Clone<Pointf> size();
|
Clone<Pointf> size();
|
||||||
Clone<Pointf> center();
|
Clone<Pointf> center();
|
||||||
|
double radius();
|
||||||
Clone<Pointf> min_point() %code{% RETVAL = THIS->min; %};
|
Clone<Pointf> min_point() %code{% RETVAL = THIS->min; %};
|
||||||
Clone<Pointf> max_point() %code{% RETVAL = THIS->max; %};
|
Clone<Pointf> max_point() %code{% RETVAL = THIS->max; %};
|
||||||
double x_min() %code{% RETVAL = THIS->min.x; %};
|
double x_min() %code{% RETVAL = THIS->min.x; %};
|
||||||
@ -61,7 +64,8 @@ new_from_points(CLASS, points)
|
|||||||
void set_x_max(double val) %code{% THIS->max.x = val; %};
|
void set_x_max(double val) %code{% THIS->max.x = val; %};
|
||||||
void set_y_min(double val) %code{% THIS->min.y = val; %};
|
void set_y_min(double val) %code{% THIS->min.y = val; %};
|
||||||
void set_y_max(double val) %code{% THIS->max.y = val; %};
|
void set_y_max(double val) %code{% THIS->max.y = val; %};
|
||||||
|
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf;%lf,%lf", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %};
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
BoundingBoxf*
|
BoundingBoxf*
|
||||||
@ -87,6 +91,7 @@ new_from_points(CLASS, points)
|
|||||||
void translate(double x, double y, double z);
|
void translate(double x, double y, double z);
|
||||||
Clone<Pointf3> size();
|
Clone<Pointf3> size();
|
||||||
Clone<Pointf3> center();
|
Clone<Pointf3> center();
|
||||||
|
double radius();
|
||||||
Clone<Pointf3> min_point() %code{% RETVAL = THIS->min; %};
|
Clone<Pointf3> min_point() %code{% RETVAL = THIS->min; %};
|
||||||
Clone<Pointf3> max_point() %code{% RETVAL = THIS->max; %};
|
Clone<Pointf3> max_point() %code{% RETVAL = THIS->max; %};
|
||||||
double x_min() %code{% RETVAL = THIS->min.x; %};
|
double x_min() %code{% RETVAL = THIS->min.x; %};
|
||||||
@ -95,4 +100,5 @@ new_from_points(CLASS, points)
|
|||||||
double y_max() %code{% RETVAL = THIS->max.y; %};
|
double y_max() %code{% RETVAL = THIS->max.y; %};
|
||||||
double z_min() %code{% RETVAL = THIS->min.z; %};
|
double z_min() %code{% RETVAL = THIS->min.z; %};
|
||||||
double z_max() %code{% RETVAL = THIS->max.z; %};
|
double z_max() %code{% RETVAL = THIS->max.z; %};
|
||||||
|
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf;%lf,%lf,%lf", THIS->min.x, THIS->min.y, THIS->min.z, THIS->max.x, THIS->max.y, THIS->max.z); RETVAL = buf; %};
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
%code{% RETVAL = new Point(THIS->negative()); %};
|
%code{% RETVAL = new Point(THIS->negative()); %};
|
||||||
bool coincides_with_epsilon(Point* point)
|
bool coincides_with_epsilon(Point* point)
|
||||||
%code{% RETVAL = THIS->coincides_with_epsilon(*point); %};
|
%code{% RETVAL = THIS->coincides_with_epsilon(*point); %};
|
||||||
|
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%d,%d", THIS->x, THIS->y); RETVAL = buf; %};
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
@ -86,6 +87,7 @@ Point::coincides_with(point_sv)
|
|||||||
%code{% RETVAL = THIS->y; %};
|
%code{% RETVAL = THIS->y; %};
|
||||||
long z()
|
long z()
|
||||||
%code{% RETVAL = THIS->z; %};
|
%code{% RETVAL = THIS->z; %};
|
||||||
|
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%d,%d,%d", THIS->x, THIS->y, THIS->z); RETVAL = buf; %};
|
||||||
};
|
};
|
||||||
|
|
||||||
%name{Slic3r::Pointf} class Pointf {
|
%name{Slic3r::Pointf} class Pointf {
|
||||||
@ -113,6 +115,7 @@ Point::coincides_with(point_sv)
|
|||||||
%code{% RETVAL = THIS->negative(); %};
|
%code{% RETVAL = THIS->negative(); %};
|
||||||
Clone<Pointf> vector_to(Pointf* point)
|
Clone<Pointf> vector_to(Pointf* point)
|
||||||
%code{% RETVAL = THIS->vector_to(*point); %};
|
%code{% RETVAL = THIS->vector_to(*point); %};
|
||||||
|
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf", THIS->x, THIS->y); RETVAL = buf; %};
|
||||||
};
|
};
|
||||||
|
|
||||||
%name{Slic3r::Pointf3} class Pointf3 {
|
%name{Slic3r::Pointf3} class Pointf3 {
|
||||||
@ -140,4 +143,5 @@ Point::coincides_with(point_sv)
|
|||||||
%code{% RETVAL = THIS->negative(); %};
|
%code{% RETVAL = THIS->negative(); %};
|
||||||
Clone<Pointf3> vector_to(Pointf3* point)
|
Clone<Pointf3> vector_to(Pointf3* point)
|
||||||
%code{% RETVAL = THIS->vector_to(*point); %};
|
%code{% RETVAL = THIS->vector_to(*point); %};
|
||||||
|
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf", THIS->x, THIS->y, THIS->z); RETVAL = buf; %};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user