mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Merge branch 'dev' of https://github.com/prusa3d/PrusaSlicer into et_reload_from_disk
This commit is contained in:
		
						commit
						9cf3793aac
					
				
					 19 changed files with 238 additions and 240 deletions
				
			
		|  | @ -117,9 +117,9 @@ public: | |||
|     virtual ConfigOption*       clone() const = 0; | ||||
|     // Set a value from a ConfigOption. The two options should be compatible.
 | ||||
|     virtual void                set(const ConfigOption *option) = 0; | ||||
|     virtual int                 getInt()        const { throw std::runtime_error("Calling ConfigOption::getInt on a non-int ConfigOption"); return 0; } | ||||
|     virtual double              getFloat()      const { throw std::runtime_error("Calling ConfigOption::getFloat on a non-float ConfigOption"); return 0; } | ||||
|     virtual bool                getBool()       const { throw std::runtime_error("Calling ConfigOption::getBool on a non-boolean ConfigOption"); return 0; } | ||||
|     virtual int                 getInt()        const { throw std::runtime_error("Calling ConfigOption::getInt on a non-int ConfigOption"); } | ||||
|     virtual double              getFloat()      const { throw std::runtime_error("Calling ConfigOption::getFloat on a non-float ConfigOption"); } | ||||
|     virtual bool                getBool()       const { throw std::runtime_error("Calling ConfigOption::getBool on a non-boolean ConfigOption");  } | ||||
|     virtual void                setInt(int /* val */) { throw std::runtime_error("Calling ConfigOption::setInt on a non-int ConfigOption"); } | ||||
|     virtual bool                operator==(const ConfigOption &rhs) const = 0; | ||||
|     bool                        operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); } | ||||
|  | @ -204,6 +204,12 @@ public: | |||
|     // Is the value nil? That should only be possible if this->nullable().
 | ||||
|     virtual bool   is_nil(size_t idx) const = 0; | ||||
| 
 | ||||
|     // We just overloaded and hid two base class virtual methods.
 | ||||
|     // Let's show it was intentional (warnings).
 | ||||
|     using ConfigOption::set; | ||||
|     using ConfigOption::is_nil; | ||||
| 
 | ||||
| 
 | ||||
| protected: | ||||
|     // Used to verify type compatibility when assigning to / from a scalar ConfigOption.
 | ||||
|     ConfigOptionType scalar_type() const { return static_cast<ConfigOptionType>(this->type() - coVectorType); } | ||||
|  | @ -544,7 +550,7 @@ public: | |||
|     static ConfigOptionType static_type() { return coInt; } | ||||
|     ConfigOptionType        type()   const override { return static_type(); } | ||||
|     int                     getInt() const override { return this->value; } | ||||
|     void                    setInt(int val) { this->value = val; } | ||||
|     void                    setInt(int val) override { this->value = val; } | ||||
|     ConfigOption*           clone()  const override { return new ConfigOptionInt(*this); } | ||||
|     bool                    operator==(const ConfigOptionInt &rhs) const { return this->value == rhs.value; } | ||||
|      | ||||
|  | @ -702,7 +708,7 @@ public: | |||
|     ConfigOption*           clone() const override { return new ConfigOptionStrings(*this); } | ||||
|     ConfigOptionStrings&    operator=(const ConfigOption *opt) { this->set(opt); return *this; } | ||||
|     bool                    operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; } | ||||
| 	bool					is_nil(size_t idx) const override { return false; } | ||||
|     bool					is_nil(size_t) const override { return false; } | ||||
| 
 | ||||
|     std::string serialize() const override | ||||
|     { | ||||
|  | @ -917,7 +923,7 @@ public: | |||
|     ConfigOption*           clone() const override { return new ConfigOptionPoints(*this); } | ||||
|     ConfigOptionPoints&     operator=(const ConfigOption *opt) { this->set(opt); return *this; } | ||||
|     bool                    operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; } | ||||
| 	bool					is_nil(size_t idx) const override { return false; } | ||||
|     bool					is_nil(size_t) const override { return false; } | ||||
| 
 | ||||
|     std::string serialize() const override | ||||
|     { | ||||
|  | @ -1502,7 +1508,7 @@ protected: | |||
|     // Both opt_key and value may be modified by handle_legacy().
 | ||||
|     // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
 | ||||
|     // handle_legacy() is called internally by set_deserialize().
 | ||||
|     virtual void                    handle_legacy(t_config_option_key &opt_key, std::string &value) const {} | ||||
|     virtual void                    handle_legacy(t_config_option_key &/*opt_key*/, std::string &/*value*/) const {} | ||||
| 
 | ||||
| public: | ||||
|     // Non-virtual methods:
 | ||||
|  | @ -1576,7 +1582,7 @@ public: | |||
|     DynamicConfig() {} | ||||
|     DynamicConfig(const DynamicConfig& other) { *this = other; } | ||||
|     DynamicConfig(DynamicConfig&& other) : options(std::move(other.options)) { other.options.clear(); } | ||||
|     virtual ~DynamicConfig() { clear(); } | ||||
|     virtual ~DynamicConfig() override { clear(); } | ||||
| 
 | ||||
|     // Copy a content of one DynamicConfig to another DynamicConfig.
 | ||||
|     // If rhs.def() is not null, then it has to be equal to this->def(). 
 | ||||
|  | @ -1697,14 +1703,14 @@ public: | |||
|     const std::string&  opt_string(const t_config_option_key &opt_key, unsigned int idx) const  { return const_cast<DynamicConfig*>(this)->opt_string(opt_key, idx); } | ||||
| 
 | ||||
|     double&             opt_float(const t_config_option_key &opt_key)                           { return this->option<ConfigOptionFloat>(opt_key)->value; } | ||||
|     const double        opt_float(const t_config_option_key &opt_key) const                     { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; } | ||||
|     const double&       opt_float(const t_config_option_key &opt_key) const                     { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; } | ||||
|     double&             opt_float(const t_config_option_key &opt_key, unsigned int idx)         { return this->option<ConfigOptionFloats>(opt_key)->get_at(idx); } | ||||
|     const double        opt_float(const t_config_option_key &opt_key, unsigned int idx) const   { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); } | ||||
|     const double&       opt_float(const t_config_option_key &opt_key, unsigned int idx) const   { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); } | ||||
| 
 | ||||
|     int&                opt_int(const t_config_option_key &opt_key)                             { return this->option<ConfigOptionInt>(opt_key)->value; } | ||||
|     const int           opt_int(const t_config_option_key &opt_key) const                       { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; } | ||||
|     int                 opt_int(const t_config_option_key &opt_key) const                       { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; } | ||||
|     int&                opt_int(const t_config_option_key &opt_key, unsigned int idx)           { return this->option<ConfigOptionInts>(opt_key)->get_at(idx); } | ||||
|     const int           opt_int(const t_config_option_key &opt_key, unsigned int idx) const     { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); } | ||||
|     int                 opt_int(const t_config_option_key &opt_key, unsigned int idx) const     { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); } | ||||
| 
 | ||||
|     template<typename ENUM> | ||||
| 	ENUM                opt_enum(const t_config_option_key &opt_key) const                      { return (ENUM)dynamic_cast<const ConfigOptionEnumGeneric*>(this->option(opt_key))->value; } | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ | |||
| #include <limits> | ||||
| #include <sstream> | ||||
| 
 | ||||
| #define L(s) (s) | ||||
| 
 | ||||
| namespace Slic3r { | ||||
|      | ||||
| void | ||||
|  | @ -318,4 +320,39 @@ ExtrusionLoop::min_mm3_per_mm() const | |||
|     return min_mm3_per_mm; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| std::string ExtrusionEntity::role_to_string(ExtrusionRole role) | ||||
| { | ||||
|     switch (role) { | ||||
|         case erNone                         : return L("None"); | ||||
|         case erPerimeter                    : return L("Perimeter"); | ||||
|         case erExternalPerimeter            : return L("External perimeter"); | ||||
|         case erOverhangPerimeter            : return L("Overhang perimeter"); | ||||
|         case erInternalInfill               : return L("Internal infill"); | ||||
|         case erSolidInfill                  : return L("Solid infill"); | ||||
|         case erTopSolidInfill               : return L("Top solid infill"); | ||||
|         case erBridgeInfill                 : return L("Bridge infill"); | ||||
|         case erGapFill                      : return L("Gap fill"); | ||||
|         case erSkirt                        : return L("Skirt"); | ||||
|         case erSupportMaterial              : return L("Support material"); | ||||
|         case erSupportMaterialInterface     : return L("Support material interface"); | ||||
|         case erWipeTower                    : return L("Wipe tower"); | ||||
|         case erCustom                       : return L("Custom"); | ||||
|         case erMixed                        : return L("Mixed"); | ||||
|         default                             : assert(false); | ||||
|     } | ||||
|     return ""; | ||||
| } | ||||
| 
 | ||||
| //std::string ExtrusionLoop::role_to_string(ExtrusionLoopRole role)
 | ||||
| //{
 | ||||
| //    switch (role) {
 | ||||
| //        case elrDefault                 : return "elrDefault";
 | ||||
| //        case elrContourInternalPerimeter: return "elrContourInternalPerimeter";
 | ||||
| //        case elrSkirt                   : return "elrSkirt";
 | ||||
| //        default                         : assert(false);
 | ||||
| //    }
 | ||||
| //};
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ class ExPolygonCollection; | |||
| class ExtrusionEntityCollection; | ||||
| class Extruder; | ||||
| 
 | ||||
| /* Each ExtrusionRole value identifies a distinct set of { extruder, speed } */ | ||||
| // Each ExtrusionRole value identifies a distinct set of { extruder, speed }
 | ||||
| enum ExtrusionRole { | ||||
|     erNone, | ||||
|     erPerimeter, | ||||
|  | @ -29,9 +29,17 @@ enum ExtrusionRole { | |||
|     erCustom, | ||||
|     // Extrusion role for a collection with multiple extrusion roles.
 | ||||
|     erMixed, | ||||
|     erCount, | ||||
|     erCount | ||||
| }; | ||||
| 
 | ||||
| // Special flags describing loop
 | ||||
| enum ExtrusionLoopRole { | ||||
|     elrDefault, | ||||
|     elrContourInternalPerimeter, | ||||
|     elrSkirt, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| inline bool is_perimeter(ExtrusionRole role) | ||||
| { | ||||
|     return role == erPerimeter | ||||
|  | @ -59,13 +67,6 @@ inline bool is_bridge(ExtrusionRole role) { | |||
|         || role == erOverhangPerimeter; | ||||
| } | ||||
| 
 | ||||
| /* Special flags describing loop */ | ||||
| enum ExtrusionLoopRole { | ||||
|     elrDefault, | ||||
|     elrContourInternalPerimeter, | ||||
|     elrSkirt, | ||||
| }; | ||||
| 
 | ||||
| class ExtrusionEntity | ||||
| { | ||||
| public: | ||||
|  | @ -74,7 +75,7 @@ public: | |||
|     virtual bool is_loop() const { return false; } | ||||
|     virtual bool can_reverse() const { return true; } | ||||
|     virtual ExtrusionEntity* clone() const = 0; | ||||
|     virtual ~ExtrusionEntity() {}; | ||||
|     virtual ~ExtrusionEntity() {} | ||||
|     virtual void reverse() = 0; | ||||
|     virtual Point first_point() const = 0; | ||||
|     virtual Point last_point() const = 0; | ||||
|  | @ -96,6 +97,8 @@ public: | |||
|     virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; } | ||||
|     virtual double length() const = 0; | ||||
|     virtual double total_volume() const = 0; | ||||
| 
 | ||||
|     static std::string role_to_string(ExtrusionRole role); | ||||
| }; | ||||
| 
 | ||||
| typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr; | ||||
|  | @ -117,17 +120,17 @@ public: | |||
|     // Id of the color, used for visualization purposed in the color printing case.
 | ||||
|     unsigned int cp_color_id; | ||||
| 
 | ||||
|     ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {}; | ||||
|     ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {}; | ||||
|     ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {} | ||||
|     ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {} | ||||
|     ExtrusionPath(const ExtrusionPath &rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {} | ||||
|     ExtrusionPath(ExtrusionPath &&rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {} | ||||
| //    ExtrusionPath(ExtrusionRole role, const Flow &flow) : m_role(role), mm3_per_mm(flow.mm3_per_mm()), width(flow.width), height(flow.height), feedrate(0.0f), extruder_id(0) {};
 | ||||
| 
 | ||||
|     ExtrusionPath& operator=(const ExtrusionPath &rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->polyline = rhs.polyline; return *this; } | ||||
|     ExtrusionPath& operator=(ExtrusionPath &&rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->polyline = std::move(rhs.polyline); return *this; } | ||||
|     ExtrusionPath& operator=(const ExtrusionPath &rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate; this->extruder_id = rhs.extruder_id; this->cp_color_id = rhs.cp_color_id; this->polyline = rhs.polyline; return *this; } | ||||
|     ExtrusionPath& operator=(ExtrusionPath &&rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate; this->extruder_id = rhs.extruder_id; this->cp_color_id = rhs.cp_color_id; this->polyline = std::move(rhs.polyline); return *this; } | ||||
| 
 | ||||
|     ExtrusionPath* clone() const { return new ExtrusionPath (*this); } | ||||
|     void reverse() { this->polyline.reverse(); } | ||||
|     ExtrusionPath* clone() const override { return new ExtrusionPath (*this); } | ||||
|     void reverse() override { this->polyline.reverse(); } | ||||
|     Point first_point() const override { return this->polyline.points.front(); } | ||||
|     Point last_point() const override { return this->polyline.points.back(); } | ||||
|     size_t size() const { return this->polyline.size(); } | ||||
|  | @ -145,18 +148,18 @@ public: | |||
|     ExtrusionRole role() const override { return m_role; } | ||||
|     // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
 | ||||
|     // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
 | ||||
|     void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const; | ||||
|     void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override; | ||||
|     // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing.
 | ||||
|     // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
 | ||||
|     // Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
 | ||||
|     void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const; | ||||
|     void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override; | ||||
|     Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const | ||||
|         { Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } | ||||
|     Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const | ||||
|         { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } | ||||
|     // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
 | ||||
|     double min_mm3_per_mm() const { return this->mm3_per_mm; } | ||||
|     Polyline as_polyline() const { return this->polyline; } | ||||
|     double min_mm3_per_mm() const override { return this->mm3_per_mm; } | ||||
|     Polyline as_polyline() const override { return this->polyline; } | ||||
|     void   collect_polylines(Polylines &dst) const override { if (! this->polyline.empty()) dst.emplace_back(this->polyline); } | ||||
|     double total_volume() const override { return mm3_per_mm * unscale<double>(length()); } | ||||
| 
 | ||||
|  | @ -174,37 +177,37 @@ class ExtrusionMultiPath : public ExtrusionEntity | |||
| public: | ||||
|     ExtrusionPaths paths; | ||||
|      | ||||
|     ExtrusionMultiPath() {}; | ||||
|     ExtrusionMultiPath() {} | ||||
|     ExtrusionMultiPath(const ExtrusionMultiPath &rhs) : paths(rhs.paths) {} | ||||
|     ExtrusionMultiPath(ExtrusionMultiPath &&rhs) : paths(std::move(rhs.paths)) {} | ||||
|     ExtrusionMultiPath(const ExtrusionPaths &paths) : paths(paths) {}; | ||||
|     ExtrusionMultiPath(const ExtrusionPaths &paths) : paths(paths) {} | ||||
|     ExtrusionMultiPath(const ExtrusionPath &path) { this->paths.push_back(path); } | ||||
| 
 | ||||
|     ExtrusionMultiPath& operator=(const ExtrusionMultiPath &rhs) { this->paths = rhs.paths; return *this; } | ||||
|     ExtrusionMultiPath& operator=(ExtrusionMultiPath &&rhs) { this->paths = std::move(rhs.paths); return *this; } | ||||
| 
 | ||||
|     bool is_loop() const { return false; } | ||||
|     bool can_reverse() const { return true; } | ||||
|     ExtrusionMultiPath* clone() const { return new ExtrusionMultiPath(*this); } | ||||
|     void reverse(); | ||||
|     bool is_loop() const override { return false; } | ||||
|     bool can_reverse() const override { return true; } | ||||
|     ExtrusionMultiPath* clone() const override { return new ExtrusionMultiPath(*this); } | ||||
|     void reverse() override; | ||||
|     Point first_point() const override { return this->paths.front().polyline.points.front(); } | ||||
|     Point last_point() const override { return this->paths.back().polyline.points.back(); } | ||||
|     double length() const override; | ||||
|     ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); } | ||||
|     // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
 | ||||
|     // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
 | ||||
|     void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const; | ||||
|     void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override; | ||||
|     // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing.
 | ||||
|     // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
 | ||||
|     // Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
 | ||||
|     void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const; | ||||
|     void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override; | ||||
|     Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const | ||||
|         { Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } | ||||
|     Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const | ||||
|         { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } | ||||
|     // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
 | ||||
|     double min_mm3_per_mm() const; | ||||
|     Polyline as_polyline() const; | ||||
|     double min_mm3_per_mm() const override; | ||||
|     Polyline as_polyline() const override; | ||||
|     void   collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); } | ||||
|     double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } | ||||
| }; | ||||
|  | @ -215,19 +218,19 @@ class ExtrusionLoop : public ExtrusionEntity | |||
| public: | ||||
|     ExtrusionPaths paths; | ||||
|      | ||||
|     ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {}; | ||||
|     ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {}; | ||||
|     ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {}; | ||||
|     ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {} | ||||
|     ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {} | ||||
|     ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {} | ||||
|     ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)  | ||||
|         { this->paths.push_back(path); }; | ||||
|         { this->paths.push_back(path); } | ||||
|     ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role) | ||||
|         { this->paths.emplace_back(std::move(path)); }; | ||||
|     bool is_loop() const { return true; } | ||||
|     bool can_reverse() const { return false; } | ||||
|     ExtrusionLoop* clone() const { return new ExtrusionLoop (*this); } | ||||
|         { this->paths.emplace_back(std::move(path)); } | ||||
|     bool is_loop() const override{ return true; } | ||||
|     bool can_reverse() const override { return false; } | ||||
|     ExtrusionLoop* clone() const override{ return new ExtrusionLoop (*this); } | ||||
|     bool make_clockwise(); | ||||
|     bool make_counter_clockwise(); | ||||
|     void reverse(); | ||||
|     void reverse() override; | ||||
|     Point first_point() const override { return this->paths.front().polyline.points.front(); } | ||||
|     Point last_point() const override { assert(first_point() == this->paths.back().polyline.points.back()); return first_point(); } | ||||
|     Polygon polygon() const; | ||||
|  | @ -242,21 +245,23 @@ public: | |||
|     ExtrusionLoopRole loop_role() const { return m_loop_role; } | ||||
|     // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
 | ||||
