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