mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-16 19:05:59 +08:00
Review of spacing & volume compute, add a test for that.
Change a bit the fill api, to allow a bit safer spacing init and ensure nothing erase a parameter in mid-compute.
This commit is contained in:
parent
9ae142ef3e
commit
9c6008e5e0
@ -235,6 +235,23 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Set Params for fill
|
||||||
|
// apply half spacing using this flow's own spacing and generate infill
|
||||||
|
FillParams params;
|
||||||
|
params.density = float(0.01 * density);
|
||||||
|
params.dont_adjust = false;
|
||||||
|
params.fill_exactly = layerm.region()->config().enforce_full_fill_volume.getBool();
|
||||||
|
params.dont_connect = layerm.region()->config().infill_not_connected.getBool();
|
||||||
|
//adjust flow (to over-extrude when needed)
|
||||||
|
float flow_percent = 1;
|
||||||
|
if (surface.has_pos_top()) flow_percent *= layerm.region()->config().fill_top_flow_ratio.get_abs_value(1);
|
||||||
|
params.flow_mult = flow_percent;
|
||||||
|
//adjust spacing (to over-extrude when needed)
|
||||||
|
if (surface.has_mod_overBridge()) {
|
||||||
|
params.density = layerm.region()->config().over_bridge_flow_ratio.get_abs_value(1);
|
||||||
|
}
|
||||||
|
params.config = &layerm.region()->config();
|
||||||
|
|
||||||
// get filler object
|
// get filler object
|
||||||
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(fill_pattern));
|
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(fill_pattern));
|
||||||
f->set_bounding_box(layerm.layer()->object()->bounding_box());
|
f->set_bounding_box(layerm.layer()->object()->bounding_box());
|
||||||
@ -252,7 +269,9 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
|
|
||||||
// calculate flow spacing for infill pattern generation
|
// calculate flow spacing for infill pattern generation
|
||||||
bool using_internal_flow = false;
|
bool using_internal_flow = false;
|
||||||
if (! surface.has_fill_solid() && ! is_bridge) {
|
{
|
||||||
|
coordf_t spacing;
|
||||||
|
if (!surface.has_fill_solid() && !is_bridge) {
|
||||||
// it's internal infill, so we can calculate a generic flow spacing
|
// it's internal infill, so we can calculate a generic flow spacing
|
||||||
// for all layers, for avoiding the ugly effect of
|
// for all layers, for avoiding the ugly effect of
|
||||||
// misaligned infill on first layer because of different extrusion width and
|
// misaligned infill on first layer because of different extrusion width and
|
||||||
@ -265,16 +284,19 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
-1, // auto width
|
-1, // auto width
|
||||||
*layerm.layer()->object()
|
*layerm.layer()->object()
|
||||||
);
|
);
|
||||||
f->spacing = internal_flow.spacing();
|
spacing = internal_flow.spacing();
|
||||||
using_internal_flow = true;
|
using_internal_flow = true;
|
||||||
} else {
|
}
|
||||||
f->spacing = flow.spacing();
|
else {
|
||||||
|
spacing = flow.spacing();
|
||||||
|
}
|
||||||
|
f->init_spacing(spacing, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
double link_max_length = 0.;
|
double link_max_length = 0.;
|
||||||
if (! is_bridge) {
|
if (! is_bridge) {
|
||||||
if (density > 80.) // 80%
|
if (density > 80.) // 80%
|
||||||
link_max_length = 3 * f->spacing; // slic3r default : 3
|
link_max_length = 3 * f->get_spacing(); // slic3r default : 3
|
||||||
}
|
}
|
||||||
|
|
||||||
f->layer_id = layerm.layer()->id();
|
f->layer_id = layerm.layer()->id();
|
||||||
@ -288,7 +310,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
//give the overlap size to let the infill do his overlap
|
//give the overlap size to let the infill do his overlap
|
||||||
//add overlap if at least one perimeter
|
//add overlap if at least one perimeter
|
||||||
if (layerm.region()->config().perimeters > 0) {
|
if (layerm.region()->config().perimeters > 0) {
|
||||||
f->overlap = layerm.region()->config().get_abs_value("infill_overlap", (perimeter_spacing + (f->spacing)) / 2);
|
f->overlap = layerm.region()->config().get_abs_value("infill_overlap", (perimeter_spacing + (f->get_spacing())) / 2);
|
||||||
if (f->overlap!=0) {
|
if (f->overlap!=0) {
|
||||||
f->no_overlap_expolygons = intersection_ex(layerm.fill_no_overlap_expolygons, ExPolygons() = { surface.expolygon });
|
f->no_overlap_expolygons = intersection_ex(layerm.fill_no_overlap_expolygons, ExPolygons() = { surface.expolygon });
|
||||||
} else {
|
} else {
|
||||||
@ -299,13 +321,6 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
f->no_overlap_expolygons.push_back(surface.expolygon);
|
f->no_overlap_expolygons.push_back(surface.expolygon);
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply half spacing using this flow's own spacing and generate infill
|
|
||||||
FillParams params;
|
|
||||||
params.density = float(0.01 * density);
|
|
||||||
params.dont_adjust = false;
|
|
||||||
params.fill_exactly = layerm.region()->config().enforce_full_fill_volume.getBool();
|
|
||||||
params.dont_connect = layerm.region()->config().infill_not_connected.getBool();
|
|
||||||
|
|
||||||
// calculate actual flow from spacing (which might have been adjusted by the infill
|
// calculate actual flow from spacing (which might have been adjusted by the infill
|
||||||
// pattern generator)
|
// pattern generator)
|
||||||
if (using_internal_flow) {
|
if (using_internal_flow) {
|
||||||
@ -313,21 +328,10 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
// so we can safely ignore the slight variation that might have
|
// so we can safely ignore the slight variation that might have
|
||||||
// been applied to $f->flow_spacing
|
// been applied to $f->flow_spacing
|
||||||
} else {
|
} else {
|
||||||
flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, (float)h, is_bridge);
|
flow = Flow::new_from_spacing(f->get_spacing(), flow.nozzle_diameter, (float)h, is_bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
//adjust flow (to over-extrude when needed)
|
|
||||||
float flow_percent = 1;
|
|
||||||
if (surface.has_pos_top()) flow_percent *= layerm.region()->config().fill_top_flow_ratio.get_abs_value(1);
|
|
||||||
params.flow_mult = flow_percent;
|
|
||||||
|
|
||||||
//adjust spacing (to over-extrude when needed)
|
|
||||||
if (surface.has_mod_overBridge()){
|
|
||||||
params.density = layerm.region()->config().over_bridge_flow_ratio.get_abs_value(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
params.flow = &flow;
|
params.flow = &flow;
|
||||||
params.config = &layerm.region()->config();
|
|
||||||
f->fill_surface_extrusion(&surface, params, out.entities);
|
f->fill_surface_extrusion(&surface, params, out.entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "FillRectilinear2.hpp"
|
#include "FillRectilinear2.hpp"
|
||||||
#include "FillRectilinear3.hpp"
|
#include "FillRectilinear3.hpp"
|
||||||
#include "FillSmooth.hpp"
|
#include "FillSmooth.hpp"
|
||||||
|
#include "../MedialAxis.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ Fill* Fill::new_from_type(const std::string &type)
|
|||||||
return (it == enum_keys_map.end()) ? nullptr : new_from_type(InfillPattern(it->second));
|
return (it == enum_keys_map.end()) ? nullptr : new_from_type(InfillPattern(it->second));
|
||||||
}
|
}
|
||||||
|
|
||||||
Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms) const
|
||||||
{
|
{
|
||||||
// Perform offset.
|
// Perform offset.
|
||||||
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, double(scale_(0 - 0.5 * this->spacing)));
|
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, double(scale_(0 - 0.5 * this->spacing)));
|
||||||
@ -140,7 +141,7 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
|
|||||||
return std::pair<float, Point>(out_angle, out_shift);
|
return std::pair<float, Point>(out_angle, out_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) {
|
void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const {
|
||||||
//add overlap & call fill_surface
|
//add overlap & call fill_surface
|
||||||
Polylines polylines = this->fill_surface(surface, params);
|
Polylines polylines = this->fill_surface(surface, params);
|
||||||
if (polylines.empty())
|
if (polylines.empty())
|
||||||
@ -163,14 +164,6 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶
|
|||||||
double poylineVolume = 0;
|
double poylineVolume = 0;
|
||||||
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
|
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
|
||||||
poylineVolume += params.flow->height*unscaled(unscaled(poly->area()));
|
poylineVolume += params.flow->height*unscaled(unscaled(poly->area()));
|
||||||
// add external "perimeter gap"
|
|
||||||
double perimeterRoundGap = unscaled(poly->contour.length()) * params.flow->height * (1 - 0.25*PI) * 0.5;
|
|
||||||
// add holes "perimeter gaps"
|
|
||||||
double holesGaps = 0;
|
|
||||||
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
|
|
||||||
holesGaps += unscaled(hole->length()) * params.flow->height * (1 - 0.25*PI) * 0.5;
|
|
||||||
}
|
|
||||||
poylineVolume += perimeterRoundGap + holesGaps;
|
|
||||||
}
|
}
|
||||||
//printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n",
|
//printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n",
|
||||||
// extrudedVolume,
|
// extrudedVolume,
|
||||||
@ -203,6 +196,10 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
coord_t Fill::_line_spacing_for_density(float density) const
|
||||||
|
{
|
||||||
|
return coord_t(scale_(this->spacing) / density);
|
||||||
|
}
|
||||||
|
|
||||||
/// cut poly between poly.point[idx_1] & poly.point[idx_1+1]
|
/// cut poly between poly.point[idx_1] & poly.point[idx_1+1]
|
||||||
/// add p1+-width to one part and p2+-width to the other one.
|
/// add p1+-width to one part and p2+-width to the other one.
|
||||||
@ -461,7 +458,8 @@ Points getFrontier(Polylines &polylines, const Point& p1, const Point& p2, const
|
|||||||
/// return the connected polylines in polylines_out. Can output polygons (stored as polylines with first_point = last_point).
|
/// return the connected polylines in polylines_out. Can output polygons (stored as polylines with first_point = last_point).
|
||||||
/// complexity: worst: N(infill_ordered.points) x N(boundary.points)
|
/// complexity: worst: N(infill_ordered.points) x N(boundary.points)
|
||||||
/// typical: N(infill_ordered) x ( N(boundary.points) + N(infill_ordered.points) )
|
/// typical: N(infill_ordered) x ( N(boundary.points) + N(infill_ordered.points) )
|
||||||
void Fill::connect_infill(const Polylines &infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const FillParams ¶ms) {
|
void
|
||||||
|
Fill::connect_infill(const Polylines &infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const FillParams ¶ms) const {
|
||||||
|
|
||||||
//TODO: fallback to the quick & dirty old algorithm when n(points) is too high.
|
//TODO: fallback to the quick & dirty old algorithm when n(points) is too high.
|
||||||
Polylines polylines_frontier = to_polylines(((Polygons)boundary));
|
Polylines polylines_frontier = to_polylines(((Polygons)boundary));
|
||||||
@ -573,4 +571,56 @@ void Fill::connect_infill(const Polylines &infill_ordered, const ExPolygon &boun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Fill::do_gap_fill(const ExPolygons &gapfill_areas, const FillParams ¶ms, ExtrusionEntitiesPtr &coll_out) const {
|
||||||
|
|
||||||
|
ThickPolylines polylines_gapfill;
|
||||||
|
double min = 0.4 * scale_(params.flow->nozzle_diameter) * (1 - INSET_OVERLAP_TOLERANCE);
|
||||||
|
double max = 2. * params.flow->scaled_width();
|
||||||
|
// collapse
|
||||||
|
//be sure we don't gapfill where the perimeters are already touching each other (negative spacing).
|
||||||
|
min = std::max(min, double(Flow::new_from_spacing(EPSILON, params.flow->nozzle_diameter, params.flow->height, false).scaled_width()));
|
||||||
|
//ExPolygons gapfill_areas_collapsed = diff_ex(
|
||||||
|
// offset2_ex(gapfill_areas, double(-min / 2), double(+min / 2)),
|
||||||
|
// offset2_ex(gapfill_areas, double(-max / 2), double(+max / 2)),
|
||||||
|
// true);
|
||||||
|
ExPolygons gapfill_areas_collapsed = offset2_ex(gapfill_areas, double(-min / 2), double(+min / 2));
|
||||||
|
for (const ExPolygon &ex : gapfill_areas_collapsed) {
|
||||||
|
//remove too small gaps that are too hard to fill.
|
||||||
|
//ie one that are smaller than an extrusion with width of min and a length of max.
|
||||||
|
if (ex.area() > scale_(params.flow->nozzle_diameter)*scale_(params.flow->nozzle_diameter) * 2) {
|
||||||
|
MedialAxis{ ex, params.flow->scaled_width() * 2, params.flow->scaled_width() / 5, coord_t(params.flow->height) }.build(polylines_gapfill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!polylines_gapfill.empty() && params.role != erBridgeInfill) {
|
||||||
|
//test
|
||||||
|
#ifdef _DEBUG
|
||||||
|
for (ThickPolyline poly : polylines_gapfill) {
|
||||||
|
for (coordf_t width : poly.width) {
|
||||||
|
if (width > params.flow->scaled_width() * 2.2) {
|
||||||
|
std::cerr << "ERRROR!!!! gapfill width = " << unscaled(width) << " > max_width = " << (params.flow->width * 2) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ExtrusionEntityCollection gap_fill = thin_variable_width(polylines_gapfill, erGapFill, *params.flow);
|
||||||
|
//set role if needed
|
||||||
|
if (params.role != erSolidInfill) {
|
||||||
|
ExtrusionSetRole set_good_role(params.role);
|
||||||
|
gap_fill.visit(set_good_role);
|
||||||
|
}
|
||||||
|
//move them into the collection
|
||||||
|
if (!gap_fill.entities.empty()) {
|
||||||
|
ExtrusionEntityCollection *coll_gapfill = new ExtrusionEntityCollection();
|
||||||
|
coll_gapfill->no_sort = this->no_sort();
|
||||||
|
coll_gapfill->append(std::move(gap_fill.entities));
|
||||||
|
coll_out.push_back(coll_gapfill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -73,8 +73,6 @@ public:
|
|||||||
size_t layer_id;
|
size_t layer_id;
|
||||||
// Z coordinate of the top print surface, in unscaled coordinates
|
// Z coordinate of the top print surface, in unscaled coordinates
|
||||||
coordf_t z;
|
coordf_t z;
|
||||||
// in unscaled coordinates
|
|
||||||
coordf_t spacing;
|
|
||||||
// infill / perimeter overlap, in unscaled coordinates
|
// infill / perimeter overlap, in unscaled coordinates
|
||||||
coordf_t overlap;
|
coordf_t overlap;
|
||||||
ExPolygons no_overlap_expolygons;
|
ExPolygons no_overlap_expolygons;
|
||||||
@ -88,6 +86,9 @@ public:
|
|||||||
coord_t loop_clipping;
|
coord_t loop_clipping;
|
||||||
// In scaled coordinates. Bounding box of the 2D projection of the object.
|
// In scaled coordinates. Bounding box of the 2D projection of the object.
|
||||||
BoundingBox bounding_box;
|
BoundingBox bounding_box;
|
||||||
|
protected:
|
||||||
|
// in unscaled coordinates, please use init (after settings all others settings) as some algos want to modify the value
|
||||||
|
coordf_t spacing;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Fill() {}
|
virtual ~Fill() {}
|
||||||
@ -96,15 +97,17 @@ public:
|
|||||||
static Fill* new_from_type(const std::string &type);
|
static Fill* new_from_type(const std::string &type);
|
||||||
|
|
||||||
void set_bounding_box(const Slic3r::BoundingBox &bbox) { bounding_box = bbox; }
|
void set_bounding_box(const Slic3r::BoundingBox &bbox) { bounding_box = bbox; }
|
||||||
|
virtual void init_spacing(coordf_t spacing, const FillParams ¶ms) { this->spacing = spacing; }
|
||||||
|
coordf_t get_spacing() const { return spacing; }
|
||||||
|
|
||||||
// Do not sort the fill lines to optimize the print head path?
|
// Do not sort the fill lines to optimize the print head path?
|
||||||
virtual bool no_sort() const { return false; }
|
virtual bool no_sort() const { return false; }
|
||||||
|
|
||||||
// This method have to fill the ExtrusionEntityCollection. It call fill_surface by default
|
// This method have to fill the ExtrusionEntityCollection. It call fill_surface by default
|
||||||
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out);
|
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const;
|
||||||
|
|
||||||
// Perform the fill.
|
// Perform the fill.
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fill() :
|
Fill() :
|
||||||
@ -127,17 +130,19 @@ protected:
|
|||||||
unsigned int /* thickness_layers */,
|
unsigned int /* thickness_layers */,
|
||||||
const std::pair<float, Point> & /* direction */,
|
const std::pair<float, Point> & /* direction */,
|
||||||
ExPolygon & /* expolygon */,
|
ExPolygon & /* expolygon */,
|
||||||
Polylines & /* polylines_out */) {};
|
Polylines & /* polylines_out */) const {};
|
||||||
|
|
||||||
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }
|
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }
|
||||||
|
|
||||||
|
virtual coord_t _line_spacing_for_density(float density) const;
|
||||||
|
|
||||||
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
||||||
|
|
||||||
void connect_infill(const Polylines &infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const FillParams ¶ms);
|
void connect_infill(const Polylines &infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const FillParams ¶ms) const;
|
||||||
|
|
||||||
void do_gap_fill(const ExPolygons &gapfill_areas, const FillParams ¶ms, ExtrusionEntitiesPtr &coll_out);
|
void do_gap_fill(const ExPolygons &gapfill_areas, const FillParams ¶ms, ExtrusionEntitiesPtr &coll_out) const;
|
||||||
|
|
||||||
ExtrusionRole getRoleFromSurfaceType(const FillParams ¶ms, const Surface *surface){
|
ExtrusionRole getRoleFromSurfaceType(const FillParams ¶ms, const Surface *surface) const {
|
||||||
if (params.role == erNone || params.role == erCustom) {
|
if (params.role == erNone || params.role == erCustom) {
|
||||||
return params.flow->bridge ?
|
return params.flow->bridge ?
|
||||||
erBridgeInfill :
|
erBridgeInfill :
|
||||||
|
@ -9,29 +9,36 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
void
|
||||||
|
FillConcentric::init_spacing(coordf_t spacing, const FillParams ¶ms)
|
||||||
|
{
|
||||||
|
Fill::init_spacing(spacing, params);
|
||||||
|
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||||
|
this->spacing = unscale<double>(this->_adjust_solid_spacing(bounding_box.size()(0), _line_spacing_for_density(params.density)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FillConcentric::_fill_surface_single(
|
void
|
||||||
|
FillConcentric::_fill_surface_single(
|
||||||
const FillParams ¶ms,
|
const FillParams ¶ms,
|
||||||
unsigned int thickness_layers,
|
unsigned int thickness_layers,
|
||||||
const std::pair<float, Point> &direction,
|
const std::pair<float, Point> &direction,
|
||||||
ExPolygon &expolygon,
|
ExPolygon &expolygon,
|
||||||
Polylines &polylines_out)
|
Polylines &polylines_out) const
|
||||||
{
|
{
|
||||||
// no rotation is supported for this infill pattern
|
// no rotation is supported for this infill pattern
|
||||||
BoundingBox bounding_box = expolygon.contour.bounding_box();
|
BoundingBox bounding_box = expolygon.contour.bounding_box();
|
||||||
|
|
||||||
coord_t min_spacing = scale_(this->spacing);
|
coord_t distance = _line_spacing_for_density(params.density);
|
||||||
coord_t distance = coord_t(min_spacing / params.density);
|
|
||||||
|
|
||||||
if (params.density > 0.9999f && !params.dont_adjust) {
|
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||||
distance = this->_adjust_solid_spacing(bounding_box.size()(0), distance);
|
//it's == this->_adjust_solid_spacing(bounding_box.size()(0), _line_spacing_for_density(params.density)) because of the init_spacing()
|
||||||
this->spacing = unscale<double>(distance);
|
distance = scale_(this->spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygons loops = (Polygons)expolygon;
|
Polygons loops = (Polygons)expolygon;
|
||||||
Polygons last = loops;
|
Polygons last = loops;
|
||||||
while (! last.empty()) {
|
while (! last.empty()) {
|
||||||
last = offset2(last, -(distance + min_spacing/2), +min_spacing/2);
|
last = offset2(last, -(distance + scale_(this->spacing) /2), +scale_(this->spacing) /2);
|
||||||
loops.insert(loops.end(), last.begin(), last.end());
|
loops.insert(loops.end(), last.begin(), last.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +73,7 @@ void FillConcentric::_fill_surface_single(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms,
|
void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms,
|
||||||
ExtrusionEntitiesPtr &out) {
|
ExtrusionEntitiesPtr &out) const {
|
||||||
|
|
||||||
// Perform offset.
|
// Perform offset.
|
||||||
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, double(scale_(0 - 0.5 * this->spacing)));
|
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, double(scale_(0 - 0.5 * this->spacing)));
|
||||||
@ -86,19 +93,16 @@ void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, cons
|
|||||||
// no rotation is supported for this infill pattern
|
// no rotation is supported for this infill pattern
|
||||||
BoundingBox bounding_box = expolygon.contour.bounding_box();
|
BoundingBox bounding_box = expolygon.contour.bounding_box();
|
||||||
|
|
||||||
coord_t min_spacing = scale_(this->spacing);
|
coord_t distance = _line_spacing_for_density(params.density);
|
||||||
coord_t distance = coord_t(min_spacing / params.density);
|
|
||||||
|
|
||||||
if (params.density > 0.9999f && !params.dont_adjust) {
|
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||||
distance = this->_adjust_solid_spacing(bounding_box.size().x(), distance);
|
distance = scale_(this->spacing);
|
||||||
this->spacing = unscaled(distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons gaps;
|
ExPolygons gaps;
|
||||||
Polygons loops = (Polygons)expolygon;
|
Polygons loops = (Polygons)expolygon;
|
||||||
Polygons last = loops;
|
Polygons last = loops;
|
||||||
while (!last.empty()) {
|
while (!last.empty()) {
|
||||||
Polygons next_onion = offset2(last, -(distance + min_spacing / 2), +min_spacing / 2);
|
Polygons next_onion = offset2(last, -(distance + scale_(this->spacing) / 2), +scale_(this->spacing) / 2);
|
||||||
loops.insert(loops.end(), next_onion.begin(), next_onion.end());
|
loops.insert(loops.end(), next_onion.begin(), next_onion.end());
|
||||||
append(gaps, diff_ex(
|
append(gaps, diff_ex(
|
||||||
offset(last, -0.5f * distance),
|
offset(last, -0.5f * distance),
|
||||||
|
@ -12,12 +12,13 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Fill* clone() const { return new FillConcentric(*this); };
|
virtual Fill* clone() const { return new FillConcentric(*this); };
|
||||||
|
void init_spacing(coordf_t spacing, const FillParams ¶ms) override;
|
||||||
virtual void _fill_surface_single(
|
virtual void _fill_surface_single(
|
||||||
const FillParams ¶ms,
|
const FillParams ¶ms,
|
||||||
unsigned int thickness_layers,
|
unsigned int thickness_layers,
|
||||||
const std::pair<float, Point> &direction,
|
const std::pair<float, Point> &direction,
|
||||||
ExPolygon &expolygon,
|
ExPolygon &expolygon,
|
||||||
Polylines &polylines_out);
|
Polylines &polylines_out) const;
|
||||||
|
|
||||||
virtual bool no_sort() const { return true; }
|
virtual bool no_sort() const { return true; }
|
||||||
};
|
};
|
||||||
@ -29,7 +30,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Fill* clone() const { return new FillConcentricWGapFill(*this); };
|
virtual Fill* clone() const { return new FillConcentricWGapFill(*this); };
|
||||||
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const override;
|
||||||
|
|
||||||
virtual bool no_sort() const { return true; }
|
virtual bool no_sort() const { return true; }
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ void FillPlanePath::_fill_surface_single(
|
|||||||
unsigned int thickness_layers,
|
unsigned int thickness_layers,
|
||||||
const std::pair<float, Point> &direction,
|
const std::pair<float, Point> &direction,
|
||||||
ExPolygon &expolygon,
|
ExPolygon &expolygon,
|
||||||
Polylines &polylines_out)
|
Polylines &polylines_out) const
|
||||||
{
|
{
|
||||||
expolygon.rotate(- direction.first);
|
expolygon.rotate(- direction.first);
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ void FillPlanePath::_fill_surface_single(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Follow an Archimedean spiral, in polar coordinates: r=a+b\theta
|
// Follow an Archimedean spiral, in polar coordinates: r=a+b\theta
|
||||||
Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y)
|
Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) const
|
||||||
{
|
{
|
||||||
// Radius to achieve.
|
// Radius to achieve.
|
||||||
coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5;
|
coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5;
|
||||||
@ -145,7 +145,7 @@ static inline Point hilbert_n_to_xy(const size_t n)
|
|||||||
return Point(x, y);
|
return Point(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y)
|
Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) const
|
||||||
{
|
{
|
||||||
// Minimum power of two square to fit the domain.
|
// Minimum power of two square to fit the domain.
|
||||||
size_t sz = 2;
|
size_t sz = 2;
|
||||||
@ -168,7 +168,7 @@ Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x,
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y)
|
Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) const
|
||||||
{
|
{
|
||||||
// Radius to achieve.
|
// Radius to achieve.
|
||||||
coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5;
|
coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5;
|
||||||
|
@ -24,11 +24,11 @@ protected:
|
|||||||
unsigned int thickness_layers,
|
unsigned int thickness_layers,
|
||||||
const std::pair<float, Point> &direction,
|
const std::pair<float, Point> &direction,
|
||||||
ExPolygon &expolygon,
|
ExPolygon &expolygon,
|
||||||
Polylines &polylines_out) override;
|
Polylines &polylines_out) const override;
|
||||||
|
|
||||||
virtual float _layer_angle(size_t idx) const { return 0.f; }
|
virtual float _layer_angle(size_t idx) const { return 0.f; }
|
||||||
virtual bool _centered() const = 0;
|
virtual bool _centered() const = 0;
|
||||||
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) = 0;
|
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillArchimedeanChords : public FillPlanePath
|
class FillArchimedeanChords : public FillPlanePath
|
||||||
@ -39,7 +39,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool _centered() const { return true; }
|
virtual bool _centered() const { return true; }
|
||||||
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y);
|
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillHilbertCurve : public FillPlanePath
|
class FillHilbertCurve : public FillPlanePath
|
||||||
@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool _centered() const { return false; }
|
virtual bool _centered() const { return false; }
|
||||||
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y);
|
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillOctagramSpiral : public FillPlanePath
|
class FillOctagramSpiral : public FillPlanePath
|
||||||
@ -61,7 +61,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool _centered() const { return true; }
|
virtual bool _centered() const { return true; }
|
||||||
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y);
|
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -865,12 +865,18 @@ std::vector<SegmentedIntersectionLine> FillRectilinear2::_vert_lines_for_polygon
|
|||||||
return segs;
|
return segs;
|
||||||
}
|
}
|
||||||
|
|
||||||
coord_t FillRectilinear2::_line_spacing_for_density(float density) const
|
void
|
||||||
|
FillRectilinear2::init_spacing(coordf_t spacing, const FillParams ¶ms)
|
||||||
{
|
{
|
||||||
return coord_t(scale_(this->spacing) / density);
|
Fill::init_spacing(spacing, params);
|
||||||
|
//remove this code path becaus it's only really useful for squares at 45° and it override a setting
|
||||||
|
// define flow spacing according to requested density
|
||||||
|
//if (params.full_infill() && !params.dont_adjust) {
|
||||||
|
// this->spacing = unscale<coordf_t>(this->_adjust_solid_spacing(bounding_box.size()(0), _line_spacing_for_density(params.density)));
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out)
|
bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out) const
|
||||||
{
|
{
|
||||||
// At the end, only the new polylines will be rotated back.
|
// At the end, only the new polylines will be rotated back.
|
||||||
size_t n_polylines_out_initial = polylines_out.size();
|
size_t n_polylines_out_initial = polylines_out.size();
|
||||||
@ -904,8 +910,8 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
|||||||
|
|
||||||
// define flow spacing according to requested density
|
// define flow spacing according to requested density
|
||||||
if (params.full_infill() && !params.dont_adjust) {
|
if (params.full_infill() && !params.dont_adjust) {
|
||||||
line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing);
|
//it's == this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing) because of the init_spacing
|
||||||
this->spacing = unscale<double>(line_spacing);
|
line_spacing = scale_(this->spacing);
|
||||||
} else {
|
} else {
|
||||||
// extend bounding box so that our pattern will be aligned with other layers
|
// extend bounding box so that our pattern will be aligned with other layers
|
||||||
// Transform the reference point to the rotated coordinate system.
|
// Transform the reference point to the rotated coordinate system.
|
||||||
@ -1441,7 +1447,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Polylines FillRectilinear2::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines FillRectilinear2::fill_surface(const Surface *surface, const FillParams ¶ms) const
|
||||||
{
|
{
|
||||||
Polylines polylines_out;
|
Polylines polylines_out;
|
||||||
if (!fill_surface_by_lines(surface, params, 0.f, 0.f, polylines_out)) {
|
if (!fill_surface_by_lines(surface, params, 0.f, 0.f, polylines_out)) {
|
||||||
@ -1450,7 +1456,7 @@ Polylines FillRectilinear2::fill_surface(const Surface *surface, const FillParam
|
|||||||
return polylines_out;
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Polylines FillGrid2::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines FillGrid2::fill_surface(const Surface *surface, const FillParams ¶ms) const
|
||||||
{
|
{
|
||||||
// Each linear fill covers half of the target coverage.
|
// Each linear fill covers half of the target coverage.
|
||||||
FillParams params2 = params;
|
FillParams params2 = params;
|
||||||
@ -1463,7 +1469,7 @@ Polylines FillGrid2::fill_surface(const Surface *surface, const FillParams ¶
|
|||||||
return polylines_out;
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Polylines FillTriangles::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines FillTriangles::fill_surface(const Surface *surface, const FillParams ¶ms) const
|
||||||
{
|
{
|
||||||
// Each linear fill covers 1/3 of the target coverage.
|
// Each linear fill covers 1/3 of the target coverage.
|
||||||
FillParams params2 = params;
|
FillParams params2 = params;
|
||||||
@ -1479,7 +1485,7 @@ Polylines FillTriangles::fill_surface(const Surface *surface, const FillParams &
|
|||||||
return polylines_out;
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Polylines FillStars::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines FillStars::fill_surface(const Surface *surface, const FillParams ¶ms) const
|
||||||
{
|
{
|
||||||
// Each linear fill covers 1/3 of the target coverage.
|
// Each linear fill covers 1/3 of the target coverage.
|
||||||
FillParams params2 = params;
|
FillParams params2 = params;
|
||||||
@ -1495,7 +1501,7 @@ Polylines FillStars::fill_surface(const Surface *surface, const FillParams ¶
|
|||||||
return polylines_out;
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶ms) const
|
||||||
{
|
{
|
||||||
// Each linear fill covers 1/3 of the target coverage.
|
// Each linear fill covers 1/3 of the target coverage.
|
||||||
FillParams params2 = params;
|
FillParams params2 = params;
|
||||||
@ -1515,7 +1521,7 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out)
|
FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const
|
||||||
{
|
{
|
||||||
ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection();
|
ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection();
|
||||||
//you don't want to sort the extrusions: big infill first, small second
|
//you don't want to sort the extrusions: big infill first, small second
|
||||||
@ -1623,7 +1629,7 @@ coord_t FillScatteredRectilinear::_line_spacing_for_density(float density) const
|
|||||||
return coord_t(scale_(this->spacing) / 1.0);
|
return coord_t(scale_(this->spacing) / 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Polylines FillScatteredRectilinear::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines FillScatteredRectilinear::fill_surface(const Surface *surface, const FillParams ¶ms) const
|
||||||
{
|
{
|
||||||
Polylines polylines_out;
|
Polylines polylines_out;
|
||||||
|
|
||||||
@ -1659,7 +1665,7 @@ std::vector<SegmentedIntersectionLine> FillScatteredRectilinear::_vert_lines_for
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FillRectilinearSawtooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) {
|
FillRectilinearSawtooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const {
|
||||||
const coord_t scaled_nozzle_diam = scale_(params.flow->nozzle_diameter);
|
const coord_t scaled_nozzle_diam = scale_(params.flow->nozzle_diameter);
|
||||||
const coord_t clearance = scaled_nozzle_diam * 2;
|
const coord_t clearance = scaled_nozzle_diam * 2;
|
||||||
const coord_t tooth_spacing_min = scaled_nozzle_diam;
|
const coord_t tooth_spacing_min = scaled_nozzle_diam;
|
||||||
@ -1770,7 +1776,8 @@ FillRectilinearSawtooth::fill_surface_extrusion(const Surface *surface, const Fi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FillRectilinear2WGapFill::split_polygon_gap_fill(const Surface &surface, const FillParams ¶ms, ExPolygons &rectilinear, ExPolygons &gapfill) {
|
void
|
||||||
|
FillRectilinear2WGapFill::split_polygon_gap_fill(const Surface &surface, const FillParams ¶ms, ExPolygons &rectilinear, ExPolygons &gapfill) {
|
||||||
|
|
||||||
// remove areas for gapfill
|
// remove areas for gapfill
|
||||||
// factor=0.5 : remove area smaller than a spacing. factor=1 : max spacing for the gapfill (but not the width)
|
// factor=0.5 : remove area smaller than a spacing. factor=1 : max spacing for the gapfill (but not the width)
|
||||||
@ -1786,7 +1793,7 @@ void FillRectilinear2WGapFill::split_polygon_gap_fill(const Surface &surface, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FillRectilinear2WGapFill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) {
|
FillRectilinear2WGapFill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const {
|
||||||
ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection();
|
ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection();
|
||||||
coll_nosort->no_sort = true; //can be sorted inside the pass
|
coll_nosort->no_sort = true; //can be sorted inside the pass
|
||||||
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
|
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
|
||||||
@ -1889,55 +1896,5 @@ FillRectilinear2WGapFill::fill_surface_extrusion(const Surface *surface, const F
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Fill::do_gap_fill(const ExPolygons &gapfill_areas, const FillParams ¶ms, ExtrusionEntitiesPtr &coll_out) {
|
|
||||||
|
|
||||||
ThickPolylines polylines_gapfill;
|
|
||||||
double min = 0.4 * scale_(params.flow->nozzle_diameter) * (1 - INSET_OVERLAP_TOLERANCE);
|
|
||||||
double max = 2. * params.flow->scaled_width();
|
|
||||||
// collapse
|
|
||||||
//be sure we don't gapfill where the perimeters are already touching each other (negative spacing).
|
|
||||||
min = std::max(min, double(Flow::new_from_spacing(EPSILON, params.flow->nozzle_diameter, params.flow->height, false).scaled_width()));
|
|
||||||
//ExPolygons gapfill_areas_collapsed = diff_ex(
|
|
||||||
// offset2_ex(gapfill_areas, double(-min / 2), double(+min / 2)),
|
|
||||||
// offset2_ex(gapfill_areas, double(-max / 2), double(+max / 2)),
|
|
||||||
// true);
|
|
||||||
ExPolygons gapfill_areas_collapsed = offset2_ex(gapfill_areas, double(-min / 2), double(+min / 2));
|
|
||||||
for (const ExPolygon &ex : gapfill_areas_collapsed) {
|
|
||||||
//remove too small gaps that are too hard to fill.
|
|
||||||
//ie one that are smaller than an extrusion with width of min and a length of max.
|
|
||||||
if (ex.area() > scale_(params.flow->nozzle_diameter)*scale_(params.flow->nozzle_diameter) * 2) {
|
|
||||||
MedialAxis{ ex, params.flow->scaled_width() * 2, params.flow->scaled_width() / 5, coord_t(params.flow->height) }.build(polylines_gapfill);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!polylines_gapfill.empty() && params.role != erBridgeInfill) {
|
|
||||||
//test
|
|
||||||
#ifdef _DEBUG
|
|
||||||
for (ThickPolyline poly : polylines_gapfill) {
|
|
||||||
for (coordf_t width : poly.width) {
|
|
||||||
if (width > params.flow->scaled_width() * 2.2) {
|
|
||||||
std::cerr << "ERRROR!!!! recti gapfill width = " << unscaled(width) << " > max_width = " << (params.flow->width * 2) << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ExtrusionEntityCollection gap_fill = thin_variable_width(polylines_gapfill, erGapFill, *params.flow);
|
|
||||||
//set role if needed
|
|
||||||
if (params.role != erSolidInfill) {
|
|
||||||
ExtrusionSetRole set_good_role(params.role);
|
|
||||||
gap_fill.visit(set_good_role);
|
|
||||||
}
|
|
||||||
//move them into the collection
|
|
||||||
if (!gap_fill.entities.empty()) {
|
|
||||||
ExtrusionEntityCollection *coll_gapfill = new ExtrusionEntityCollection();
|
|
||||||
coll_gapfill->no_sort = this->no_sort();
|
|
||||||
coll_gapfill->append(std::move(gap_fill.entities));
|
|
||||||
coll_out.push_back(coll_gapfill);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -16,13 +16,13 @@ class FillRectilinear2 : public Fill
|
|||||||
public:
|
public:
|
||||||
virtual Fill* clone() const { return new FillRectilinear2(*this); };
|
virtual Fill* clone() const { return new FillRectilinear2(*this); };
|
||||||
virtual ~FillRectilinear2() {}
|
virtual ~FillRectilinear2() {}
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
void init_spacing(coordf_t spacing, const FillParams ¶ms) override;
|
||||||
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual std::vector<SegmentedIntersectionLine> _vert_lines_for_polygon(const ExPolygonWithOffset &poly_with_offset, const BoundingBox &bounding_box, const FillParams ¶ms, coord_t line_spacing) const;
|
virtual std::vector<SegmentedIntersectionLine> _vert_lines_for_polygon(const ExPolygonWithOffset &poly_with_offset, const BoundingBox &bounding_box, const FillParams ¶ms, coord_t line_spacing) const;
|
||||||
virtual coord_t _line_spacing_for_density(float density) const;
|
|
||||||
|
|
||||||
bool fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out);
|
bool fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillGrid2 : public FillRectilinear2
|
class FillGrid2 : public FillRectilinear2
|
||||||
@ -30,7 +30,7 @@ class FillGrid2 : public FillRectilinear2
|
|||||||
public:
|
public:
|
||||||
virtual Fill* clone() const { return new FillGrid2(*this); };
|
virtual Fill* clone() const { return new FillGrid2(*this); };
|
||||||
virtual ~FillGrid2() {}
|
virtual ~FillGrid2() {}
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||||
@ -42,7 +42,7 @@ class FillTriangles : public FillRectilinear2
|
|||||||
public:
|
public:
|
||||||
virtual Fill* clone() const { return new FillTriangles(*this); };
|
virtual Fill* clone() const { return new FillTriangles(*this); };
|
||||||
virtual ~FillTriangles() {}
|
virtual ~FillTriangles() {}
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||||
@ -54,7 +54,7 @@ class FillStars : public FillRectilinear2
|
|||||||
public:
|
public:
|
||||||
virtual Fill* clone() const { return new FillStars(*this); };
|
virtual Fill* clone() const { return new FillStars(*this); };
|
||||||
virtual ~FillStars() {}
|
virtual ~FillStars() {}
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||||
@ -66,7 +66,7 @@ class FillCubic : public FillRectilinear2
|
|||||||
public:
|
public:
|
||||||
virtual Fill* clone() const { return new FillCubic(*this); };
|
virtual Fill* clone() const { return new FillCubic(*this); };
|
||||||
virtual ~FillCubic() {}
|
virtual ~FillCubic() {}
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||||
@ -80,7 +80,7 @@ public:
|
|||||||
virtual Fill* clone() const { return new FillRectilinear2Peri(*this); };
|
virtual Fill* clone() const { return new FillRectilinear2Peri(*this); };
|
||||||
virtual ~FillRectilinear2Peri() {}
|
virtual ~FillRectilinear2Peri() {}
|
||||||
//virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
//virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||||
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ class FillScatteredRectilinear : public FillRectilinear2
|
|||||||
public:
|
public:
|
||||||
virtual Fill* clone() const override{ return new FillScatteredRectilinear(*this); };
|
virtual Fill* clone() const override{ return new FillScatteredRectilinear(*this); };
|
||||||
virtual ~FillScatteredRectilinear() {}
|
virtual ~FillScatteredRectilinear() {}
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual float _layer_angle(size_t idx) const;
|
virtual float _layer_angle(size_t idx) const;
|
||||||
@ -103,7 +103,7 @@ public:
|
|||||||
|
|
||||||
virtual Fill* clone() const { return new FillRectilinearSawtooth(*this); };
|
virtual Fill* clone() const { return new FillRectilinearSawtooth(*this); };
|
||||||
virtual ~FillRectilinearSawtooth() {}
|
virtual ~FillRectilinearSawtooth() {}
|
||||||
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ public:
|
|||||||
|
|
||||||
virtual Fill* clone() const { return new FillRectilinear2WGapFill(*this); };
|
virtual Fill* clone() const { return new FillRectilinear2WGapFill(*this); };
|
||||||
virtual ~FillRectilinear2WGapFill() {}
|
virtual ~FillRectilinear2WGapFill() {}
|
||||||
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const override;
|
||||||
static void split_polygon_gap_fill(const Surface &surface, const FillParams ¶ms, ExPolygons &rectilinear, ExPolygons &gapfill);
|
static void split_polygon_gap_fill(const Surface &surface, const FillParams ¶ms, ExPolygons &rectilinear, ExPolygons &gapfill);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
Polylines FillSmooth::fill_surface(const Surface *surface, const FillParams ¶ms)
|
Polylines FillSmooth::fill_surface(const Surface *surface, const FillParams ¶ms) const
|
||||||
{
|
{
|
||||||
//ERROR: you shouldn't call that. Default to the rectilinear one.
|
//ERROR: you shouldn't call that. Default to the rectilinear one.
|
||||||
printf("FillSmooth::fill_surface() : you call the wrong method (fill_surface instead of fill_surface_extrusion).\n");
|
printf("FillSmooth::fill_surface() : you call the wrong method (fill_surface instead of fill_surface_extrusion).\n");
|
||||||
@ -20,7 +20,7 @@ namespace Slic3r {
|
|||||||
|
|
||||||
/// @idx: the index of the step (0 = first step, 1 = second step, ...) The first lay down the volume and the others smoothen the surface.
|
/// @idx: the index of the step (0 = first step, 1 = second step, ...) The first lay down the volume and the others smoothen the surface.
|
||||||
void FillSmooth::perform_single_fill(const int idx, ExtrusionEntityCollection &eecroot, const Surface &srf_source,
|
void FillSmooth::perform_single_fill(const int idx, ExtrusionEntityCollection &eecroot, const Surface &srf_source,
|
||||||
const FillParams ¶ms, const double volume){
|
const FillParams ¶ms, const double volume) const {
|
||||||
if (srf_source.expolygon.empty()) return;
|
if (srf_source.expolygon.empty()) return;
|
||||||
|
|
||||||
// Save into layer smoothing path.
|
// Save into layer smoothing path.
|
||||||
@ -44,7 +44,7 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Surface surfaceNoOverlap(srf_source);
|
Surface surfaceNoOverlap(srf_source);
|
||||||
for (ExPolygon &poly : this->no_overlap_expolygons) {
|
for (const ExPolygon &poly : this->no_overlap_expolygons) {
|
||||||
if (poly.empty()) continue;
|
if (poly.empty()) continue;
|
||||||
surfaceNoOverlap.expolygon = poly;
|
surfaceNoOverlap.expolygon = poly;
|
||||||
this->fill_expolygon(idx, *eec, surfaceNoOverlap, params_modifided, volume);
|
this->fill_expolygon(idx, *eec, surfaceNoOverlap, params_modifided, volume);
|
||||||
@ -56,11 +56,11 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FillSmooth::fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill,
|
void FillSmooth::fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill,
|
||||||
const FillParams ¶ms, const double volume){
|
const FillParams ¶ms, const double volume) const {
|
||||||
|
|
||||||
std::unique_ptr<Fill> f2 = std::unique_ptr<Fill>(Fill::new_from_type(fillPattern[idx]));
|
std::unique_ptr<Fill> f2 = std::unique_ptr<Fill>(Fill::new_from_type(fillPattern[idx]));
|
||||||
f2->bounding_box = this->bounding_box;
|
f2->bounding_box = this->bounding_box;
|
||||||
f2->spacing = this->spacing;
|
f2->init_spacing(this->get_spacing(),params);
|
||||||
f2->layer_id = this->layer_id;
|
f2->layer_id = this->layer_id;
|
||||||
f2->z = this->z;
|
f2->z = this->z;
|
||||||
f2->angle = anglePass[idx] + this->angle;
|
f2->angle = anglePass[idx] + this->angle;
|
||||||
@ -102,7 +102,7 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FillSmooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out)
|
void FillSmooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const
|
||||||
{
|
{
|
||||||
coordf_t init_spacing = this->spacing;
|
coordf_t init_spacing = this->spacing;
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ public:
|
|||||||
}
|
}
|
||||||
virtual Fill* clone() const{ return new FillSmooth(*this); }
|
virtual Fill* clone() const{ return new FillSmooth(*this); }
|
||||||
|
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) const override;
|
||||||
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int nbPass=2;
|
int nbPass=2;
|
||||||
@ -56,9 +56,9 @@ protected:
|
|||||||
InfillPattern fillPattern[3];
|
InfillPattern fillPattern[3];
|
||||||
|
|
||||||
void perform_single_fill(const int idx, ExtrusionEntityCollection &eecroot, const Surface &srf_source,
|
void perform_single_fill(const int idx, ExtrusionEntityCollection &eecroot, const Surface &srf_source,
|
||||||
const FillParams ¶ms, const double volume);
|
const FillParams ¶ms, const double volume) const;
|
||||||
void fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill,
|
void fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill,
|
||||||
const FillParams ¶ms, const double volume);
|
const FillParams ¶ms, const double volume) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1220,9 +1220,9 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->full_label = L("Ironing flow distribution");
|
def->full_label = L("Ironing flow distribution");
|
||||||
def->category = OptionCategory::infill;
|
def->category = OptionCategory::infill;
|
||||||
def->tooltip = L("This is the percentage of the flow that is used for the second ironing pass. Typical 0-20%. "
|
def->tooltip = L("This is the percentage of the flow that is used for the second ironing pass. Typical 0-20%. "
|
||||||
"Should not be lower than 20%, unless you have your top extrusion width greatly superior to your nozzle width.");
|
"Should not be higher than 20%, unless you have your top extrusion width greatly superior to your nozzle width.");
|
||||||
def->min = 0;
|
//def->min = 0;
|
||||||
def->max = 0.9;
|
//def->max = 0.9;
|
||||||
def->mode = comExpert;
|
def->mode = comExpert;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(10, true));
|
def->set_default_value(new ConfigOptionFloatOrPercent(10, true));
|
||||||
|
|
||||||
|
@ -2337,7 +2337,8 @@ static inline void fill_expolygons_generate_paths(
|
|||||||
Fill *filler,
|
Fill *filler,
|
||||||
float density,
|
float density,
|
||||||
ExtrusionRole role,
|
ExtrusionRole role,
|
||||||
const Flow &flow)
|
const Flow &flow,
|
||||||
|
coordf_t spacing)
|
||||||
{
|
{
|
||||||
FillParams fill_params;
|
FillParams fill_params;
|
||||||
fill_params.density = density;
|
fill_params.density = density;
|
||||||
@ -2345,6 +2346,7 @@ static inline void fill_expolygons_generate_paths(
|
|||||||
fill_params.dont_adjust = true;
|
fill_params.dont_adjust = true;
|
||||||
fill_params.flow = &flow;
|
fill_params.flow = &flow;
|
||||||
fill_params.role = role;
|
fill_params.role = role;
|
||||||
|
filler->init_spacing(spacing, fill_params);
|
||||||
for (ExPolygon &expoly : expolygons) {
|
for (ExPolygon &expoly : expolygons) {
|
||||||
Surface surface(stPosInternal | stDensSparse, std::move(expoly));
|
Surface surface(stPosInternal | stDensSparse, std::move(expoly));
|
||||||
filler->fill_surface_extrusion(&surface, fill_params, dst);
|
filler->fill_surface_extrusion(&surface, fill_params, dst);
|
||||||
@ -3059,8 +3061,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
// value that guarantees that all layers are correctly aligned.
|
// value that guarantees that all layers are correctly aligned.
|
||||||
Fill *filler = filler_support.get();
|
Fill *filler = filler_support.get();
|
||||||
filler->angle = raft_angle_base;
|
filler->angle = raft_angle_base;
|
||||||
filler->spacing = m_support_material_flow.spacing();
|
filler->link_max_length = coord_t(scale_(m_support_material_flow.spacing() * link_max_length_factor / support_density));
|
||||||
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / support_density));
|
|
||||||
fill_expolygons_generate_paths(
|
fill_expolygons_generate_paths(
|
||||||
// Destination
|
// Destination
|
||||||
support_layer.support_fills.entities,
|
support_layer.support_fills.entities,
|
||||||
@ -3069,7 +3070,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
// Filler and its parameters
|
// Filler and its parameters
|
||||||
filler, float(support_density),
|
filler, float(support_density),
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
erSupportMaterial, flow);
|
erSupportMaterial, flow, m_support_material_flow.spacing());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3077,6 +3078,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
Fill *filler = filler_interface.get();
|
Fill *filler = filler_interface.get();
|
||||||
Flow flow = m_first_layer_flow;
|
Flow flow = m_first_layer_flow;
|
||||||
float density = 0.f;
|
float density = 0.f;
|
||||||
|
coordf_t spacing = 0.f;
|
||||||
if (support_layer_id == 0) {
|
if (support_layer_id == 0) {
|
||||||
// Base flange.
|
// Base flange.
|
||||||
if (this->m_object_config->support_material_solid_first_layer.value) {
|
if (this->m_object_config->support_material_solid_first_layer.value) {
|
||||||
@ -3088,17 +3090,17 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
// 70% of density on the 1st layer.
|
// 70% of density on the 1st layer.
|
||||||
density = 0.7f;
|
density = 0.7f;
|
||||||
}
|
}
|
||||||
filler->spacing = m_first_layer_flow.spacing();
|
spacing = m_first_layer_flow.spacing();
|
||||||
} else if (support_layer_id >= m_slicing_params.base_raft_layers) {
|
} else if (support_layer_id >= m_slicing_params.base_raft_layers) {
|
||||||
filler->angle = raft_angle_interface;
|
filler->angle = raft_angle_interface;
|
||||||
// We don't use $base_flow->spacing because we need a constant spacing
|
// We don't use $base_flow->spacing because we need a constant spacing
|
||||||
// value that guarantees that all layers are correctly aligned.
|
// value that guarantees that all layers are correctly aligned.
|
||||||
filler->spacing = m_support_material_flow.spacing();
|
spacing = m_support_material_flow.spacing();
|
||||||
flow = Flow(float(m_support_material_interface_flow.width), float(raft_layer.height), m_support_material_flow.nozzle_diameter, raft_layer.bridging);
|
flow = Flow(float(m_support_material_interface_flow.width), float(raft_layer.height), m_support_material_flow.nozzle_diameter, raft_layer.bridging);
|
||||||
density = float(interface_density);
|
density = float(interface_density);
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density));
|
filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / density));
|
||||||
fill_expolygons_generate_paths(
|
fill_expolygons_generate_paths(
|
||||||
// Destination
|
// Destination
|
||||||
support_layer.support_fills.entities,
|
support_layer.support_fills.entities,
|
||||||
@ -3107,7 +3109,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
// Filler and its parameters
|
// Filler and its parameters
|
||||||
filler, density,
|
filler, density,
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
(support_layer_id < m_slicing_params.base_raft_layers) ? erSupportMaterial : erSupportMaterialInterface, flow);
|
(support_layer_id < m_slicing_params.base_raft_layers) ? erSupportMaterial : erSupportMaterialInterface, flow, spacing);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3214,21 +3216,22 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
layer_ex.layer->bridging);
|
layer_ex.layer->bridging);
|
||||||
Fill *filler = i == 2 ? filler_intermediate_interface.get() : filler_interface.get();
|
Fill *filler = i == 2 ? filler_intermediate_interface.get() : filler_interface.get();
|
||||||
float density = interface_density;
|
float density = interface_density;
|
||||||
|
coordf_t spacing;
|
||||||
//if first layer and solid first layer : draw concentric with 100% density
|
//if first layer and solid first layer : draw concentric with 100% density
|
||||||
if (support_layer.id() == 0 && this->m_object_config->support_material_solid_first_layer.value) {
|
if (support_layer.id() == 0 && this->m_object_config->support_material_solid_first_layer.value) {
|
||||||
filler = filler_solid.get();
|
filler = filler_solid.get();
|
||||||
density = 1.f;
|
density = 1.f;
|
||||||
interface_flow = m_first_layer_flow;
|
interface_flow = m_first_layer_flow;
|
||||||
filler->angle = 0;
|
filler->angle = 0;
|
||||||
filler->spacing = interface_flow.spacing();
|
spacing = interface_flow.spacing();
|
||||||
} else {
|
} else {
|
||||||
filler->angle = interface_as_base ?
|
filler->angle = interface_as_base ?
|
||||||
// If zero interface layers are configured, use the same angle as for the base layers.
|
// If zero interface layers are configured, use the same angle as for the base layers.
|
||||||
angles[support_layer_id % angles.size()] :
|
angles[support_layer_id % angles.size()] :
|
||||||
// Use interface angle for the interface layers.
|
// Use interface angle for the interface layers.
|
||||||
interface_angle;
|
interface_angle;
|
||||||
filler->spacing = m_support_material_interface_flow.spacing();
|
spacing = m_support_material_interface_flow.spacing();
|
||||||
filler->link_max_length = coord_t(scale_(filler_interface->spacing * link_max_length_factor / density));
|
filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / density));
|
||||||
}
|
}
|
||||||
fill_expolygons_generate_paths(
|
fill_expolygons_generate_paths(
|
||||||
// Destination
|
// Destination
|
||||||
@ -3238,7 +3241,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
// Filler and its parameters
|
// Filler and its parameters
|
||||||
filler, float(density),
|
filler, float(density),
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
erSupportMaterialInterface, interface_flow);
|
erSupportMaterialInterface, interface_flow, spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base support or flange.
|
// Base support or flange.
|
||||||
@ -3253,8 +3256,8 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
float(base_layer.layer->height),
|
float(base_layer.layer->height),
|
||||||
m_support_material_flow.nozzle_diameter,
|
m_support_material_flow.nozzle_diameter,
|
||||||
base_layer.layer->bridging);
|
base_layer.layer->bridging);
|
||||||
filler->spacing = m_support_material_flow.spacing();
|
coordf_t spacing = m_support_material_flow.spacing();
|
||||||
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / support_density));
|
filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / support_density));
|
||||||
float density = float(support_density);
|
float density = float(support_density);
|
||||||
// find centerline of the external loop/extrusions
|
// find centerline of the external loop/extrusions
|
||||||
ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ?
|
ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ?
|
||||||
@ -3271,12 +3274,12 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
filler = filler_interface.get();
|
filler = filler_interface.get();
|
||||||
filler->angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value + 90.));
|
filler->angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value + 90.));
|
||||||
density = 0.5f;
|
density = 0.5f;
|
||||||
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density));
|
filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / density));
|
||||||
}
|
}
|
||||||
// use the proper spacing for first layer as we don't need to align
|
// use the proper spacing for first layer as we don't need to align
|
||||||
// its pattern to the other layers
|
// its pattern to the other layers
|
||||||
flow = m_first_layer_flow;
|
flow = m_first_layer_flow;
|
||||||
filler->spacing = flow.spacing();
|
spacing = flow.spacing();
|
||||||
} else if (with_sheath) {
|
} else if (with_sheath) {
|
||||||
// Draw a perimeter all around the support infill. This makes the support stable, but difficult to remove.
|
// Draw a perimeter all around the support infill. This makes the support stable, but difficult to remove.
|
||||||
// TODO: use brim ordering algorithm
|
// TODO: use brim ordering algorithm
|
||||||
@ -3296,7 +3299,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
// Filler and its parameters
|
// Filler and its parameters
|
||||||
filler, density,
|
filler, density,
|
||||||
// Extrusion parameters
|
// Extrusion parameters
|
||||||
erSupportMaterial, flow);
|
erSupportMaterial, flow, spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
layer_cache.overlaps.reserve(4);
|
layer_cache.overlaps.reserve(4);
|
||||||
|
@ -56,7 +56,6 @@ class Surface
|
|||||||
public:
|
public:
|
||||||
SurfaceType surface_type;
|
SurfaceType surface_type;
|
||||||
ExPolygon expolygon;
|
ExPolygon expolygon;
|
||||||
ExPolygons notOverlaps;
|
|
||||||
double thickness; // in mm
|
double thickness; // in mm
|
||||||
unsigned short thickness_layers; // in layers
|
unsigned short thickness_layers; // in layers
|
||||||
double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined)
|
double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined)
|
||||||
|
@ -9,9 +9,11 @@
|
|||||||
#include "../../libslic3r/Flow.hpp"
|
#include "../../libslic3r/Flow.hpp"
|
||||||
#include "../../libslic3r/ClipperUtils.hpp"
|
#include "../../libslic3r/ClipperUtils.hpp"
|
||||||
#include "../../libslic3r/SVG.hpp"
|
#include "../../libslic3r/SVG.hpp"
|
||||||
|
#include "../test_data.hpp" // get access to init_print, etc
|
||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace Slic3r::Geometry;
|
using namespace Slic3r::Geometry;
|
||||||
|
using namespace Slic3r::Test;
|
||||||
|
|
||||||
bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_spacing, double angle = 0, double density = 1.0);
|
bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_spacing, double angle = 0, double density = 1.0);
|
||||||
|
|
||||||
@ -32,10 +34,11 @@ Polylines test(const ExPolygon& poly, Fill &filler, const FillParams ¶ms){
|
|||||||
TEST_CASE("Fill: Pattern Path Length") {
|
TEST_CASE("Fill: Pattern Path Length") {
|
||||||
Fill* filler {Slic3r::Fill::new_from_type("rectilinear")};
|
Fill* filler {Slic3r::Fill::new_from_type("rectilinear")};
|
||||||
filler->angle = -(PI) / 2.0;
|
filler->angle = -(PI) / 2.0;
|
||||||
filler->spacing = 5;
|
|
||||||
FillParams params{};
|
FillParams params{};
|
||||||
params.dont_adjust = true;
|
params.dont_adjust = true;
|
||||||
params.density = filler->spacing / 50.0;
|
params.density = 0.1; // 5/50
|
||||||
|
filler->set_bounding_box(BoundingBox(Point(0, 0), Point::new_scale(Point(100, 100))));
|
||||||
|
filler->init_spacing(5, params);
|
||||||
//params.endpoints_overlap = false;
|
//params.endpoints_overlap = false;
|
||||||
|
|
||||||
|
|
||||||
@ -85,7 +88,7 @@ TEST_CASE("Fill: Pattern Path Length") {
|
|||||||
for (double angle : {-(PI/2.0), -(PI/4.0), -(PI), PI/2.0, PI}) {
|
for (double angle : {-(PI/2.0), -(PI/4.0), -(PI), PI/2.0, PI}) {
|
||||||
for (double spacing : {25.0, 5.0, 7.5, 8.5}) {
|
for (double spacing : {25.0, 5.0, 7.5, 8.5}) {
|
||||||
FillParams params_local = params;
|
FillParams params_local = params;
|
||||||
params_local.density = filler->spacing / spacing;
|
params_local.density = filler->get_spacing() / spacing;
|
||||||
filler->angle = angle;
|
filler->angle = angle;
|
||||||
Slic3r::ExPolygon e{};
|
Slic3r::ExPolygon e{};
|
||||||
e.contour = Slic3r::Polygon(test_square);
|
e.contour = Slic3r::Polygon(test_square);
|
||||||
@ -110,12 +113,13 @@ TEST_CASE("Fill: Pattern Path Length") {
|
|||||||
}
|
}
|
||||||
SECTION("Regression: Missing infill segments in some rare circumstances") {
|
SECTION("Regression: Missing infill segments in some rare circumstances") {
|
||||||
FillParams params_local = params;
|
FillParams params_local = params;
|
||||||
|
params_local.density = 1;
|
||||||
|
params_local.dont_adjust = false;
|
||||||
Fill* filler_local = { Slic3r::Fill::new_from_type("rectilinear") };
|
Fill* filler_local = { Slic3r::Fill::new_from_type("rectilinear") };
|
||||||
filler_local->angle = (PI/4.0);
|
filler_local->angle = (PI/4.0);
|
||||||
params_local.dont_adjust = false;
|
filler_local->set_bounding_box(BoundingBox(Point(0, 0), Point(2512749, 2512749)));
|
||||||
filler_local->spacing = 0.654498;
|
filler_local->init_spacing(0.654498, params_local);
|
||||||
//filler_local->endpoints_overlap = unscale(359974);
|
//filler_local->endpoints_overlap = unscale(359974);
|
||||||
params_local.density = 1;
|
|
||||||
filler_local->layer_id = 66;
|
filler_local->layer_id = 66;
|
||||||
filler_local->z = 20.15;
|
filler_local->z = 20.15;
|
||||||
|
|
||||||
@ -142,8 +146,8 @@ TEST_CASE("Fill: Pattern Path Length") {
|
|||||||
Surface surface {(stPosTop|stDensSolid), expolygon};
|
Surface surface {(stPosTop|stDensSolid), expolygon};
|
||||||
Flow flow {0.69f, 0.4f, 0.50f};
|
Flow flow {0.69f, 0.4f, 0.50f};
|
||||||
|
|
||||||
filler->spacing = flow.spacing();
|
|
||||||
params.density = 1.0;
|
params.density = 1.0;
|
||||||
|
filler->init_spacing(flow.spacing(), params);
|
||||||
|
|
||||||
for (auto angle : { 0.0, 45.0}) {
|
for (auto angle : { 0.0, 45.0}) {
|
||||||
surface.expolygon.rotate(angle, Point{0,0});
|
surface.expolygon.rotate(angle, Point{0,0});
|
||||||
@ -204,6 +208,219 @@ TEST_CASE("Fill: Pattern Path Length") {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ExtrusionGetVolume : public ExtrusionVisitor {
|
||||||
|
double volume = 0;
|
||||||
|
public:
|
||||||
|
ExtrusionGetVolume() {}
|
||||||
|
void use(ExtrusionPath &path) override {
|
||||||
|
volume += unscaled(path.length()) * path.mm3_per_mm; }
|
||||||
|
void use(ExtrusionPath3D &path3D) override { volume += unscaled(path3D.length()) * path3D.mm3_per_mm; }
|
||||||
|
void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath path : multipath.paths) path.visit(*this); }
|
||||||
|
void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath path : multipath.paths) path.visit(*this); }
|
||||||
|
void use(ExtrusionLoop &loop) override { for (ExtrusionPath path : loop.paths) path.visit(*this); }
|
||||||
|
void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities) entity->visit(*this); }
|
||||||
|
double get(ExtrusionEntityCollection &coll) {
|
||||||
|
for (ExtrusionEntity *entity : coll.entities) entity->visit(*this);
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "../../libslic3r/GCodeReader.hpp"
|
||||||
|
TEST_CASE("Fill: extrude gcode and check it")
|
||||||
|
{
|
||||||
|
|
||||||
|
SECTION("simple square") {
|
||||||
|
Model model{};
|
||||||
|
TriangleMesh sample_mesh = make_cube(5, 5, 0.2);
|
||||||
|
double volume = (5 * 5 * 0.2);
|
||||||
|
sample_mesh.repair();
|
||||||
|
|
||||||
|
DynamicPrintConfig *config = Slic3r::DynamicPrintConfig::new_from_defaults();
|
||||||
|
config->set_key_value("perimeters", new ConfigOptionInt(1));
|
||||||
|
config->set_key_value("top_solid_layers", new ConfigOptionInt(1));
|
||||||
|
config->set_key_value("bottom_solid_layers", new ConfigOptionInt(1));
|
||||||
|
|
||||||
|
config->set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true));
|
||||||
|
config->set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.1, true));
|
||||||
|
|
||||||
|
config->set_key_value("skirts", new ConfigOptionInt(0));
|
||||||
|
|
||||||
|
config->set_key_value("layer_height", new ConfigOptionFloat(0.2)); // get a known number of layers
|
||||||
|
config->set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, false));
|
||||||
|
|
||||||
|
config->set_key_value("extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("external_perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("solid_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("top_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
auto event_counter{ 0U };
|
||||||
|
std::string stage;
|
||||||
|
Print print{};
|
||||||
|
Slic3r::Test::init_print(print, { sample_mesh }, model, config);
|
||||||
|
print.process();
|
||||||
|
|
||||||
|
std::string gcode_filepath{ "" };
|
||||||
|
Slic3r::Test::gcode(gcode_filepath, print);
|
||||||
|
//std::cout << "gcode generation done\n";
|
||||||
|
std::string gcode_from_file = read_to_string(gcode_filepath);
|
||||||
|
|
||||||
|
//string[] lineArray = gcode_from_file
|
||||||
|
GCodeReader parser;
|
||||||
|
double volume_extruded = 0;
|
||||||
|
int idx = 0;
|
||||||
|
double volume_perimeter_extruded = 0;
|
||||||
|
double volume_infill_extruded = 0;
|
||||||
|
// add remaining time lines where needed
|
||||||
|
parser.parse_buffer(gcode_from_file,
|
||||||
|
[&](GCodeReader& reader, const GCodeReader::GCodeLine& line)
|
||||||
|
{
|
||||||
|
if (line.cmd_is("G1"))
|
||||||
|
{
|
||||||
|
if (line.dist_E(reader) > 0 && line.dist_XY(reader) > 0) {
|
||||||
|
//std::cout << "add " << line.dist_E(reader)<<" now "<< volume_extruded<<"=>";
|
||||||
|
volume_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.);
|
||||||
|
//std::cout << volume_extruded << "\n";
|
||||||
|
if (idx<4)volume_perimeter_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.);
|
||||||
|
else volume_infill_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
double perimeterRoundGapRemove = unscaled(print.objects()[0]->layers()[0]->slices.expolygons[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2));
|
||||||
|
double perimeterRoundGapAdd = unscaled(print.objects()[0]->layers()[0]->slices.expolygons[0].contour.length()) * 0.1*0.1 * ((PI / 2));
|
||||||
|
//for (Line &l : print.objects()[0]->layers()[0]->slices.expolygons[0].contour.lines()) {
|
||||||
|
|
||||||
|
//}
|
||||||
|
//std::cout << "flow mm3permm: " << Flow{ 0.5f,0.2f,0.4f,false }.mm3_per_mm() << "\n";
|
||||||
|
//std::cout << "perimeter : " << unscaled(print.objects()[0]->layers()[0]->slices.expolygons[0].contour.length()) << " != " << (PI * 10) << "\n";
|
||||||
|
|
||||||
|
//std::cout << "created a mesh of volume " << volume << " and i have extruded " << volume_extruded << " mm3.\n";
|
||||||
|
//std::cout << "Note that if we remove the bits of the external extrusion, it's only a volume of " << (volume - perimeterRoundGapRemove) << " that needs to be filled\n";
|
||||||
|
//std::cout << "Note that if we add the bits of the external extrusion, it's a volume of " << (volume + perimeterRoundGapAdd) << " that needs to be filled\n";
|
||||||
|
|
||||||
|
double volumeExtrPerimeter = ExtrusionGetVolume{}.get(print.objects()[0]->layers()[0]->regions()[0]->perimeters);
|
||||||
|
double volumeExtrInfill = ExtrusionGetVolume{}.get(print.objects()[0]->layers()[0]->regions()[0]->fills);
|
||||||
|
|
||||||
|
double volumeInfill = 0;
|
||||||
|
for (const ExPolygon & p : print.objects()[0]->layers()[0]->regions()[0]->fill_no_overlap_expolygons) {
|
||||||
|
volumeInfill += unscaled(unscaled(p.area()));
|
||||||
|
}
|
||||||
|
volumeInfill *= 0.2;/*
|
||||||
|
std::cout << "volumeRealr=" << (volume_perimeter_extruded + volume_infill_extruded) << " volumeRealPerimeter= " << volume_perimeter_extruded << " and volumeRealInfill=" << volume_infill_extruded << " mm3." << "\n";
|
||||||
|
std::cout << "volumeExtr=" << (volumeExtrPerimeter + volumeExtrInfill) << " volumeExtrPerimeter= " << volumeExtrPerimeter << " and volumeExtrInfill=" << volumeExtrInfill << " mm3." << "\n";
|
||||||
|
std::cout << "volumePerimeter= " << (volume - volumeInfill) << " volumePerimeter(wo/bits)= " << (volume - volumeInfill- perimeterRoundGapRemove) << " and volumeInfill=" << volumeInfill << " mm3." << "\n";*/
|
||||||
|
|
||||||
|
//Flow fl{0.5f, 0.2f, 0.4f, false};
|
||||||
|
|
||||||
|
//{
|
||||||
|
// std::stringstream stri;
|
||||||
|
// stri << "extrusion_width_learning" << ".svg";
|
||||||
|
// SVG svg(stri.str());
|
||||||
|
// //svg.draw(bounds);
|
||||||
|
// svg.draw(print.objects()[0]->layers()[0]->slices.expolygons[0].contour, "green");
|
||||||
|
// svg.draw(print.objects()[0]->layers()[0]->regions()[0]->fill_no_overlap_expolygons, "black", scale_(0.01));
|
||||||
|
// svg.draw(print.objects()[0]->layers()[0]->regions()[0]->perimeters.as_polylines(), "orange", fl.scaled_width());
|
||||||
|
// svg.draw(print.objects()[0]->layers()[0]->regions()[0]->perimeters.as_polylines(), "red", fl.scaled_spacing());
|
||||||
|
// svg.draw(print.objects()[0]->layers()[0]->regions()[0]->fills.as_polylines(), "cyan", fl.scaled_width());
|
||||||
|
// svg.draw(print.objects()[0]->layers()[0]->regions()[0]->fills.as_polylines(), "blue", fl.scaled_spacing());
|
||||||
|
// svg.Close();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//std::cout << gcode_from_file;
|
||||||
|
REQUIRE(abs(volumeInfill - volumeExtrInfill) < EPSILON);
|
||||||
|
REQUIRE(abs(volumeInfill - volume_infill_extruded) < 0.01);
|
||||||
|
REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volumeExtrPerimeter) < 0.01);
|
||||||
|
REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volume_perimeter_extruded) < 0.1); //there are a bit less for seam mitigation
|
||||||
|
clean_file(gcode_filepath, "gcode");
|
||||||
|
|
||||||
|
}
|
||||||
|
SECTION("simple disk") {
|
||||||
|
Model model{};
|
||||||
|
TriangleMesh sample_mesh = make_cylinder(5, 0.2);
|
||||||
|
double volume = (PI * 25 * 0.2);
|
||||||
|
sample_mesh.repair();
|
||||||
|
|
||||||
|
DynamicPrintConfig *config = Slic3r::DynamicPrintConfig::new_from_defaults();
|
||||||
|
config->set_key_value("perimeters", new ConfigOptionInt(1));
|
||||||
|
config->set_key_value("top_solid_layers", new ConfigOptionInt(1));
|
||||||
|
config->set_key_value("bottom_solid_layers", new ConfigOptionInt(1));
|
||||||
|
|
||||||
|
config->set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true));
|
||||||
|
config->set_key_value("infill_overlap", new ConfigOptionFloatOrPercent(0.1, true));
|
||||||
|
|
||||||
|
config->set_key_value("skirts", new ConfigOptionInt(0));
|
||||||
|
|
||||||
|
config->set_key_value("layer_height", new ConfigOptionFloat(0.2)); // get a known number of layers
|
||||||
|
config->set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, false));
|
||||||
|
|
||||||
|
config->set_key_value("extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("external_perimeter_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("solid_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("top_infill_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
auto event_counter{ 0U };
|
||||||
|
std::string stage;
|
||||||
|
Print print{};
|
||||||
|
Slic3r::Test::init_print(print, { sample_mesh }, model, config);
|
||||||
|
print.process();
|
||||||
|
|
||||||
|
std::string gcode_filepath{ "" };
|
||||||
|
Slic3r::Test::gcode(gcode_filepath, print);
|
||||||
|
//std::cout << "gcode generation done\n";
|
||||||
|
std::string gcode_from_file = read_to_string(gcode_filepath);
|
||||||
|
|
||||||
|
//string[] lineArray = gcode_from_file
|
||||||
|
GCodeReader parser;
|
||||||
|
double volume_extruded = 0;
|
||||||
|
int idx = 0;
|
||||||
|
double volume_perimeter_extruded = 0;
|
||||||
|
double volume_infill_extruded = 0;
|
||||||
|
// add remaining time lines where needed
|
||||||
|
parser.parse_buffer(gcode_from_file,
|
||||||
|
[&](GCodeReader& reader, const GCodeReader::GCodeLine& line)
|
||||||
|
{
|
||||||
|
if (line.cmd_is("G1"))
|
||||||
|
{
|
||||||
|
if (line.dist_E(reader) > 0 && line.dist_XY(reader) > 0) {
|
||||||
|
//std::cout << "add " << line.dist_E(reader)<<" now "<< volume_extruded<<"=>";
|
||||||
|
volume_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.);
|
||||||
|
//std::cout << volume_extruded << "\n";
|
||||||
|
if (idx<36)volume_perimeter_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.);
|
||||||
|
else volume_infill_extruded += line.dist_E(reader)*(PI*1.75*1.75 / 4.);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
double perimeterRoundGapRemove = unscaled(print.objects()[0]->layers()[0]->slices.expolygons[0].contour.length()) * 0.1*0.1 * (2 - (PI / 2));
|
||||||
|
double perimeterRoundGapAdd = unscaled(print.objects()[0]->layers()[0]->slices.expolygons[0].contour.length()) * 0.1*0.1 * ((PI / 2));
|
||||||
|
|
||||||
|
double volumeExtrPerimeter = ExtrusionGetVolume{}.get(print.objects()[0]->layers()[0]->regions()[0]->perimeters);
|
||||||
|
double volumeExtrInfill = ExtrusionGetVolume{}.get(print.objects()[0]->layers()[0]->regions()[0]->fills);
|
||||||
|
|
||||||
|
double volumeInfill = 0;
|
||||||
|
for (const ExPolygon & p : print.objects()[0]->layers()[0]->regions()[0]->fill_no_overlap_expolygons) {
|
||||||
|
volumeInfill += unscaled(unscaled(p.area()));
|
||||||
|
}
|
||||||
|
volumeInfill *= 0.2;
|
||||||
|
std::cout << "volumeRealr=" << (volume_perimeter_extruded + volume_infill_extruded) << " volumeRealPerimeter= " << volume_perimeter_extruded << " and volumeRealInfill=" << volume_infill_extruded << " mm3." << "\n";
|
||||||
|
std::cout << "volumeExtr=" << (volumeExtrPerimeter + volumeExtrInfill) << " volumeExtrPerimeter= " << volumeExtrPerimeter << " and volumeExtrInfill=" << volumeExtrInfill << " mm3." << "\n";
|
||||||
|
std::cout << "volumePerimeter= " << (volume - volumeInfill) << " volumePerimeter(wo/bits)= " << (volume - volumeInfill - perimeterRoundGapRemove) << " and volumeInfill=" << volumeInfill << " mm3." << "\n";
|
||||||
|
|
||||||
|
REQUIRE(abs(volumeInfill - volumeExtrInfill) < EPSILON);
|
||||||
|
REQUIRE(abs(volumeInfill - volume_infill_extruded) < 0.01);
|
||||||
|
REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volumeExtrPerimeter) < EPSILON);
|
||||||
|
REQUIRE(abs((volume - volumeInfill - perimeterRoundGapRemove) - volume_perimeter_extruded) < 0.1); //there are a bit less for seam mitigation
|
||||||
|
clean_file(gcode_filepath, "gcode");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -458,8 +675,8 @@ bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_width,
|
|||||||
//note: here we do flow.width = flow_width , flow.gheight = 0.4, flow.nozzle_size = flow_width;
|
//note: here we do flow.width = flow_width , flow.gheight = 0.4, flow.nozzle_size = flow_width;
|
||||||
Flow flow(flow_width, 0.4, flow_width);
|
Flow flow(flow_width, 0.4, flow_width);
|
||||||
|
|
||||||
filler->spacing = flow.spacing();
|
|
||||||
params.density = density;
|
params.density = density;
|
||||||
|
filler->init_spacing(flow.spacing(), params);
|
||||||
|
|
||||||
Polylines paths {filler->fill_surface(&surface, params)};
|
Polylines paths {filler->fill_surface(&surface, params)};
|
||||||
|
|
||||||
@ -469,7 +686,7 @@ bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_width,
|
|||||||
|
|
||||||
// figure out what is actually going on here re: data types
|
// figure out what is actually going on here re: data types
|
||||||
std::for_each(paths.begin(), paths.end(), [filler, &grown_paths] (const Slic3r::Polyline& p) {
|
std::for_each(paths.begin(), paths.end(), [filler, &grown_paths] (const Slic3r::Polyline& p) {
|
||||||
polygons_append(grown_paths, offset(p, scale_(filler->spacing / 2.0)));
|
polygons_append(grown_paths, offset(p, scale_(filler->get_spacing() / 2.0)));
|
||||||
});
|
});
|
||||||
|
|
||||||
ExPolygons uncovered = diff_ex(expolygon, grown_paths, true);
|
ExPolygons uncovered = diff_ex(expolygon, grown_paths, true);
|
||||||
|
@ -88,7 +88,8 @@ SCENARIO("Print: Changing number of solid surfaces does not cause all surfaces t
|
|||||||
config->set_key_value("top_solid_layers", new ConfigOptionInt(2));
|
config->set_key_value("top_solid_layers", new ConfigOptionInt(2));
|
||||||
config->set_key_value("bottom_solid_layers", new ConfigOptionInt(1));
|
config->set_key_value("bottom_solid_layers", new ConfigOptionInt(1));
|
||||||
config->set_key_value("layer_height", new ConfigOptionFloat(0.5)); // get a known number of layers
|
config->set_key_value("layer_height", new ConfigOptionFloat(0.5)); // get a known number of layers
|
||||||
config->set_key_value("first_layer_height", new ConfigOptionFloat(0.5));
|
config->set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
|
config->set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true));
|
||||||
Slic3r::Model model;
|
Slic3r::Model model;
|
||||||
auto event_counter {0U};
|
auto event_counter {0U};
|
||||||
std::string stage;
|
std::string stage;
|
||||||
|
@ -301,11 +301,11 @@ void init_print(Print& print, std::initializer_list<TriangleMesh> meshes, Slic3r
|
|||||||
DynamicPrintConfig* config {Slic3r::DynamicPrintConfig::new_from_defaults()};
|
DynamicPrintConfig* config {Slic3r::DynamicPrintConfig::new_from_defaults()};
|
||||||
config->apply(*_config);
|
config->apply(*_config);
|
||||||
|
|
||||||
const std::string v {std::getenv("SLIC3R_TESTS_GCODE")};
|
//const std::string v {std::getenv("SLIC3R_TESTS_GCODE")};
|
||||||
std::string tests_gcode {(v == "" ? "" : v)};
|
//std::string tests_gcode {(v == "" ? "" : v)};
|
||||||
|
|
||||||
if (tests_gcode != ""s)
|
//if (tests_gcode != ""s)
|
||||||
config->set_key_value("gcode_comments", new ConfigOptionBool(true));
|
//config->set_key_value("gcode_comments", new ConfigOptionBool(true));
|
||||||
|
|
||||||
for (const TriangleMesh& t : meshes) {
|
for (const TriangleMesh& t : meshes) {
|
||||||
ModelObject* object {model.add_object()};
|
ModelObject* object {model.add_object()};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user