|     // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
 | ||||
|     void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const; | ||||
|     void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override; | ||||
|     // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing.
 | ||||
|     // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
 | ||||
|     // Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
 | ||||
|     void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const; | ||||
|     void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const  override; | ||||
|     Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const | ||||
|         { Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } | ||||
|     Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const | ||||
|         { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } | ||||
|     // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
 | ||||
|     double min_mm3_per_mm() const; | ||||
|     Polyline as_polyline() const { return this->polygon().split_at_first_point(); } | ||||
|     double min_mm3_per_mm() const override; | ||||
|     Polyline as_polyline() const override { return this->polygon().split_at_first_point(); } | ||||
|     void   collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); } | ||||
|     double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } | ||||
| 
 | ||||
|     //static inline std::string role_to_string(ExtrusionLoopRole role);
 | ||||
| 
 | ||||
| private: | ||||
|     ExtrusionLoopRole m_loop_role; | ||||
| }; | ||||
|  |  | |||
|  | @ -1916,7 +1916,7 @@ void GCode::process_layer( | |||
|     _write(file, gcode); | ||||
|     BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<  | ||||
|         ", time estimator memory: " << | ||||
|             format_memsize_MB(m_normal_time_estimator.memory_used() + m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0) << | ||||
|             format_memsize_MB(m_normal_time_estimator.memory_used() + (m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0)) << | ||||
|         ", analyzer memory: " << | ||||
|             format_memsize_MB(m_analyzer.memory_used()) << | ||||
|         log_memory_info(); | ||||
|  | @ -1997,38 +1997,6 @@ std::string GCode::change_layer(coordf_t print_z) | |||
|     return gcode; | ||||
| } | ||||
| 
 | ||||
