Infill for SLAPrint

This commit is contained in:
Alessandro Ranellucci 2016-11-30 09:38:50 +01:00
parent 2dbc5d6e07
commit 3f3f696502
6 changed files with 183 additions and 47 deletions

View File

@ -521,7 +521,6 @@ has 'sender' => (is => 'rw');
has 'timer' => (is => 'rw');
has 'is_printing' => (is => 'rw', default => sub { 0 });
has '_print' => (is => 'rw');
has '_layers' => (is => 'rw');
has '_heights' => (is => 'rw');
has '_layer_num' => (is => 'rw');
has '_timer_cb' => (is => 'rw');
@ -545,8 +544,7 @@ sub BUILD {
$print->slice;
$progress_dialog->Destroy;
}
$self->_layers([ map $print->slices($_), 0..($print->layer_count-1) ]);
$self->_heights($print->heights);
}
@ -639,7 +637,7 @@ sub print_completed {
sub is_projecting {
my ($self) = @_;
return defined $self->screen->layer;
return defined $self->screen->layer_num;
}
sub project_layer {
@ -650,7 +648,7 @@ sub project_layer {
return;
}
$self->screen->project_layer($self->_layers->[$layer_num], $layer_num);
$self->screen->project_layer($layer_num);
}
sub project_next_layer {
@ -719,7 +717,7 @@ sub total_resin {
for my $i (0..($self->_print->layer_count-1)) {
my $lh = $self->_heights->[$i] - ($i == 0 ? 0 : $self->_heights->[$i-1]);
$vol += unscale(unscale($_->area)) * $lh for @{ $self->_print->slices($i) };
$vol += unscale(unscale($_->area)) * $lh for @{ $self->_print->layer_slices($i) };
}
return $vol/1000/1000; # liters
@ -742,7 +740,7 @@ use List::Util qw(min);
use Slic3r::Geometry qw(X Y unscale scale);
use Slic3r::Geometry::Clipper qw(intersection_pl);
__PACKAGE__->mk_accessors(qw(config config2 scaling_factor bed_origin layer print layer_num));
__PACKAGE__->mk_accessors(qw(config config2 scaling_factor bed_origin print layer_num));
sub new {
my ($class, $parent, $config, $config2) = @_;
@ -803,9 +801,8 @@ sub _resize {
}
sub project_layer {
my ($self, $layer, $layer_num) = @_;
my ($self, $layer_num) = @_;
$self->layer($layer);
$self->layer_num($layer_num);
$self->Refresh;
}
@ -873,20 +870,19 @@ sub _repaint {
}
}
return if !defined $self->layer;
# get layers at this height
# draw layers
$dc->SetPen(Wx::Pen->new(wxWHITE, 1, wxSOLID));
my @polygons = sort { $a->contains_point($b->first_point) ? -1 : 1 } map @$_, @{$self->layer};
foreach my $polygon (@polygons) {
if ($polygon->is_counter_clockwise) {
$dc->SetBrush(Wx::Brush->new(wxWHITE, wxSOLID));
} else {
$dc->SetBrush(Wx::Brush->new(wxBLACK, wxSOLID));
}
$dc->DrawPolygon($self->scaled_points_to_pixel($polygon->pp), 0, 0);
return if !$self->print || !defined $self->layer_num;
if ($self->print->layer_solid($self->layer_num)) {
$self->_paint_expolygon($_, $dc) for @{$self->print->layer_slices($self->layer_num)};
} else {
$self->_paint_expolygon($_, $dc) for @{$self->print->layer_solid_infill($self->layer_num)};
$self->_paint_polygon($_, $dc) for map @{$_->grow},
@{$self->print->layer_perimeters($self->layer_num)},
@{$self->print->layer_infill($self->layer_num)};
}
# draw support material
@ -908,6 +904,24 @@ sub _repaint {
}
}
sub _paint_expolygon {
my ($self, $expolygon, $dc) = @_;
my @polygons = sort { $a->contains_point($b->first_point) ? -1 : 1 } @$expolygon;
$self->_paint_polygon($_, $dc) for @polygons;
}
sub _paint_polygon {
my ($self, $polygon, $dc) = @_;
if ($polygon->is_counter_clockwise) {
$dc->SetBrush(Wx::Brush->new(wxWHITE, wxSOLID));
} else {
$dc->SetBrush(Wx::Brush->new(wxBLACK, wxSOLID));
}
$dc->DrawPolygon($self->scaled_points_to_pixel($polygon->pp), 0, 0);
}
# convert a model coordinate into a pixel coordinate
sub unscaled_point_to_pixel {
my ($self, $point) = @_;

View File

@ -155,7 +155,7 @@ offset(const Polygons &polygons, const float delta,
// perform offset
ClipperLib::Paths output = _offset(polygons, delta, scale, joinType, miterLimit);
// convert into ExPolygons
// convert into Polygons
return ClipperPaths_to_Slic3rMultiPoints<Polygons>(output);
}
@ -166,7 +166,7 @@ offset(const Polylines &polylines, const float delta,
// perform offset
ClipperLib::Paths output = _offset(polylines, delta, scale, joinType, miterLimit);
// convert into ExPolygons
// convert into Polygons
return ClipperPaths_to_Slic3rMultiPoints<Polygons>(output);
}

View File

@ -533,8 +533,13 @@ class SLAPrintConfig
: public virtual StaticPrintConfig
{
public:
ConfigOptionFloat fill_angle;
ConfigOptionPercent fill_density;
ConfigOptionEnum<InfillPattern> fill_pattern;
ConfigOptionFloatOrPercent first_layer_height;
ConfigOptionFloatOrPercent infill_extrusion_width;
ConfigOptionFloat layer_height;
ConfigOptionFloatOrPercent perimeter_extrusion_width;
ConfigOptionInt raft_layers;
ConfigOptionFloat raft_offset;
ConfigOptionBool support_material;
@ -546,8 +551,13 @@ class SLAPrintConfig
};
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
OPT_PTR(fill_angle);
OPT_PTR(fill_density);
OPT_PTR(fill_pattern);
OPT_PTR(first_layer_height);
OPT_PTR(infill_extrusion_width);
OPT_PTR(layer_height);
OPT_PTR(perimeter_extrusion_width);
OPT_PTR(raft_layers);
OPT_PTR(raft_offset);
OPT_PTR(support_material);

View File

@ -1,5 +1,9 @@
#include "SLAPrint.hpp"
#include "ClipperUtils.hpp"
#include "ExtrusionEntity.hpp"
#include "Fill/FillBase.hpp"
#include "Geometry.hpp"
#include "Surface.hpp"
#include <iostream>
#include <cstdio>
@ -47,7 +51,73 @@ SLAPrint::slice()
TriangleMeshSlicer(&mesh).slice(slice_z, &slices);
for (size_t i = 0; i < slices.size(); ++i)
this->layers[i].slices = ExPolygonCollection(slices[i]);
this->layers[i].slices.expolygons = slices[i];
}
// generate infill
if (this->config.fill_density < 100) {
const float shell_thickness = this->config.get_abs_value("perimeter_extrusion_width", this->config.layer_height.value);
std::auto_ptr<Fill> fill = std::auto_ptr<Fill>(Fill::new_from_type(this->config.fill_pattern.value));
//fill->bounding_box = this->bb;
fill->spacing = this->config.get_abs_value("infill_extrusion_width", this->config.layer_height.value);
fill->angle = Geometry::deg2rad(this->config.fill_angle.value);
FillParams fill_params;
fill_params.density = this->config.fill_density.value/100;
ExtrusionPath templ(erInternalInfill);
templ.width = fill->spacing;
for (size_t i = 0; i < this->layers.size(); ++i) {
Layer &layer = this->layers[i];
// In order to detect what regions of this layer need to be solid,
// perform an intersection with layers within the requested shell thickness.
Polygons internal = layer.slices;
for (size_t j = 0; j < this->layers.size(); ++j) {
const Layer &other = this->layers[j];
if (abs(other.print_z - layer.print_z) > shell_thickness) continue;
if (j == 0 || j == this->layers.size()-1) {
internal.clear();
break;
} else if (i != j) {
internal = intersection(internal, other.slices);
if (internal.empty()) break;
}
}
// If we have no internal infill, just print the whole layer as a solid slice.
if (internal.empty()) continue;
layer.solid = false;
const Polygons infill = offset(layer.slices, -scale_(shell_thickness));
// Generate solid infill.
layer.solid_infill.append(diff_ex(infill, internal, true));
// Generate internal infill.
{
fill->layer_id = i;
fill->z = layer.print_z;
const ExPolygons internal_ex = intersection_ex(infill, internal);
for (ExPolygons::const_iterator it = internal_ex.begin(); it != internal_ex.end(); ++it) {
Polylines polylines = fill->fill_surface(Surface(stInternal, *it), fill_params);
layer.infill.append(polylines, templ);
}
}
// Generate perimeter(s).
{
const Polygons perimeters = offset(layer.slices, -scale_(shell_thickness)/2);
for (Polygons::const_iterator it = perimeters.begin(); it != perimeters.end(); ++it) {
ExtrusionPath ep(erPerimeter);
ep.polyline = *it;
ep.width = shell_thickness;
layer.perimeters.append(ExtrusionLoop(ep));
}
}
}
}
// generate support material
@ -154,23 +224,31 @@ SLAPrint::write_svg(const std::string &outputfile) const
layer.print_z - (i == 0 ? 0 : this->layers[i-1].print_z)
);
const ExPolygons &slices = layer.slices.expolygons;
for (ExPolygons::const_iterator it = slices.begin(); it != slices.end(); ++it) {
std::string pd;
Polygons pp = *it;
for (Polygons::const_iterator mp = pp.begin(); mp != pp.end(); ++mp) {
std::ostringstream d;
d << "M ";
for (Points::const_iterator p = mp->points.begin(); p != mp->points.end(); ++p) {
d << unscale(p->x) - this->bb.min.x << " ";
d << size.y - (unscale(p->y) - this->bb.min.y) << " "; // mirror Y coordinates as SVG uses downwards Y
}
d << "z";
pd += d.str() + " ";
if (layer.solid) {
const ExPolygons &slices = layer.slices.expolygons;
for (ExPolygons::const_iterator it = slices.begin(); it != slices.end(); ++it) {
std::string pd = this->_SVG_path_d(*it);
fprintf(f,"\t\t<path d=\"%s\" style=\"fill: %s; stroke: %s; stroke-width: %s; fill-type: evenodd\" slic3r:area=\"%0.4f\" />\n",
pd.c_str(), "white", "black", "0", unscale(unscale(it->area()))
);
}
} else {
// Solid infill.
const ExPolygons &solid_infill = layer.solid_infill.expolygons;
for (ExPolygons::const_iterator it = solid_infill.begin(); it != solid_infill.end(); ++it) {
std::string pd = this->_SVG_path_d(*it);
fprintf(f,"\t\t<path d=\"%s\" style=\"fill: %s; stroke: %s; stroke-width: %s; fill-type: evenodd\" slic3r:type=\"infill\" />\n",
pd.c_str(), "white", "black", "0"
);
}
// Generate perimeters.
for (ExtrusionEntitiesPtr::const_iterator it = layer.perimeters.entities.begin();
it != layer.perimeters.entities.end(); ++it) {
//std::string pd = this->_SVG_path_d(it->polygon());
}
fprintf(f,"\t\t<path d=\"%s\" style=\"fill: %s; stroke: %s; stroke-width: %s; fill-type: evenodd\" slic3r:area=\"%0.4f\" />\n",
pd.c_str(), "white", "black", "0", unscale(unscale(it->area()))
);
}
// don't print support material in raft layers
@ -206,4 +284,28 @@ SLAPrint::sm_pillars_radius() const
return radius;
}
std::string
SLAPrint::_SVG_path_d(const Polygon &polygon) const
{
const Sizef3 size = this->bb.size();
std::ostringstream d;
d << "M ";
for (Points::const_iterator p = polygon.points.begin(); p != polygon.points.end(); ++p) {
d << unscale(p->x) - this->bb.min.x << " ";
d << size.y - (unscale(p->y) - this->bb.min.y) << " "; // mirror Y coordinates as SVG uses downwards Y
}
d << "z";
return d.str();
}
std::string
SLAPrint::_SVG_path_d(const ExPolygon &expolygon) const
{
std::string pd;
const Polygons pp = expolygon;
for (Polygons::const_iterator mp = pp.begin(); mp != pp.end(); ++mp)
pd += this->_SVG_path_d(*mp) + " ";
return pd;
}
}

View File

@ -19,9 +19,14 @@ class SLAPrint
class Layer {
public:
ExPolygonCollection slices;
ExtrusionEntityCollection perimeters;
ExtrusionEntityCollection infill;
ExPolygonCollection solid_infill;
float slice_z, print_z;
bool solid;
Layer(float _slice_z, float _print_z) : slice_z(_slice_z), print_z(_print_z) {};
Layer(float _slice_z, float _print_z)
: slice_z(_slice_z), print_z(_print_z), solid(true) {};
};
std::vector<Layer> layers;
@ -41,6 +46,8 @@ class SLAPrint
BoundingBoxf3 bb;
coordf_t sm_pillars_radius() const;
std::string _SVG_path_d(const Polygon &polygon) const;
std::string _SVG_path_d(const ExPolygon &expolygon) const;
};
}

View File

@ -18,16 +18,19 @@
DynamicPrintConfig* config()
%code%{ RETVAL = new DynamicPrintConfig; RETVAL->apply(THIS->config); %};
ExPolygons layer_slices(size_t i)
%code%{ RETVAL = THIS->layers[i].slices; %};
ExPolygons layer_solid_infill(size_t i)
%code%{ RETVAL = THIS->layers[i].solid_infill.expolygons; %};
Ref<ExtrusionEntityCollection> layer_perimeters(size_t i)
%code%{ RETVAL = &THIS->layers[i].perimeters; %};
Ref<ExtrusionEntityCollection> layer_infill(size_t i)
%code%{ RETVAL = &THIS->layers[i].infill; %};
bool layer_solid(size_t i)
%code%{ RETVAL = THIS->layers[i].solid; %};
%{
ExPolygons
SLAPrint::slices(i)
size_t i;
CODE:
RETVAL = THIS->layers[i].slices;
OUTPUT:
RETVAL
std::vector<double>
SLAPrint::heights()
CODE: