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:
bubnikv 2016-11-04 00:10:35 +01:00
parent f278fa454e
commit 483a658144
8 changed files with 97 additions and 69 deletions

View file

@ -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

View file

@ -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(); }

View file

@ -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;
}

View file

@ -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.;
}
};
}

View file

@ -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));
}
}

View file

@ -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*

View file

@ -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*

View file

@ -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*