| static inline const char* ExtrusionRole2String(const ExtrusionRole role) | ||||
| { | ||||
|     switch (role) { | ||||
|     case erNone:                        return "erNone"; | ||||
|     case erPerimeter:                   return "erPerimeter"; | ||||
|     case erExternalPerimeter:           return "erExternalPerimeter"; | ||||
|     case erOverhangPerimeter:           return "erOverhangPerimeter"; | ||||
|     case erInternalInfill:              return "erInternalInfill"; | ||||
|     case erSolidInfill:                 return "erSolidInfill"; | ||||
|     case erTopSolidInfill:              return "erTopSolidInfill"; | ||||
|     case erBridgeInfill:                return "erBridgeInfill"; | ||||
|     case erGapFill:                     return "erGapFill"; | ||||
|     case erSkirt:                       return "erSkirt"; | ||||
|     case erSupportMaterial:             return "erSupportMaterial"; | ||||
|     case erSupportMaterialInterface:    return "erSupportMaterialInterface"; | ||||
|     case erWipeTower:                   return "erWipeTower"; | ||||
|     case erMixed:                       return "erMixed"; | ||||
| 
 | ||||
|     default:                            return "erInvalid"; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| static inline const char* ExtrusionLoopRole2String(const ExtrusionLoopRole role) | ||||
| { | ||||
|     switch (role) { | ||||
|     case elrDefault:                    return "elrDefault"; | ||||
|     case elrContourInternalPerimeter:   return "elrContourInternalPerimeter"; | ||||
|     case elrSkirt:                      return "elrSkirt"; | ||||
|     default:                            return "elrInvalid"; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| // Return a value in <0, 1> of a cubic B-spline kernel centered around zero.
 | ||||
| // The B-spline is re-scaled so it has value 1 at zero.
 | ||||
| static inline float bspline_kernel(float x) | ||||
|  | @ -2411,8 +2379,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou | |||
|     // extrude along the path
 | ||||
|     std::string gcode; | ||||
|     for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) { | ||||
| //    description += ExtrusionLoopRole2String(loop.loop_role());
 | ||||
| //    description += ExtrusionRole2String(path->role);
 | ||||
| //    description += ExtrusionLoop::role_to_string(loop.loop_role());
 | ||||
| //    description += ExtrusionEntity::role_to_string(path->role);
 | ||||
|         path->simplify(SCALED_RESOLUTION); | ||||
|         gcode += this->_extrude(*path, description, speed); | ||||
|     } | ||||
|  | @ -2465,8 +2433,8 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string | |||
|     // extrude along the path
 | ||||
|     std::string gcode; | ||||
|     for (ExtrusionPath path : multipath.paths) { | ||||
| //    description += ExtrusionLoopRole2String(loop.loop_role());
 | ||||
| //    description += ExtrusionRole2String(path->role);
 | ||||
| //    description += ExtrusionLoop::role_to_string(loop.loop_role());
 | ||||
| //    description += ExtrusionEntity::role_to_string(path->role);
 | ||||
|         path.simplify(SCALED_RESOLUTION); | ||||
|         gcode += this->_extrude(path, description, speed); | ||||
|     } | ||||
|  | @ -2495,7 +2463,7 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string des | |||
| 
 | ||||
| std::string GCode::extrude_path(ExtrusionPath path, std::string description, double speed) | ||||
| { | ||||
| //    description += ExtrusionRole2String(path.role());
 | ||||
| //    description += ExtrusionEntity::role_to_string(path.role());
 | ||||
|     path.simplify(SCALED_RESOLUTION); | ||||
|     std::string gcode = this->_extrude(path, description, speed); | ||||
|     if (m_wipe.enable) { | ||||
|  |  | |||
|  | @ -121,7 +121,7 @@ GCodePreviewData::LegendItem::LegendItem(const std::string& text, const GCodePre | |||
| { | ||||
| } | ||||
| 
 | ||||
| const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[Num_Extrusion_Roles] = | ||||
| const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount] = | ||||
| { | ||||
|     Color(0.0f, 0.0f, 0.0f, 1.0f),   // erNone
 | ||||
|     Color(1.0f, 0.0f, 0.0f, 1.0f),   // erPerimeter
 | ||||
|  | @ -140,44 +140,20 @@ const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Rol | |||
|     Color(0.0f, 0.0f, 0.0f, 1.0f)    // erMixed
 | ||||
| }; | ||||
| 
 | ||||
| // todo: merge with Slic3r::ExtrusionRole2String() from GCode.cpp
 | ||||
| const std::string GCodePreviewData::Extrusion::Default_Extrusion_Role_Names[Num_Extrusion_Roles] | ||||
| { | ||||
|     L("None"), | ||||
|     L("Perimeter"), | ||||
|     L("External perimeter"), | ||||
|     L("Overhang perimeter"), | ||||
|     L("Internal infill"), | ||||
|     L("Solid infill"), | ||||
|     L("Top solid infill"), | ||||
|     L("Bridge infill"), | ||||
|     L("Gap fill"), | ||||
|     L("Skirt"), | ||||
|     L("Support material"), | ||||
|     L("Support material interface"), | ||||
|     L("Wipe tower"), | ||||
|     L("Custom"), | ||||
|     L("Mixed") | ||||
| }; | ||||
| 
 | ||||
| const GCodePreviewData::Extrusion::EViewType GCodePreviewData::Extrusion::Default_View_Type = GCodePreviewData::Extrusion::FeatureType; | ||||
| 
 | ||||
| void GCodePreviewData::Extrusion::set_default() | ||||
| { | ||||
|     view_type = Default_View_Type; | ||||
| 
 | ||||
|     ::memcpy((void*)role_colors, (const void*)Default_Extrusion_Role_Colors, Num_Extrusion_Roles * sizeof(Color)); | ||||
|     ::memcpy((void*)role_colors, (const void*)Default_Extrusion_Role_Colors, erCount * sizeof(Color)); | ||||
| 
 | ||||
|     for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i) | ||||
|     { | ||||
|         role_names[i] = Default_Extrusion_Role_Names[i]; | ||||
|     } | ||||
|     for (unsigned int i = 0; i < erCount; ++i) | ||||
|         role_names[i] = ExtrusionEntity::role_to_string(ExtrusionRole(i)); | ||||
| 
 | ||||
|     role_flags = 0; | ||||
|     for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i) | ||||
|     { | ||||
|     for (unsigned int i = 0; i < erCount; ++i) | ||||
|         role_flags |= 1 << i; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool GCodePreviewData::Extrusion::is_role_flag_set(ExtrusionRole role) const | ||||
|  | @ -318,7 +294,7 @@ GCodePreviewData::Color GCodePreviewData::get_volumetric_rate_color(float rate) | |||
| 
 | ||||
| void GCodePreviewData::set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha) | ||||
| { | ||||
|     for (unsigned int i = 0; i < Extrusion::Num_Extrusion_Roles; ++i) | ||||
|     for (unsigned int i = 0; i < erCount; ++i) | ||||
|     { | ||||
|         if (role_name == extrusion.role_names[i]) | ||||
|         { | ||||
|  |  | |||
|  | @ -80,9 +80,8 @@ public: | |||
|             Num_View_Types | ||||
|         }; | ||||
| 
 | ||||
|         static const unsigned int Num_Extrusion_Roles = (unsigned int)erMixed + 1; | ||||
|         static const Color Default_Extrusion_Role_Colors[Num_Extrusion_Roles]; | ||||
|         static const std::string Default_Extrusion_Role_Names[Num_Extrusion_Roles]; | ||||
|         static const Color Default_Extrusion_Role_Colors[erCount]; | ||||
|         static const std::string Default_Extrusion_Role_Names[erCount]; | ||||
|         static const EViewType Default_View_Type; | ||||
| 
 | ||||
|         struct Layer | ||||
|  | @ -96,8 +95,8 @@ public: | |||
|         typedef std::vector<Layer> LayersList; | ||||
| 
 | ||||
|         EViewType view_type; | ||||
|         Color role_colors[Num_Extrusion_Roles]; | ||||
|         std::string role_names[Num_Extrusion_Roles]; | ||||
|         Color role_colors[erCount]; | ||||
|         std::string role_names[erCount]; | ||||
|         LayersList layers; | ||||
|         unsigned int role_flags; | ||||
| 
 | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ public: | |||
|     void    slices_to_fill_surfaces_clipped(); | ||||
|     void    prepare_fill_surfaces(); | ||||
|     void    make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces); | ||||
|     void    process_external_surfaces(const Layer* lower_layer); | ||||
|     void    process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered); | ||||
|     double  infill_area_threshold() const; | ||||
|     // Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer.
 | ||||
|     void    trim_surfaces(const Polygons &trimming_polygons); | ||||
|  |  | |||
|  | @ -86,11 +86,12 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec | |||
| //#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 1.5
 | ||||
| #define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtSquare, 0. | ||||
| 
 | ||||
| void LayerRegion::process_external_surfaces(const Layer* lower_layer) | ||||
| void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered) | ||||
| { | ||||
|     const Surfaces &surfaces = this->fill_surfaces.surfaces; | ||||
|     const double margin = scale_(EXTERNAL_INFILL_MARGIN); | ||||
|      | ||||
|     const Surfaces &surfaces   = this->fill_surfaces.surfaces; | ||||
|     const bool      has_infill = this->region()->config().fill_density.value > 0.; | ||||
|     const float		margin 	   = float(scale_(EXTERNAL_INFILL_MARGIN)); | ||||
| 
 | ||||
| #ifdef SLIC3R_DEBUG_SLICE_PROCESSING | ||||
|     export_region_fill_surfaces_to_svg_debug("3_process_external_surfaces-initial"); | ||||
| #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ | ||||
|  | @ -106,36 +107,44 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer) | |||
|     // Internal surfaces, not grown.
 | ||||
|     Surfaces                    internal; | ||||
|     // Areas, where an infill of various types (top, bottom, bottom bride, sparse, void) could be placed.
 | ||||
|     //FIXME if non zero infill, then fill_boundaries could be cheaply initialized from layerm->fill_expolygons.
 | ||||
|     Polygons                    fill_boundaries; | ||||
|     Polygons                    fill_boundaries = to_polygons(this->fill_expolygons); | ||||
|     Polygons  					lower_layer_covered_tmp; | ||||
| 
 | ||||
|     // Collect top surfaces and internal surfaces.
 | ||||
|     // Collect fill_boundaries: If we're slicing with no infill, we can't extend external surfaces over non-existent infill.
 | ||||
|     // This loop destroys the surfaces (aliasing this->fill_surfaces.surfaces) by moving into top/internal/fill_boundaries!
 | ||||
| 
 | ||||
|     { | ||||
|         // bottom_polygons are used to trim inflated top surfaces.
 | ||||
|         fill_boundaries.reserve(number_polygons(surfaces)); | ||||
|         bool has_infill = this->region()->config().fill_density.value > 0.; | ||||
|         // Voids are sparse infills if infill rate is zero.
 | ||||
|         Polygons voids; | ||||
|         for (const Surface &surface : this->fill_surfaces.surfaces) { | ||||
|             if (surface.surface_type == stTop) { | ||||
|                 // Collect the top surfaces, inflate them and trim them by the bottom surfaces.
 | ||||
|                 // This gives the priority to bottom surfaces.
 | ||||
|                 surfaces_append(top, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface); | ||||
|             } else if (surface.surface_type == stBottom || (surface.surface_type == stBottomBridge && lower_layer == NULL)) { | ||||
|                 surfaces_append(top, offset_ex(surface.expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface); | ||||
|             } else if (surface.surface_type == stBottom || (surface.surface_type == stBottomBridge && lower_layer == nullptr)) { | ||||
|                 // Grown by 3mm.
 | ||||
|                 surfaces_append(bottom, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface); | ||||
|                 surfaces_append(bottom, offset_ex(surface.expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface); | ||||
|             } else if (surface.surface_type == stBottomBridge) { | ||||
|                 if (! surface.empty()) | ||||
|                     bridges.push_back(surface); | ||||
|                     bridges.emplace_back(surface); | ||||
|             } | ||||
|             bool internal_surface = surface.surface_type != stTop && ! surface.is_bottom(); | ||||
|             if (has_infill || surface.surface_type != stInternal) { | ||||
|                 if (internal_surface) | ||||
|                     // Make a copy as the following line uses the move semantics.
 | ||||
|                     internal.push_back(surface); | ||||
|                 polygons_append(fill_boundaries, std::move(surface.expolygon)); | ||||
|             } else if (internal_surface) | ||||
|                 internal.push_back(std::move(surface)); | ||||
|             if (surface.is_internal()) { | ||||
|             	assert(surface.surface_type == stInternal); | ||||
|             	if (! has_infill && lower_layer != nullptr) | ||||
|             		polygons_append(voids, surface.expolygon); | ||||
|             	internal.emplace_back(std::move(surface)); | ||||
|             } | ||||
|         } | ||||
|         if (! has_infill && lower_layer != nullptr && ! voids.empty()) { | ||||
|         	// Remove voids from fill_boundaries, that are not supported by the layer below.
 | ||||
|             if (lower_layer_covered == nullptr) { | ||||
|             	lower_layer_covered = &lower_layer_covered_tmp; | ||||
|             	lower_layer_covered_tmp = to_polygons(lower_layer->slices.expolygons); | ||||
|             } | ||||
|             if (! lower_layer_covered->empty()) | ||||
|             	voids = diff(voids, *lower_layer_covered); | ||||
|         	fill_boundaries = diff(fill_boundaries, voids); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -184,9 +193,9 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer) | |||
|                         break; | ||||
|                     } | ||||
|                 // Grown by 3mm.
 | ||||
|                 Polygons polys = offset(to_polygons(bridges[i].expolygon), float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS); | ||||
|                 Polygons polys = offset(to_polygons(bridges[i].expolygon), margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS); | ||||
|                 if (idx_island == -1) { | ||||
|                     printf("Bridge did not fall into the source region!\r\n"); | ||||
| 				    BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!"; | ||||
|                 } else { | ||||
|                     // Found an island, to which this bridge region belongs. Trim it,
 | ||||
|                     polys = intersection(polys, to_polygons(fill_boundaries_ex[idx_island])); | ||||
|  |  | |||
|  | @ -810,15 +810,72 @@ void PrintObject::process_external_surfaces() | |||
| { | ||||
|     BOOST_LOG_TRIVIAL(info) << "Processing external surfaces..." << log_memory_info(); | ||||
| 
 | ||||
|     // Cached surfaces covered by some extrusion, defining regions, over which the from the surfaces one layer higher are allowed to expand.
 | ||||
|     std::vector<Polygons> surfaces_covered; | ||||
|     // Is there any printing region, that has zero infill? If so, then we don't want the expansion to be performed over the complete voids, but only
 | ||||
|     // over voids, which are supported by the layer below.
 | ||||
|     bool 				  has_voids = false; | ||||
| 	for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) | ||||
| 		if (! this->region_volumes.empty() && this->print()->regions()[region_id]->config().fill_density == 0) { | ||||
| 			has_voids = true; | ||||
| 			break; | ||||
| 		} | ||||
| 	if (has_voids && m_layers.size() > 1) { | ||||
| 	    // All but stInternal fill surfaces will get expanded and possibly trimmed.
 | ||||
| 	    std::vector<unsigned char> layer_expansions_and_voids(m_layers.size(), false); | ||||
| 	    for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) { | ||||
| 	    	const Layer *layer = m_layers[layer_idx]; | ||||
| 	    	bool expansions = false; | ||||
| 	    	bool voids      = false; | ||||
| 	    	for (const LayerRegion *layerm : layer->regions()) { | ||||
| 	    		for (const Surface &surface : layerm->fill_surfaces.surfaces) { | ||||
| 	    			if (surface.surface_type == stInternal) | ||||
| 	    				voids = true; | ||||
| 	    			else | ||||
| 	    				expansions = true; | ||||
| 	    			if (voids && expansions) { | ||||
| 	    				layer_expansions_and_voids[layer_idx] = true; | ||||
| 	    				goto end; | ||||
| 	    			} | ||||
| 	    		} | ||||
| 	    	} | ||||
| 		end:; | ||||
| 		} | ||||
| 	    BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - start"; | ||||
| 	    surfaces_covered.resize(m_layers.size() - 1, Polygons()); | ||||
|     	auto unsupported_width = - float(scale_(0.3 * EXTERNAL_INFILL_MARGIN)); | ||||
| 	    tbb::parallel_for( | ||||
| 	        tbb::blocked_range<size_t>(0, m_layers.size() - 1), | ||||
| 	        [this, &surfaces_covered, &layer_expansions_and_voids, unsupported_width](const tbb::blocked_range<size_t>& range) { | ||||
| 	            for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) | ||||
| 	            	if (layer_expansions_and_voids[layer_idx + 1]) { | ||||
| 		                m_print->throw_if_canceled(); | ||||
| 		                Polygons voids; | ||||
| 		                for (const LayerRegion *layerm : m_layers[layer_idx]->regions()) { | ||||
| 		                	if (layerm->region()->config().fill_density.value == 0.) | ||||
| 		                		for (const Surface &surface : layerm->fill_surfaces.surfaces) | ||||
| 		                			// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
 | ||||
| 		                			polygons_append(voids, offset(surface.expolygon, unsupported_width)); | ||||
| 		                } | ||||
| 		                surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->slices.expolygons), voids); | ||||
| 	            	} | ||||
| 	        } | ||||
| 	    ); | ||||
| 	    m_print->throw_if_canceled(); | ||||
| 	    BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - end"; | ||||
| 	} | ||||
| 
 | ||||
| 	for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) { | ||||
|         BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - start"; | ||||
|         tbb::parallel_for( | ||||
|             tbb::blocked_range<size_t>(0, m_layers.size()), | ||||
|             [this, region_id](const tbb::blocked_range<size_t>& range) { | ||||
|             [this, &surfaces_covered, region_id](const tbb::blocked_range<size_t>& range) { | ||||
|                 for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { | ||||
|                     m_print->throw_if_canceled(); | ||||
|                     // BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
 | ||||
|                     m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]); | ||||
|                     m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces( | ||||
|                     	(layer_idx == 0) ? nullptr : m_layers[layer_idx - 1], | ||||
|                     	(layer_idx == 0 || surfaces_covered.empty() || surfaces_covered[layer_idx - 1].empty()) ? nullptr : &surfaces_covered[layer_idx - 1]); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  |  | |||
|  | @ -4,64 +4,6 @@ | |||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| Surface::operator Polygons() const | ||||
| { | ||||
|     return this->expolygon; | ||||
| } | ||||
| 
 | ||||
| double | ||||
| Surface::area() const | ||||
| { | ||||
|     return this->expolygon.area(); | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| Surface::is_solid() const | ||||
| { | ||||
|     return this->surface_type == stTop | ||||
|         || this->surface_type == stBottom | ||||
|         || this->surface_type == stBottomBridge | ||||
|         || this->surface_type == stInternalSolid | ||||
|         || this->surface_type == stInternalBridge; | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| Surface::is_external() const | ||||
| { | ||||
|     return this->surface_type == stTop | ||||
|         || this->surface_type == stBottom | ||||
|         || this->surface_type == stBottomBridge; | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| Surface::is_internal() const | ||||
| { | ||||
|     return this->surface_type == stInternal | ||||
|         || this->surface_type == stInternalBridge | ||||
|         || this->surface_type == stInternalSolid | ||||
|         || this->surface_type == stInternalVoid; | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| Surface::is_top() const | ||||
| { | ||||
|     return this->surface_type == stTop; | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| Surface::is_bottom() const | ||||
| { | ||||
|     return this->surface_type == stBottom | ||||
|         || this->surface_type == stBottomBridge; | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| Surface::is_bridge() const | ||||
| { | ||||
|     return this->surface_type == stBottomBridge | ||||
|         || this->surface_type == stInternalBridge; | ||||
| } | ||||
| 
 | ||||
| BoundingBox get_extents(const Surface &surface) | ||||
| { | ||||
|     return get_extents(surface.expolygon.contour); | ||||
|  |  | |||
|  | @ -90,16 +90,18 @@ public: | |||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     operator Polygons() const; | ||||
|     double area() const; | ||||
|     bool empty() const { return expolygon.empty(); } | ||||
|     void clear() { expolygon.clear(); } | ||||
|     bool is_solid() const; | ||||
|     bool is_external() const; | ||||
|     bool is_internal() const; | ||||
|     bool is_top() const; | ||||
|     bool is_bottom() const; | ||||
|     bool is_bridge() const; | ||||
| 	operator Polygons()  const { return this->expolygon; } | ||||
| 	double area() 		 const { return this->expolygon.area(); } | ||||
|     bool   empty() 		 const { return expolygon.empty(); } | ||||
|     void   clear() 			   { expolygon.clear(); } | ||||
| 
 | ||||
|     // The following methods do not test for stPerimeter.
 | ||||
| 	bool   is_top()      const { return this->surface_type == stTop; } | ||||
| 	bool   is_bottom()   const { return this->surface_type == stBottom || this->surface_type == stBottomBridge; } | ||||
| 	bool   is_bridge()   const { return this->surface_type == stBottomBridge || this->surface_type == stInternalBridge; } | ||||
| 	bool   is_external() const { return this->is_top() || this->is_bottom(); } | ||||
| 	bool   is_internal() const { return ! this->is_external(); } | ||||
| 	bool   is_solid()    const { return this->is_external() || this->surface_type == stInternalSolid || this->surface_type == stInternalBridge; } | ||||
| }; | ||||
| 
 | ||||
| typedef std::vector<Surface> Surfaces; | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_ | |||
|         m_map[bitmap_key] = bitmap; | ||||
|     } else { | ||||
|         bitmap = it->second; | ||||
|         if (bitmap->GetWidth() != width || bitmap->GetHeight() != height) | ||||
|         if (size_t(bitmap->GetWidth()) != width || size_t(bitmap->GetHeight()) != height) | ||||
|             bitmap->Create(width, height); | ||||
|     } | ||||
| #ifndef BROKEN_ALPHA | ||||
|  | @ -194,7 +194,7 @@ wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned w | |||
|     return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image), scale)); | ||||
| } | ||||
| 
 | ||||
| wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int width, unsigned int height,  | ||||
| wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned width, unsigned height, | ||||
|     const bool grayscale/* = false*/) | ||||
| { | ||||
|     std::string bitmap_key = bitmap_name + ( height !=0 ?  | ||||
|  | @ -211,10 +211,10 @@ wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int wid | |||
|         image.GetWidth() == 0 || image.GetHeight() == 0) | ||||
|         return nullptr; | ||||
| 
 | ||||
|     if (height != 0 && image.GetHeight() != height) | ||||
|         width   = int(0.5f + float(image.GetWidth()) * height / image.GetHeight()); | ||||
|     else if (width != 0 && image.GetWidth() != width) | ||||
|         height  = int(0.5f + float(image.GetHeight()) * width / image.GetWidth()); | ||||
|     if (height != 0 && unsigned(image.GetHeight()) != height) | ||||
|         width   = unsigned(0.5f + float(image.GetWidth()) * height / image.GetHeight()); | ||||
|     else if (width != 0 && unsigned(image.GetWidth()) != width) | ||||
|         height  = unsigned(0.5f + float(image.GetHeight()) * width / image.GetWidth()); | ||||
| 
 | ||||
|     if (height != 0 && width != 0) | ||||
|         image.Rescale(width, height, wxIMAGE_QUALITY_BILINEAR); | ||||
|  |  | |||
|  | @ -32,9 +32,9 @@ public: | |||
| 	wxBitmap* 		insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, float scale = 1.0f, const bool grayscale = false); | ||||
| 
 | ||||
| 	// Load png from resources/icons. bitmap_key is given without the .png suffix. Bitmap will be rescaled to provided height/width if nonzero.
 | ||||
|     wxBitmap* 		load_png(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0, const bool grayscale = false); | ||||
|     wxBitmap* 		load_png(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false); | ||||
| 	// Load svg from resources/icons. bitmap_key is given without the .svg suffix. SVG will be rasterized to provided height/width.
 | ||||
|     wxBitmap* 		load_svg(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0, float scale = 1.0f, const bool grayscale = false); | ||||
|     wxBitmap* 		load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, float scale = 1.0f, const bool grayscale = false); | ||||
| 
 | ||||
| 	static wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency); | ||||
| 	static wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3]) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); } | ||||
|  |  | |||
|  | @ -189,7 +189,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true | |||
|     case coFloatOrPercent: { | ||||
|         if (m_opt.type == coFloatOrPercent && !str.IsEmpty() &&  str.Last() != '%') | ||||
|         { | ||||
|             double val; | ||||
|             double val = 0.; | ||||
| 			// Replace the first occurence of comma in decimal number.
 | ||||
| 			str.Replace(",", ".", false); | ||||
|             if (check_value && !str.ToCDouble(&val)) | ||||
|  | @ -198,7 +198,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true | |||
|                 set_value(double_to_string(val), true); | ||||
|             } | ||||
|             else if (check_value && ((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) || | ||||
|                      m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1) &&  | ||||
|                      (m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)) && | ||||
|                      (m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast<std::string>(m_value))) | ||||
|             { | ||||
|                 const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm"; | ||||
|  |  | |||
|  | @ -60,10 +60,6 @@ | |||
| #endif // ENABLE_RENDER_STATISTICS
 | ||||
| 
 | ||||
| static const float TRACKBALLSIZE = 0.8f; | ||||
| static const float GROUND_Z = -0.02f; | ||||
| 
 | ||||
| static const float GIZMO_RESET_BUTTON_HEIGHT = 22.0f; | ||||
| static const float GIZMO_RESET_BUTTON_WIDTH = 70.f; | ||||
| 
 | ||||
| static const float DEFAULT_BG_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f }; | ||||
| static const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f }; | ||||
|  |  | |||
|  | @ -434,7 +434,6 @@ private: | |||
|     bool m_initialized; | ||||
|     bool m_apply_zoom_to_volumes_filter; | ||||
|     mutable std::vector<int> m_hover_volume_idxs; | ||||
|     bool m_warning_texture_enabled; | ||||
|     bool m_legend_texture_enabled; | ||||
|     bool m_picking_enabled; | ||||
|     bool m_moving_enabled; | ||||
|  |  | |||
|  | @ -1074,8 +1074,8 @@ const std::vector<std::string>& ObjectList::get_options_for_bundle(const wxStrin | |||
| static bool improper_category(const std::string& category, const int extruders_cnt, const bool is_object_settings = true) | ||||
| { | ||||
|     return  category.empty() ||  | ||||
|             extruders_cnt == 1 && (category == "Extruders" || category == "Wipe options" ) || | ||||
|             !is_object_settings && category == "Support material"; | ||||
|             (extruders_cnt == 1 && (category == "Extruders" || category == "Wipe options" )) || | ||||
|             (!is_object_settings && category == "Support material"); | ||||
| } | ||||
| 
 | ||||
| void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part) | ||||
|  |  | |||
|  | @ -668,7 +668,7 @@ void ObjectManipulation::update_mirror_buttons_visibility() | |||
|     wxGetApp().CallAfter([this, new_states]{ | ||||
|         for (int i=0; i<3; ++i) { | ||||
|             if (new_states[i] != m_mirror_buttons[i].second) { | ||||
|                 const ScalableBitmap* bmp; | ||||
|                 const ScalableBitmap* bmp = nullptr; | ||||
|                 switch (new_states[i]) { | ||||
|                     case mbHidden : bmp = &m_mirror_bitmap_hidden; m_mirror_buttons[i].first->Enable(false); break; | ||||
|                     case mbShown  : bmp = &m_mirror_bitmap_off; m_mirror_buttons[i].first->Enable(true); break; | ||||
|  |  | |||
|  | @ -363,12 +363,14 @@ private: | |||
| 	MutableHistoryInterval& operator=(const MutableHistoryInterval &rhs); | ||||
| }; | ||||
| 
 | ||||
| #ifdef SLIC3R_UNDOREDO_DEBUG | ||||
| static inline std::string ptr_to_string(const void* ptr) | ||||
| { | ||||
| 	char buf[64]; | ||||
| 	sprintf(buf, "%p", ptr); | ||||
| 	return buf; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| // Smaller objects (Model, ModelObject, ModelInstance, ModelVolume, DynamicPrintConfig)
 | ||||
| // are mutable and there is not tracking of the changes, therefore a snapshot needs to be
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri