Method ExtrusionEntity::polygons_covered() and derived were split
into polygons_covered_by_width() and polygons_covered_by_spacing(). Bugfix of ExtrusionLoop::split_at(const Point &point), where the split ExtrusionPaths were not initialised correctly.
This commit is contained in:
parent
f278fa454e
commit
483a658144
8 changed files with 97 additions and 69 deletions
|
@ -3,6 +3,7 @@
|
|||
#include "ExPolygonCollection.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Extruder.hpp"
|
||||
#include "Flow.hpp"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
@ -55,12 +56,17 @@ ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCo
|
|||
}
|
||||
}
|
||||
|
||||
Polygons
|
||||
ExtrusionPath::polygons_covered() const
|
||||
void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
Polygons pp;
|
||||
offset(this->polyline, &pp, +scale_(this->width/2));
|
||||
return pp;
|
||||
offset(this->polyline, &out, scale_(this->width/2) + scaled_epsilon);
|
||||
}
|
||||
|
||||
void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
// Instantiating the Flow class to get the line spacing.
|
||||
// Don't know the nozzle diameter, setting to zero. It shall not matter it shall be optimized out by the compiler.
|
||||
Flow flow(this->width, this->height, 0.f, this->is_bridge());
|
||||
offset(this->polyline, &out, 0.5f * flow.scaled_spacing() + scaled_epsilon);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -168,8 +174,10 @@ ExtrusionLoop::split_at(const Point &point)
|
|||
}
|
||||
|
||||
// now split path_idx in two parts
|
||||
ExtrusionPath p1(this->paths[path_idx].role), p2(this->paths[path_idx].role);
|
||||
this->paths[path_idx].polyline.split_at(p, &p1.polyline, &p2.polyline);
|
||||
const ExtrusionPath &path = this->paths[path_idx];
|
||||
ExtrusionPath p1(path.role, path.mm3_per_mm, path.width, path.height);
|
||||
ExtrusionPath p2(path.role, path.mm3_per_mm, path.width, path.height);
|
||||
path.polyline.split_at(p, &p1.polyline, &p2.polyline);
|
||||
|
||||
if (this->paths.size() == 1) {
|
||||
if (! p1.polyline.is_valid())
|
||||
|
@ -223,13 +231,16 @@ ExtrusionLoop::has_overhang_point(const Point &point) const
|
|||
return false;
|
||||
}
|
||||
|
||||
Polygons
|
||||
ExtrusionLoop::polygons_covered() const
|
||||
void ExtrusionLoop::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
Polygons pp;
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
|
||||
polygons_append(pp, path->polygons_covered());
|
||||
return pp;
|
||||
path->polygons_covered_by_width(out, scaled_epsilon);
|
||||
}
|
||||
|
||||
void ExtrusionLoop::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
|
||||
path->polygons_covered_by_spacing(out, scaled_epsilon);
|
||||
}
|
||||
|
||||
double
|
||||
|
|
|
@ -45,12 +45,21 @@ public:
|
|||
virtual void reverse() = 0;
|
||||
virtual Point first_point() const = 0;
|
||||
virtual Point last_point() const = 0;
|
||||
// Produce a list of 2D polygons covered by the extruded path.
|
||||
virtual Polygons polygons_covered() const = 0;
|
||||
// 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.
|
||||
virtual void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const = 0;
|
||||
// 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.
|
||||
virtual void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const = 0;
|
||||
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.
|
||||
virtual double min_mm3_per_mm() const = 0;
|
||||
virtual Polyline as_polyline() const = 0;
|
||||
virtual double length() const { return 0; };
|
||||
virtual double length() const = 0;
|
||||
};
|
||||
|
||||
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
|
||||
|
@ -103,8 +112,17 @@ public:
|
|||
return this->role == erBridgeInfill
|
||||
|| this->role == erOverhangPerimeter;
|
||||
}
|
||||
// Produce a list of 2D polygons covered by the extruded path.
|
||||
Polygons polygons_covered() const;
|
||||
// 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;
|
||||
// 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;
|
||||
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; }
|
||||
|
@ -160,8 +178,17 @@ class ExtrusionLoop : public ExtrusionEntity
|
|||
|| this->paths.front().role == erSolidInfill
|
||||
|| this->paths.front().role == erTopSolidInfill;
|
||||
}
|
||||
// Produce a list of 2D polygons covered by the extruded path.
|
||||
Polygons polygons_covered() const;
|
||||
// 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;
|
||||
// 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;
|
||||
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(); }
|
||||
|
|
|
@ -72,24 +72,6 @@ ExtrusionEntityCollection::reverse()
|
|||
std::reverse(this->entities.begin(), this->entities.end());
|
||||
}
|
||||
|
||||
Point
|
||||
ExtrusionEntityCollection::first_point() const
|
||||
{
|
||||
return this->entities.front()->first_point();
|
||||
}
|
||||
|
||||
Point
|
||||
ExtrusionEntityCollection::last_point() const
|
||||
{
|
||||
return this->entities.back()->last_point();
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionEntityCollection::append(const ExtrusionEntity &entity)
|
||||
{
|
||||
this->entities.push_back(entity.clone());
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionEntityCollection::append(const ExtrusionEntitiesPtr &entities)
|
||||
{
|
||||
|
@ -180,13 +162,16 @@ ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEntityCo
|
|||
}
|
||||
}
|
||||
|
||||
Polygons
|
||||
ExtrusionEntityCollection::polygons_covered() const
|
||||
void ExtrusionEntityCollection::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
Polygons pp;
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
|
||||
polygons_append(pp, (*it)->polygons_covered());
|
||||
return pp;
|
||||
(*it)->polygons_covered_by_width(out, scaled_epsilon);
|
||||
}
|
||||
|
||||
void ExtrusionEntityCollection::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
|
||||
{
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
|
||||
(*it)->polygons_covered_by_spacing(out, scaled_epsilon);
|
||||
}
|
||||
|
||||
/* Recursively count paths and loops contained in this collection */
|
||||
|
@ -230,15 +215,9 @@ ExtrusionEntityCollection::flatten() const
|
|||
double
|
||||
ExtrusionEntityCollection::min_mm3_per_mm() const
|
||||
{
|
||||
double min_mm3_per_mm = 0;
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
|
||||
double mm3_per_mm = (*it)->min_mm3_per_mm();
|
||||
if (min_mm3_per_mm == 0) {
|
||||
min_mm3_per_mm = mm3_per_mm;
|
||||
} else {
|
||||
min_mm3_per_mm = fmin(min_mm3_per_mm, mm3_per_mm);
|
||||
}
|
||||
}
|
||||
double min_mm3_per_mm = std::numeric_limits<double>::max();
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
|
||||
min_mm3_per_mm = std::min(min_mm3_per_mm, (*it)->min_mm3_per_mm());
|
||||
return min_mm3_per_mm;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Slic3r {
|
|||
|
||||
class ExtrusionEntityCollection : public ExtrusionEntity
|
||||
{
|
||||
public:
|
||||
public:
|
||||
ExtrusionEntityCollection* clone() const;
|
||||
ExtrusionEntitiesPtr entities; // we own these entities
|
||||
std::vector<size_t> orig_indices; // handy for XS
|
||||
|
@ -20,18 +20,12 @@ class ExtrusionEntityCollection : public ExtrusionEntity
|
|||
~ExtrusionEntityCollection() { clear(); }
|
||||
operator ExtrusionPaths() const;
|
||||
|
||||
bool is_collection() const {
|
||||
return true;
|
||||
};
|
||||
bool can_reverse() const {
|
||||
return !this->no_sort;
|
||||
};
|
||||
bool empty() const {
|
||||
return this->entities.empty();
|
||||
};
|
||||
bool is_collection() const { return true; };
|
||||
bool can_reverse() const { return !this->no_sort; };
|
||||
bool empty() const { return this->entities.empty(); };
|
||||
void clear();
|
||||
void swap (ExtrusionEntityCollection &c);
|
||||
void append(const ExtrusionEntity &entity);
|
||||
void append(const ExtrusionEntity &entity) { this->entities.push_back(entity.clone()); }
|
||||
void append(const ExtrusionEntitiesPtr &entities);
|
||||
void append(const ExtrusionPaths &paths);
|
||||
void replace(size_t i, const ExtrusionEntity &entity);
|
||||
|
@ -40,9 +34,19 @@ class ExtrusionEntityCollection : public ExtrusionEntity
|
|||
void chained_path(ExtrusionEntityCollection* retval, bool no_reverse = false, std::vector<size_t>* orig_indices = NULL) const;
|
||||
void chained_path_from(Point start_near, ExtrusionEntityCollection* retval, bool no_reverse = false, std::vector<size_t>* orig_indices = NULL) const;
|
||||
void reverse();
|
||||
Point first_point() const;
|
||||
Point last_point() const;
|
||||
Polygons polygons_covered() const;
|
||||
Point first_point() const { return this->entities.front()->first_point(); }
|
||||
Point last_point() const { return this->entities.back()->last_point(); }
|
||||
// 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.
|
||||
virtual void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const;
|
||||
// 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.
|
||||
virtual void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const;
|
||||
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; }
|
||||
size_t items_count() const;
|
||||
void flatten(ExtrusionEntityCollection* retval) const;
|
||||
ExtrusionEntityCollection flatten() const;
|
||||
|
@ -51,6 +55,10 @@ class ExtrusionEntityCollection : public ExtrusionEntity
|
|||
CONFESS("Calling as_polyline() on a ExtrusionEntityCollection");
|
||||
return Polyline();
|
||||
};
|
||||
virtual double length() const {
|
||||
CONFESS("Calling length() on a ExtrusionEntityCollection");
|
||||
return 0.;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ PerimeterGenerator::process()
|
|||
and use zigzag). */
|
||||
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
|
||||
// therefore it may cover the area, but no the volume.
|
||||
last = diff(last, gap_fill.polygons_covered());
|
||||
last = diff(last, gap_fill.polygons_covered_by_width(10.f));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@
|
|||
%code{% RETVAL = THIS->entities.empty(); %};
|
||||
std::vector<size_t> orig_indices()
|
||||
%code{% RETVAL = THIS->orig_indices; %};
|
||||
Polygons polygons_covered();
|
||||
Polygons polygons_covered_by_width();
|
||||
Polygons polygons_covered_by_spacing();
|
||||
%{
|
||||
|
||||
SV*
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
bool is_perimeter();
|
||||
bool is_infill();
|
||||
bool is_solid_infill();
|
||||
Polygons polygons_covered();
|
||||
Polygons polygons_covered_by_width();
|
||||
Polygons polygons_covered_by_spacing();
|
||||
%{
|
||||
|
||||
SV*
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
bool is_infill();
|
||||
bool is_solid_infill();
|
||||
bool is_bridge();
|
||||
Polygons polygons_covered();
|
||||
Polygons polygons_covered_by_width();
|
||||
Polygons polygons_covered_by_spacing();
|
||||
%{
|
||||
|
||||
ExtrusionPath*
|
||||
|
|
Loading…
Reference in a new issue