Refactored PerimeterGenerator to output out_fill_surfaces as ExPolygons,
not SurfaceCollection. Reworked combineinfill.t, 07_extrusionpath.t, 08_extrusionloop.t to c++. Removed Layer / ExtrusionPath / ExtrusionLoop / ExtrusionEntityCollection from Perl bindings.
This commit is contained in:
parent
237e56c7ce
commit
d041fa6c0c
@ -6,9 +6,4 @@ use warnings;
|
||||
use List::Util qw(min max sum first);
|
||||
use Slic3r::Surface ':types';
|
||||
|
||||
sub layers {
|
||||
my $self = shift;
|
||||
return [ map $self->get_layer($_), 0..($self->layer_count - 1) ];
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -426,12 +426,12 @@ void Layer::make_perimeters()
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceCollection fill_surfaces;
|
||||
ExPolygons fill_expolygons;
|
||||
if (layerms.size() == 1) { // optimization
|
||||
(*layerm)->m_fill_expolygons.clear();
|
||||
(*layerm)->m_fill_surfaces.clear();
|
||||
(*layerm)->make_perimeters((*layerm)->slices(), &fill_surfaces);
|
||||
(*layerm)->m_fill_expolygons = to_expolygons(fill_surfaces.surfaces);
|
||||
(*layerm)->make_perimeters((*layerm)->slices(), fill_expolygons);
|
||||
(*layerm)->m_fill_expolygons = std::move(fill_expolygons);
|
||||
} else {
|
||||
SurfaceCollection new_slices;
|
||||
// Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence.
|
||||
@ -452,12 +452,12 @@ void Layer::make_perimeters()
|
||||
new_slices.append(offset_ex(surfaces_with_extra_perimeters.second, ClipperSafetyOffset), surfaces_with_extra_perimeters.second.front());
|
||||
}
|
||||
// make perimeters
|
||||
layerm_config->make_perimeters(new_slices, &fill_surfaces);
|
||||
layerm_config->make_perimeters(new_slices, fill_expolygons);
|
||||
// assign fill_surfaces to each layer
|
||||
if (! fill_surfaces.empty()) {
|
||||
if (! fill_expolygons.empty()) {
|
||||
// Separate the fill surfaces.
|
||||
for (LayerRegion *l : layerms)
|
||||
l->m_fill_expolygons = intersection_ex(fill_surfaces.surfaces, l->slices().surfaces);
|
||||
l->m_fill_expolygons = intersection_ex(l->slices().surfaces, fill_expolygons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
|
||||
void slices_to_fill_surfaces_clipped();
|
||||
void prepare_fill_surfaces();
|
||||
void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
|
||||
void make_perimeters(const SurfaceCollection &slices, ExPolygons &fill_expolygons);
|
||||
void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered);
|
||||
double infill_area_threshold() const;
|
||||
// Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer.
|
||||
|
@ -59,7 +59,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped()
|
||||
}
|
||||
}
|
||||
|
||||
void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces)
|
||||
void LayerRegion::make_perimeters(const SurfaceCollection &slices, ExPolygons &fill_expolygons)
|
||||
{
|
||||
m_perimeters.clear();
|
||||
m_thin_fills.clear();
|
||||
@ -100,7 +100,7 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||
// output:
|
||||
m_perimeters,
|
||||
m_thin_fills,
|
||||
*fill_surfaces);
|
||||
fill_expolygons);
|
||||
else
|
||||
PerimeterGenerator::process_classic(
|
||||
// input:
|
||||
@ -111,7 +111,7 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||
// output:
|
||||
m_perimeters,
|
||||
m_thin_fills,
|
||||
*fill_surfaces);
|
||||
fill_expolygons);
|
||||
}
|
||||
|
||||
//#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 3.
|
||||
|
@ -611,7 +611,7 @@ void PerimeterGenerator::process_arachne(
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection &out_gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection &out_fill_surfaces)
|
||||
ExPolygons &out_fill_expolygons)
|
||||
{
|
||||
// other perimeters
|
||||
coord_t perimeter_spacing = params.perimeter_flow.scaled_spacing();
|
||||
@ -817,12 +817,11 @@ void PerimeterGenerator::process_arachne(
|
||||
// collapse too narrow infill areas
|
||||
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||
// append infill areas to fill_surfaces
|
||||
out_fill_surfaces.append(
|
||||
append(out_fill_expolygons,
|
||||
offset2_ex(
|
||||
union_ex(pp),
|
||||
float(- min_perimeter_infill_spacing / 2.),
|
||||
float(inset + min_perimeter_infill_spacing / 2.)),
|
||||
stInternal);
|
||||
float(inset + min_perimeter_infill_spacing / 2.)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,7 +838,7 @@ void PerimeterGenerator::process_classic(
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection &out_gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection &out_fill_surfaces)
|
||||
ExPolygons &out_fill_expolygons)
|
||||
{
|
||||
// other perimeters
|
||||
coord_t perimeter_width = params.perimeter_flow.scaled_width();
|
||||
@ -1094,12 +1093,11 @@ void PerimeterGenerator::process_classic(
|
||||
// collapse too narrow infill areas
|
||||
coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||
// append infill areas to fill_surfaces
|
||||
out_fill_surfaces.append(
|
||||
append(out_fill_expolygons,
|
||||
offset2_ex(
|
||||
union_ex(pp),
|
||||
float(- inset - min_perimeter_infill_spacing / 2.),
|
||||
float(min_perimeter_infill_spacing / 2.)),
|
||||
stInternal);
|
||||
float(min_perimeter_infill_spacing / 2.)));
|
||||
} // for each island
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ void process_classic(
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection &out_gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection &out_fill_surfaces);
|
||||
ExPolygons &out_fill_expolygons);
|
||||
|
||||
void process_arachne(
|
||||
// Inputs:
|
||||
@ -92,7 +92,7 @@ void process_arachne(
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection &out_gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection &out_fill_surfaces);
|
||||
ExPolygons &out_fill_expolygons);
|
||||
|
||||
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance);
|
||||
|
||||
|
@ -32,12 +32,13 @@
|
||||
#include "Technologies.hpp"
|
||||
#include "Semver.hpp"
|
||||
|
||||
using coord_t =
|
||||
#if 1
|
||||
// Saves around 32% RAM after slicing step, 6.7% after G-code export (tested on PrusaSlicer 2.2.0 final).
|
||||
using coord_t = int32_t;
|
||||
int32_t;
|
||||
#else
|
||||
//FIXME At least FillRectilinear2 and std::boost Voronoi require coord_t to be 32bit.
|
||||
typedef int64_t coord_t;
|
||||
//FIXME At least FillRectilinear2 and std::boost Voronoi require coord_t to be 32bit.
|
||||
int64_t;
|
||||
#endif
|
||||
|
||||
using coordf_t = double;
|
||||
@ -366,4 +367,4 @@ inline IntegerOnly<I, I> fast_round_up(double a)
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
#endif // _libslic3r_h_
|
||||
|
@ -1,110 +0,0 @@
|
||||
use Test::More;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use local::lib "$FindBin::Bin/../local-lib";
|
||||
}
|
||||
|
||||
use List::Util qw(first);
|
||||
use Slic3r;
|
||||
use Slic3r::Surface ':types';
|
||||
use Slic3r::Test;
|
||||
|
||||
plan tests => 8;
|
||||
|
||||
{
|
||||
my $test = sub {
|
||||
my ($config) = @_;
|
||||
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
|
||||
ok my $gcode = Slic3r::Test::gcode($print), "infill_every_layers does not crash";
|
||||
|
||||
my $tool = undef;
|
||||
my %layers = (); # layer_z => 1
|
||||
my %layer_infill = (); # layer_z => has_infill
|
||||
Slic3r::GCode::Reader->new->parse($gcode, sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd =~ /^T(\d+)/) {
|
||||
$tool = $1;
|
||||
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0 && $tool != $config->support_material_extruder-1) {
|
||||
$layer_infill{$self->Z} //= 0;
|
||||
if ($tool == $config->infill_extruder-1) {
|
||||
$layer_infill{$self->Z} = 1;
|
||||
}
|
||||
}
|
||||
# Previously, all G-code commands had a fixed number of decimal points with means with redundant zeros after decimal points.
|
||||
# We changed this behavior and got rid of these redundant padding zeros, which caused this test to fail
|
||||
# because the position in Z-axis is compared as a string, and previously, G-code contained the following two commands:
|
||||
# "G1 Z5 F5000 ; lift nozzle"
|
||||
# "G1 Z5.000 F7800.000"
|
||||
# That has a different Z-axis position from the view of string comparisons of floating-point numbers.
|
||||
# To correct the computation of the number of printed layers, even in the case of string comparisons of floating-point numbers,
|
||||
# we filtered out the G-code command with the commend 'lift nozzle'.
|
||||
$layers{$args->{Z}} = 1 if $cmd eq 'G1' && $info->{dist_Z} && index($info->{comment}, 'lift nozzle') == -1;
|
||||
});
|
||||
|
||||
my $layers_with_perimeters = scalar(keys %layer_infill);
|
||||
my $layers_with_infill = grep $_ > 0, values %layer_infill;
|
||||
is scalar(keys %layers), $layers_with_perimeters+$config->raft_layers, 'expected number of layers';
|
||||
|
||||
if ($config->raft_layers == 0) {
|
||||
# first infill layer printed directly on print bed is not combined, so we don't consider it.
|
||||
$layers_with_infill--;
|
||||
$layers_with_perimeters--;
|
||||
}
|
||||
|
||||
# we expect that infill is generated for half the number of combined layers
|
||||
# plus for each single layer that was not combined (remainder)
|
||||
is $layers_with_infill,
|
||||
int($layers_with_perimeters/$config->infill_every_layers) + ($layers_with_perimeters % $config->infill_every_layers),
|
||||
'infill is only present in correct number of layers';
|
||||
};
|
||||
|
||||
my $config = Slic3r::Config::new_from_defaults;
|
||||
$config->set('layer_height', 0.2);
|
||||
$config->set('first_layer_height', 0.2);
|
||||
$config->set('nozzle_diameter', [0.5,0.5,0.5,0.5]);
|
||||
$config->set('infill_every_layers', 2);
|
||||
$config->set('perimeter_extruder', 1);
|
||||
$config->set('infill_extruder', 2);
|
||||
$config->set('wipe_into_infill', 0);
|
||||
$config->set('support_material_extruder', 3);
|
||||
$config->set('support_material_interface_extruder', 3);
|
||||
$config->set('top_solid_layers', 0);
|
||||
$config->set('bottom_solid_layers', 0);
|
||||
$test->($config);
|
||||
|
||||
$config->set('skirts', 0); # prevent usage of perimeter_extruder in raft layers
|
||||
$config->set('raft_layers', 5);
|
||||
$test->($config);
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config::new_from_defaults;
|
||||
$config->set('layer_height', 0.2);
|
||||
$config->set('first_layer_height', 0.2);
|
||||
$config->set('nozzle_diameter', [0.5]);
|
||||
$config->set('infill_every_layers', 2);
|
||||
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
|
||||
$print->process;
|
||||
|
||||
ok defined(first { @{$_->get_region(0)->fill_surfaces->filter_by_type(S_TYPE_INTERNALVOID)} > 0 }
|
||||
@{$print->print->get_object(0)->layers}),
|
||||
'infill combination produces internal void surfaces';
|
||||
|
||||
# we disable combination after infill has been generated
|
||||
$config->set('infill_every_layers', 1);
|
||||
$print->apply($print->print->model->clone, $config);
|
||||
$print->process;
|
||||
|
||||
ok !(defined first { @{$_->get_region(0)->fill_surfaces} == 0 }
|
||||
@{$print->print->get_object(0)->layers}),
|
||||
'infill combination is idempotent';
|
||||
}
|
||||
|
||||
__END__
|
@ -35,7 +35,254 @@ static Slic3r::ExtrusionPaths random_paths(size_t count = 10, size_t length = 20
|
||||
return p;
|
||||
}
|
||||
|
||||
SCENARIO("ExtrusionEntityCollection: Polygon flattening", "[ExtrusionEntity]") {
|
||||
SCENARIO("ExtrusionPath", "[ExtrusionEntity]") {
|
||||
GIVEN("Simple path") {
|
||||
Slic3r::ExtrusionPath path{ erExternalPerimeter };
|
||||
path.polyline = { { 100, 100 }, { 200, 100 }, { 200, 200 } };
|
||||
path.mm3_per_mm = 1.;
|
||||
THEN("first point") {
|
||||
REQUIRE(path.first_point() == path.polyline.front());
|
||||
}
|
||||
THEN("cloned") {
|
||||
auto cloned = std::unique_ptr<ExtrusionEntity>(path.clone());
|
||||
REQUIRE(cloned->role() == path.role());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ExtrusionPath new_extrusion_path(const Polyline &polyline, ExtrusionRole role, double mm3_per_mm)
|
||||
{
|
||||
ExtrusionPath path(role);
|
||||
path.polyline = polyline;
|
||||
path.mm3_per_mm = 1.;
|
||||
return path;
|
||||
}
|
||||
|
||||
SCENARIO("ExtrusionLoop", "[ExtrusionEntity]")
|
||||
{
|
||||
GIVEN("Square") {
|
||||
Polygon square { { 100, 100 }, { 200, 100 }, { 200, 200 }, { 100, 200 } };
|
||||
|
||||
ExtrusionLoop loop;
|
||||
loop.paths.emplace_back(new_extrusion_path(square.split_at_first_point(), erExternalPerimeter, 1.));
|
||||
THEN("polygon area") {
|
||||
REQUIRE(loop.polygon().area() == Approx(square.area()));
|
||||
}
|
||||
THEN("loop length") {
|
||||
REQUIRE(loop.length() == Approx(square.length()));
|
||||
}
|
||||
|
||||
WHEN("cloned") {
|
||||
auto loop2 = std::unique_ptr<ExtrusionLoop>(dynamic_cast<ExtrusionLoop*>(loop.clone()));
|
||||
THEN("cloning worked") {
|
||||
REQUIRE(loop2 != nullptr);
|
||||
}
|
||||
THEN("loop contains one path") {
|
||||
REQUIRE(loop2->paths.size() == 1);
|
||||
}
|
||||
THEN("cloned role") {
|
||||
REQUIRE(loop2->paths.front().role() == erExternalPerimeter);
|
||||
}
|
||||
}
|
||||
WHEN("cloned and split") {
|
||||
auto loop2 = std::unique_ptr<ExtrusionLoop>(dynamic_cast<ExtrusionLoop*>(loop.clone()));
|
||||
loop2->split_at_vertex(square.points[2]);
|
||||
THEN("splitting a single-path loop results in a single path") {
|
||||
REQUIRE(loop2->paths.size() == 1);
|
||||
}
|
||||
THEN("path has correct number of points") {
|
||||
REQUIRE(loop2->paths.front().size() == 5);
|
||||
}
|
||||
THEN("expected point order") {
|
||||
REQUIRE(loop2->paths.front().polyline[0] == square.points[2]);
|
||||
REQUIRE(loop2->paths.front().polyline[1] == square.points[3]);
|
||||
REQUIRE(loop2->paths.front().polyline[2] == square.points[0]);
|
||||
REQUIRE(loop2->paths.front().polyline[3] == square.points[1]);
|
||||
REQUIRE(loop2->paths.front().polyline[4] == square.points[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("Loop with two pieces") {
|
||||
Polyline polyline1 { { 100, 100 }, { 200, 100 }, { 200, 200 } };
|
||||
Polyline polyline2 { { 200, 200 }, { 100, 200 }, { 100, 100 } };
|
||||
ExtrusionLoop loop;
|
||||
loop.paths.emplace_back(new_extrusion_path(polyline1, erExternalPerimeter, 1.));
|
||||
loop.paths.emplace_back(new_extrusion_path(polyline2, erOverhangPerimeter, 1.));
|
||||
|
||||
double tot_len = polyline1.length() + polyline2.length();
|
||||
THEN("length") {
|
||||
REQUIRE(loop.length() == Approx(tot_len));
|
||||
}
|
||||
|
||||
WHEN("splitting at intermediate point") {
|
||||
auto loop2 = std::unique_ptr<ExtrusionLoop>(dynamic_cast<ExtrusionLoop*>(loop.clone()));
|
||||
loop2->split_at_vertex(polyline1.points[1]);
|
||||
THEN("length after splitting is unchanged") {
|
||||
REQUIRE(loop2->length() == Approx(tot_len));
|
||||
}
|
||||
THEN("loop contains three paths after splitting") {
|
||||
REQUIRE(loop2->paths.size() == 3);
|
||||
}
|
||||
THEN("expected starting point") {
|
||||
REQUIRE(loop2->paths.front().polyline.front() == polyline1.points[1]);
|
||||
}
|
||||
THEN("expected ending point") {
|
||||
REQUIRE(loop2->paths.back().polyline.back() == polyline1.points[1]);
|
||||
}
|
||||
THEN("paths have common point") {
|
||||
REQUIRE(loop2->paths.front().polyline.back() == loop2->paths[1].polyline.front());
|
||||
REQUIRE(loop2->paths[1].polyline.back() == loop2->paths[2].polyline.front());
|
||||
}
|
||||
THEN("expected order after splitting") {
|
||||
REQUIRE(loop2->paths.front().role() == erExternalPerimeter);
|
||||
REQUIRE(loop2->paths[1].role() == erOverhangPerimeter);
|
||||
REQUIRE(loop2->paths[2].role() == erExternalPerimeter);
|
||||
}
|
||||
THEN("path has correct number of points") {
|
||||
REQUIRE(loop2->paths.front().polyline.size() == 2);
|
||||
REQUIRE(loop2->paths[1].polyline.size() == 3);
|
||||
REQUIRE(loop2->paths[2].polyline.size() == 2);
|
||||
}
|
||||
THEN("clipped path has expected length") {
|
||||
double l = loop2->length();
|
||||
ExtrusionPaths paths;
|
||||
loop2->clip_end(3, &paths);
|
||||
double l2 = 0;
|
||||
for (const ExtrusionPath &p : paths)
|
||||
l2 += p.length();
|
||||
REQUIRE(l2 == Approx(l - 3.));
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("splitting at endpoint") {
|
||||
auto loop2 = std::unique_ptr<ExtrusionLoop>(dynamic_cast<ExtrusionLoop*>(loop.clone()));
|
||||
loop2->split_at_vertex(polyline2.points.front());
|
||||
THEN("length after splitting is unchanged") {
|
||||
REQUIRE(loop2->length() == Approx(tot_len));
|
||||
}
|
||||
THEN("loop contains two paths after splitting") {
|
||||
REQUIRE(loop2->paths.size() == 2);
|
||||
}
|
||||
THEN("expected starting point") {
|
||||
REQUIRE(loop2->paths.front().polyline.front() == polyline2.points.front());
|
||||
}
|
||||
THEN("expected ending point") {
|
||||
REQUIRE(loop2->paths.back().polyline.back() == polyline2.points.front());
|
||||
}
|
||||
THEN("paths have common point") {
|
||||
REQUIRE(loop2->paths.front().polyline.back() == loop2->paths[1].polyline.front());
|
||||
REQUIRE(loop2->paths[1].polyline.back() == loop2->paths.front().polyline.front());
|
||||
}
|
||||
THEN("expected order after splitting") {
|
||||
REQUIRE(loop2->paths.front().role() == erOverhangPerimeter);
|
||||
REQUIRE(loop2->paths[1].role() == erExternalPerimeter);
|
||||
}
|
||||
THEN("path has correct number of points") {
|
||||
REQUIRE(loop2->paths.front().polyline.size() == 3);
|
||||
REQUIRE(loop2->paths[1].polyline.size() == 3);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("splitting at an edge") {
|
||||
Point point(250, 150);
|
||||
auto loop2 = std::unique_ptr<ExtrusionLoop>(dynamic_cast<ExtrusionLoop*>(loop.clone()));
|
||||
loop2->split_at(point, false, 0);
|
||||
THEN("length after splitting is unchanged") {
|
||||
REQUIRE(loop2->length() == Approx(tot_len));
|
||||
}
|
||||
Point expected_start_point(200, 150);
|
||||
THEN("expected starting point") {
|
||||
REQUIRE(loop2->paths.front().polyline.front() == expected_start_point);
|
||||
}
|
||||
THEN("expected ending point") {
|
||||
REQUIRE(loop2->paths.back().polyline.back() == expected_start_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("Loop with four pieces") {
|
||||
Polyline polyline1 { { 59312736, 4821067 }, { 64321068, 4821067 }, { 64321068, 4821067 }, { 64321068, 9321068 }, { 59312736, 9321068 } };
|
||||
Polyline polyline2 { { 59312736, 9321068 }, { 9829401, 9321068 } };
|
||||
Polyline polyline3 { { 9829401, 9321068 }, { 4821067, 9321068 }, { 4821067, 4821067 }, { 9829401, 4821067 } };
|
||||
Polyline polyline4 { { 9829401, 4821067 }, { 59312736,4821067 } };
|
||||
ExtrusionLoop loop;
|
||||
loop.paths.emplace_back(new_extrusion_path(polyline1, erExternalPerimeter, 1.));
|
||||
loop.paths.emplace_back(new_extrusion_path(polyline2, erOverhangPerimeter, 1.));
|
||||
loop.paths.emplace_back(new_extrusion_path(polyline3, erExternalPerimeter, 1.));
|
||||
loop.paths.emplace_back(new_extrusion_path(polyline4, erOverhangPerimeter, 1.));
|
||||
double len = loop.length();
|
||||
WHEN("splitting at vertex") {
|
||||
Point point(4821067, 9321068);
|
||||
if (! loop.split_at_vertex(point))
|
||||
loop.split_at(point, false, 0);
|
||||
THEN("total length is preserved after splitting") {
|
||||
REQUIRE(loop.length() == Approx(len));
|
||||
}
|
||||
THEN("order is correctly preserved after splitting") {
|
||||
REQUIRE(loop.paths.front().role() == erExternalPerimeter);
|
||||
REQUIRE(loop.paths[1].role() == erOverhangPerimeter);
|
||||
REQUIRE(loop.paths[2].role() == erExternalPerimeter);
|
||||
REQUIRE(loop.paths[3].role() == erOverhangPerimeter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("Some complex loop") {
|
||||
ExtrusionLoop loop;
|
||||
loop.paths.emplace_back(new_extrusion_path(
|
||||
Polyline { { 15896783, 15868739 }, { 24842049, 12117558 }, { 33853238, 15801279 }, { 37591780, 24780128 }, { 37591780, 24844970 },
|
||||
{ 33853231, 33825297 }, { 24842049, 37509013 }, { 15896798, 33757841 }, { 12211841, 24812544 }, { 15896783, 15868739 } },
|
||||
erExternalPerimeter, 1.));
|
||||
double len = loop.length();
|
||||
THEN("split_at() preserves total length") {
|
||||
loop.split_at({ 15896783, 15868739 }, false, 0);
|
||||
REQUIRE(loop.length() == Approx(len));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("ExtrusionEntityCollection: Basics", "[ExtrusionEntity]")
|
||||
{
|
||||
Polyline polyline { { 100, 100 }, { 200, 100 }, { 200, 200 } };
|
||||
ExtrusionPath path = new_extrusion_path(polyline, erExternalPerimeter, 1.);
|
||||
ExtrusionLoop loop;
|
||||
loop.paths.emplace_back(new_extrusion_path(Polygon(polyline.points).split_at_first_point(), erInternalInfill, 1.));
|
||||
ExtrusionEntityCollection collection;
|
||||
collection.append(path);
|
||||
THEN("no_sort is false by default") {
|
||||
REQUIRE(! collection.no_sort);
|
||||
}
|
||||
collection.append(collection);
|
||||
THEN("append ExtrusionEntityCollection") {
|
||||
REQUIRE(collection.entities.size() == 2);
|
||||
}
|
||||
collection.append(path);
|
||||
THEN("append ExtrusionPath") {
|
||||
REQUIRE(collection.entities.size() == 3);
|
||||
}
|
||||
collection.append(loop);
|
||||
THEN("append ExtrusionLoop") {
|
||||
REQUIRE(collection.entities.size() == 4);
|
||||
}
|
||||
THEN("appended collection was duplicated") {
|
||||
REQUIRE(dynamic_cast<ExtrusionEntityCollection*>(collection.entities[1])->entities.size() == 1);
|
||||
}
|
||||
WHEN("cloned") {
|
||||
auto coll2 = std::unique_ptr<ExtrusionEntityCollection>(dynamic_cast<ExtrusionEntityCollection*>(collection.clone()));
|
||||
THEN("expected no_sort value") {
|
||||
assert(! coll2->no_sort);
|
||||
}
|
||||
coll2->no_sort = true;
|
||||
THEN("no_sort is kept after clone") {
|
||||
auto coll3 = std::unique_ptr<ExtrusionEntityCollection>(dynamic_cast<ExtrusionEntityCollection*>(coll2->clone()));
|
||||
assert(coll3->no_sort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("ExtrusionEntityCollection: Polygon flattening", "[ExtrusionEntity]")
|
||||
{
|
||||
srand(0xDEADBEEF); // consistent seed for test reproducibility.
|
||||
|
||||
// Generate one specific random path set and save it for later comparison
|
||||
@ -101,7 +348,7 @@ TEST_CASE("ExtrusionEntityCollection: Chained path", "[ExtrusionEntity]") {
|
||||
{ {0,20}, {0,18}, {0,15} },
|
||||
{ {0,10}, {0,8}, {0,5} }
|
||||
},
|
||||
{ 0,30 }
|
||||
{ 0, 30 }
|
||||
},
|
||||
{
|
||||
{
|
||||
@ -112,7 +359,7 @@ TEST_CASE("ExtrusionEntityCollection: Chained path", "[ExtrusionEntity]") {
|
||||
{ {20,5}, {15,5}, {10,5} },
|
||||
{ {15,0}, {10,0}, {4,0} }
|
||||
},
|
||||
{ 30,0 }
|
||||
{ 30, 0 }
|
||||
},
|
||||
{
|
||||
{
|
||||
@ -123,7 +370,7 @@ TEST_CASE("ExtrusionEntityCollection: Chained path", "[ExtrusionEntity]") {
|
||||
{ {20,5}, {15,5}, {10,5} },
|
||||
{ {15,0}, {10,0}, {4,0} }
|
||||
},
|
||||
{ 30,0 }
|
||||
{ 30, 0 }
|
||||
},
|
||||
};
|
||||
for (const Test &test : tests) {
|
||||
@ -132,12 +379,24 @@ TEST_CASE("ExtrusionEntityCollection: Chained path", "[ExtrusionEntity]") {
|
||||
ExtrusionEntityCollection unchained_extrusions;
|
||||
extrusion_entities_append_paths(unchained_extrusions.entities, test.unchained,
|
||||
erInternalInfill, 0., 0.4f, 0.3f);
|
||||
ExtrusionEntityCollection chained_extrusions = unchained_extrusions.chained_path_from(test.initial_point);
|
||||
REQUIRE(chained_extrusions.entities.size() == test.chained.size());
|
||||
for (size_t i = 0; i < chained_extrusions.entities.size(); ++ i) {
|
||||
const Points &p1 = test.chained[i].points;
|
||||
const Points &p2 = dynamic_cast<const ExtrusionPath*>(chained_extrusions.entities[i])->polyline.points;
|
||||
REQUIRE(p1 == p2);
|
||||
THEN("Chaining works") {
|
||||
ExtrusionEntityCollection chained_extrusions = unchained_extrusions.chained_path_from(test.initial_point);
|
||||
REQUIRE(chained_extrusions.entities.size() == test.chained.size());
|
||||
for (size_t i = 0; i < chained_extrusions.entities.size(); ++ i) {
|
||||
const Points &p1 = test.chained[i].points;
|
||||
const Points &p2 = dynamic_cast<const ExtrusionPath*>(chained_extrusions.entities[i])->polyline.points;
|
||||
REQUIRE(p1 == p2);
|
||||
}
|
||||
}
|
||||
THEN("Chaining produces no change with no_sort") {
|
||||
unchained_extrusions.no_sort = true;
|
||||
ExtrusionEntityCollection chained_extrusions = unchained_extrusions.chained_path_from(test.initial_point);
|
||||
REQUIRE(chained_extrusions.entities.size() == test.unchained.size());
|
||||
for (size_t i = 0; i < chained_extrusions.entities.size(); ++ i) {
|
||||
const Points &p1 = test.unchained[i].points;
|
||||
const Points &p2 = dynamic_cast<const ExtrusionPath*>(chained_extrusions.entities[i])->polyline.points;
|
||||
REQUIRE(p1 == p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,17 @@
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/Fill/Fill.hpp"
|
||||
#include "libslic3r/Flow.hpp"
|
||||
#include "libslic3r/Layer.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "libslic3r/Geometry/ConvexHull.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/SVG.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
#include "test_data.hpp"
|
||||
|
||||
@ -329,6 +332,130 @@ SCENARIO("Infill only where needed", "[Fill]")
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Combine infill", "[Fill]")
|
||||
{
|
||||
{
|
||||
auto test = [](const DynamicPrintConfig &config) {
|
||||
std::string gcode = Test::slice({ Test::TestMesh::cube_20x20x20 }, config);
|
||||
THEN("infill_every_layers does not crash") {
|
||||
REQUIRE(! gcode.empty());
|
||||
}
|
||||
|
||||
Slic3r::GCodeReader parser;
|
||||
int tool = -1;
|
||||
std::set<coord_t> layers; // layer_z => 1
|
||||
std::map<coord_t, bool> layer_infill; // layer_z => has_infill
|
||||
const int infill_extruder = config.opt_int("infill_extruder");
|
||||
const int support_material_extruder = config.opt_int("support_material_extruder");
|
||||
parser.parse_buffer(gcode,
|
||||
[&tool, &layers, &layer_infill, infill_extruder, support_material_extruder](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line)
|
||||
{
|
||||
coord_t z = line.new_Z(self) / SCALING_FACTOR;
|
||||
if (boost::starts_with(line.cmd(), "T")) {
|
||||
tool = atoi(line.cmd().data() + 1);
|
||||
} else if (line.cmd_is("G1") && line.extruding(self) && line.dist_XY(self) > 0 && tool + 1 != support_material_extruder) {
|
||||
if (tool + 1 == infill_extruder)
|
||||
layer_infill[z] = true;
|
||||
else if (auto it = layer_infill.find(z); it == layer_infill.end())
|
||||
layer_infill.insert(it, std::make_pair(z, false));
|
||||
}
|
||||
// Previously, all G-code commands had a fixed number of decimal points with means with redundant zeros after decimal points.
|
||||
// We changed this behavior and got rid of these redundant padding zeros, which caused this test to fail
|
||||
// because the position in Z-axis is compared as a string, and previously, G-code contained the following two commands:
|
||||
// "G1 Z5 F5000 ; lift nozzle"
|
||||
// "G1 Z5.000 F7800.000"
|
||||
// That has a different Z-axis position from the view of string comparisons of floating-point numbers.
|
||||
// To correct the computation of the number of printed layers, even in the case of string comparisons of floating-point numbers,
|
||||
// we filtered out the G-code command with the commend 'lift nozzle'.
|
||||
if (line.cmd_is("G1") && line.dist_Z(self) != 0 && line.comment().find("lift nozzle") == std::string::npos)
|
||||
layers.insert(z);
|
||||
});
|
||||
|
||||
auto layers_with_perimeters = int(layer_infill.size());
|
||||
auto layers_with_infill = int(std::count_if(layer_infill.begin(), layer_infill.end(), [](auto &v){ return v.second; }));
|
||||
THEN("expected number of layers") {
|
||||
REQUIRE(layers.size() == layers_with_perimeters + config.opt_int("raft_layers"));
|
||||
}
|
||||
|
||||
if (config.opt_int("raft_layers") == 0) {
|
||||
// first infill layer printed directly on print bed is not combined, so we don't consider it.
|
||||
-- layers_with_infill;
|
||||
-- layers_with_perimeters;
|
||||
}
|
||||
|
||||
// we expect that infill is generated for half the number of combined layers
|
||||
// plus for each single layer that was not combined (remainder)
|
||||
THEN("infill is only present in correct number of layers") {
|
||||
int infill_every = config.opt_int("infill_every_layers");
|
||||
REQUIRE(layers_with_infill == int(layers_with_perimeters / infill_every) + (layers_with_perimeters % infill_every));
|
||||
}
|
||||
};
|
||||
|
||||
auto config = Slic3r::DynamicPrintConfig::full_print_config_with({
|
||||
{ "nozzle_diameter", "0.5, 0.5, 0.5, 0.5" },
|
||||
{ "layer_height", 0.2 },
|
||||
{ "first_layer_height", 0.2 },
|
||||
{ "infill_every_layers", 2 },
|
||||
{ "perimeter_extruder", 1 },
|
||||
{ "infill_extruder", 2 },
|
||||
{ "wipe_into_infill", false },
|
||||
{ "support_material_extruder", 3 },
|
||||
{ "support_material_interface_extruder", 3 },
|
||||
{ "top_solid_layers", 0 },
|
||||
{ "bottom_solid_layers", 0 }
|
||||
});
|
||||
|
||||
test(config);
|
||||
|
||||
// Reuse the config above
|
||||
config.set_deserialize_strict({
|
||||
{ "skirts", 0 }, // prevent usage of perimeter_extruder in raft layers
|
||||
{ "raft_layers", 5 }
|
||||
});
|
||||
test(config);
|
||||
}
|
||||
|
||||
WHEN("infill_every_layers == 2") {
|
||||
Slic3r::Print print;
|
||||
Slic3r::Test::init_and_process_print({ Test::TestMesh::cube_20x20x20 }, print, {
|
||||
{ "nozzle_diameter", "0.5" },
|
||||
{ "layer_height", 0.2 },
|
||||
{ "first_layer_height", 0.2 },
|
||||
{ "infill_every_layers", 2 }
|
||||
});
|
||||
THEN("infill combination produces internal void surfaces") {
|
||||
bool has_void = false;
|
||||
for (const Layer *layer : print.get_object(0)->layers())
|
||||
if (layer->get_region(0)->fill_surfaces().filter_by_type(stInternalVoid).size() > 0) {
|
||||
has_void = true;
|
||||
break;
|
||||
}
|
||||
REQUIRE(has_void);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("infill_every_layers disabled") {
|
||||
// we disable combination after infill has been generated
|
||||
Slic3r::Print print;
|
||||
Slic3r::Test::init_and_process_print({ Test::TestMesh::cube_20x20x20 }, print, {
|
||||
{ "nozzle_diameter", "0.5" },
|
||||
{ "layer_height", 0.2 },
|
||||
{ "first_layer_height", 0.2 },
|
||||
{ "infill_every_layers", 1 }
|
||||
});
|
||||
|
||||
THEN("infill combination is idempotent") {
|
||||
bool has_infill_on_each_layer = true;
|
||||
for (const Layer *layer : print.get_object(0)->layers())
|
||||
if (layer->get_region(0)->fill_surfaces().empty()) {
|
||||
has_infill_on_each_layer = false;
|
||||
break;
|
||||
}
|
||||
REQUIRE(has_infill_on_each_layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Infill density zero", "[Fill]")
|
||||
{
|
||||
WHEN("20mm cube is sliced") {
|
||||
|
@ -44,7 +44,7 @@ SCENARIO("Perimeter nesting", "[Perimeters]")
|
||||
|
||||
ExtrusionEntityCollection loops;
|
||||
ExtrusionEntityCollection gap_fill;
|
||||
SurfaceCollection fill_surfaces;
|
||||
ExPolygons fill_expolygons;
|
||||
Flow flow(1., 1., 1.);
|
||||
PerimeterGenerator::Parameters perimeter_generator_params(
|
||||
1., // layer height
|
||||
@ -67,7 +67,7 @@ SCENARIO("Perimeter nesting", "[Perimeters]")
|
||||
// cache:
|
||||
lower_layer_polygons_cache,
|
||||
// output:
|
||||
loops, gap_fill, fill_surfaces);
|
||||
loops, gap_fill, fill_expolygons);
|
||||
|
||||
THEN("expected number of collections") {
|
||||
REQUIRE(loops.entities.size() == data.expolygons.size());
|
||||
|
@ -46,11 +46,7 @@ set(XS_XSP_FILES
|
||||
${XSP_DIR}/BoundingBox.xsp
|
||||
${XSP_DIR}/Config.xsp
|
||||
${XSP_DIR}/ExPolygon.xsp
|
||||
${XSP_DIR}/ExtrusionEntityCollection.xsp
|
||||
${XSP_DIR}/ExtrusionLoop.xsp
|
||||
${XSP_DIR}/ExtrusionPath.xsp
|
||||
${XSP_DIR}/Geometry.xsp
|
||||
${XSP_DIR}/Layer.xsp
|
||||
${XSP_DIR}/Line.xsp
|
||||
${XSP_DIR}/Model.xsp
|
||||
${XSP_DIR}/Point.xsp
|
||||
|
@ -159,8 +159,6 @@ for my $class (qw(
|
||||
Slic3r::ExtrusionPath
|
||||
Slic3r::ExtrusionPath::Collection
|
||||
Slic3r::Geometry::BoundingBox
|
||||
Slic3r::Layer
|
||||
Slic3r::Layer::Region
|
||||
Slic3r::Line
|
||||
Slic3r::Model
|
||||
Slic3r::Model::Instance
|
||||
|
@ -8,8 +8,6 @@ REGISTER_CLASS(ExtrusionPath, "ExtrusionPath");
|
||||
REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop");
|
||||
REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection");
|
||||
REGISTER_CLASS(GCode, "GCode");
|
||||
REGISTER_CLASS(Layer, "Layer");
|
||||
REGISTER_CLASS(LayerRegion, "Layer::Region");
|
||||
REGISTER_CLASS(Line, "Line");
|
||||
REGISTER_CLASS(Polygon, "Polygon");
|
||||
REGISTER_CLASS(Polyline, "Polyline");
|
||||
|
@ -1,36 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 5;
|
||||
|
||||
my $points = [
|
||||
[100, 100],
|
||||
[200, 100],
|
||||
[200, 200],
|
||||
];
|
||||
|
||||
my $path = Slic3r::ExtrusionPath->new(
|
||||
polyline => Slic3r::Polyline->new(@$points),
|
||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||
mm3_per_mm => 1,
|
||||
);
|
||||
|
||||
$path->reverse;
|
||||
is_deeply $path->polyline->pp, [ reverse @$points ], 'reverse path';
|
||||
|
||||
$path->append([ 150, 150 ]);
|
||||
is scalar(@$path), 4, 'append to path';
|
||||
|
||||
$path->pop_back;
|
||||
is scalar(@$path), 3, 'pop_back from path';
|
||||
|
||||
ok $path->first_point->coincides_with($path->polyline->[0]), 'first_point';
|
||||
|
||||
$path = $path->clone;
|
||||
|
||||
is $path->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'role';
|
||||
|
||||
__END__
|
@ -1,157 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use List::Util qw(sum);
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 46;
|
||||
|
||||
{
|
||||
my $square = [
|
||||
[100, 100],
|
||||
[200, 100],
|
||||
[200, 200],
|
||||
[100, 200],
|
||||
];
|
||||
my $square_p = Slic3r::Polygon->new(@$square);
|
||||
|
||||
my $loop = Slic3r::ExtrusionLoop->new;
|
||||
$loop->append(Slic3r::ExtrusionPath->new(
|
||||
polyline => $square_p->split_at_first_point,
|
||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||
mm3_per_mm => 1,
|
||||
));
|
||||
|
||||
isa_ok $loop, 'Slic3r::ExtrusionLoop';
|
||||
isa_ok $loop->polygon, 'Slic3r::Polygon', 'loop polygon';
|
||||
is $loop->polygon->area, $square_p->area, 'polygon area';
|
||||
is $loop->length, $square_p->length(), 'loop length';
|
||||
|
||||
$loop = $loop->clone;
|
||||
|
||||
is scalar(@$loop), 1, 'loop contains one path';
|
||||
{
|
||||
my $path = $loop->[0];
|
||||
is $path->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'role';
|
||||
}
|
||||
|
||||
$loop->split_at_vertex($square_p->[2]);
|
||||
is scalar(@$loop), 1, 'splitting a single-path loop results in a single path';
|
||||
is scalar(@{$loop->[0]->polyline}), 5, 'path has correct number of points';
|
||||
ok $loop->[0]->polyline->[0]->coincides_with($square_p->[2]), 'expected point order';
|
||||
ok $loop->[0]->polyline->[1]->coincides_with($square_p->[3]), 'expected point order';
|
||||
ok $loop->[0]->polyline->[2]->coincides_with($square_p->[0]), 'expected point order';
|
||||
ok $loop->[0]->polyline->[3]->coincides_with($square_p->[1]), 'expected point order';
|
||||
ok $loop->[0]->polyline->[4]->coincides_with($square_p->[2]), 'expected point order';
|
||||
}
|
||||
|
||||
{
|
||||
my $polyline1 = Slic3r::Polyline->new([100,100], [200,100], [200,200]);
|
||||
my $polyline2 = Slic3r::Polyline->new([200,200], [100,200], [100,100]);
|
||||
|
||||
my $loop = Slic3r::ExtrusionLoop->new_from_paths(
|
||||
Slic3r::ExtrusionPath->new(
|
||||
polyline => $polyline1,
|
||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||
mm3_per_mm => 1,
|
||||
),
|
||||
Slic3r::ExtrusionPath->new(
|
||||
polyline => $polyline2,
|
||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER,
|
||||
mm3_per_mm => 1,
|
||||
),
|
||||
);
|
||||
my $tot_len = sum($polyline1->length, $polyline2->length);
|
||||
is $loop->length, $tot_len, 'length';
|
||||
is scalar(@$loop), 2, 'loop contains two paths';
|
||||
|
||||
{
|
||||
# check splitting at intermediate point
|
||||
my $loop2 = $loop->clone;
|
||||
isa_ok $loop2, 'Slic3r::ExtrusionLoop';
|
||||
$loop2->split_at_vertex($polyline1->[1]);
|
||||
is $loop2->length, $tot_len, 'length after splitting is unchanged';
|
||||
is scalar(@$loop2), 3, 'loop contains three paths after splitting';
|
||||
ok $loop2->[0]->polyline->[0]->coincides_with($polyline1->[1]), 'expected starting point';
|
||||
ok $loop2->[-1]->polyline->[-1]->coincides_with($polyline1->[1]), 'expected ending point';
|
||||
ok $loop2->[0]->polyline->[-1]->coincides_with($loop2->[1]->polyline->[0]), 'paths have common point';
|
||||
ok $loop2->[1]->polyline->[-1]->coincides_with($loop2->[2]->polyline->[0]), 'paths have common point';
|
||||
is $loop2->[0]->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'expected order after splitting';
|
||||
is $loop2->[1]->role, Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER, 'expected order after splitting';
|
||||
is $loop2->[2]->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'expected order after splitting';
|
||||
is scalar(@{$loop2->[0]->polyline}), 2, 'path has correct number of points';
|
||||
is scalar(@{$loop2->[1]->polyline}), 3, 'path has correct number of points';
|
||||
is scalar(@{$loop2->[2]->polyline}), 2, 'path has correct number of points';
|
||||
|
||||
my @paths = @{$loop2->clip_end(3)};
|
||||
is sum(map $_->length, @paths), $loop2->length - 3, 'returned paths have expected length';
|
||||
}
|
||||
|
||||
{
|
||||
# check splitting at endpoint
|
||||
my $loop2 = $loop->clone;
|
||||
$loop2->split_at_vertex($polyline2->[0]);
|
||||
is $loop2->length, $tot_len, 'length after splitting is unchanged';
|
||||
is scalar(@$loop2), 2, 'loop contains two paths after splitting';
|
||||
ok $loop2->[0]->polyline->[0]->coincides_with($polyline2->[0]), 'expected starting point';
|
||||
ok $loop2->[-1]->polyline->[-1]->coincides_with($polyline2->[0]), 'expected ending point';
|
||||
ok $loop2->[0]->polyline->[-1]->coincides_with($loop2->[1]->polyline->[0]), 'paths have common point';
|
||||
ok $loop2->[1]->polyline->[-1]->coincides_with($loop2->[0]->polyline->[0]), 'paths have common point';
|
||||
is $loop2->[0]->role, Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER, 'expected order after splitting';
|
||||
is $loop2->[1]->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'expected order after splitting';
|
||||
is scalar(@{$loop2->[0]->polyline}), 3, 'path has correct number of points';
|
||||
is scalar(@{$loop2->[1]->polyline}), 3, 'path has correct number of points';
|
||||
}
|
||||
|
||||
{
|
||||
my $loop2 = $loop->clone;
|
||||
my $point = Slic3r::Point->new(250,150);
|
||||
$loop2->split_at($point);
|
||||
is $loop2->length, $tot_len, 'length after splitting is unchanged';
|
||||
is scalar(@$loop2), 3, 'loop contains three paths after splitting';
|
||||
my $expected_start_point = Slic3r::Point->new(200,150);
|
||||
ok $loop2->[0]->polyline->[0]->coincides_with($expected_start_point), 'expected starting point';
|
||||
ok $loop2->[-1]->polyline->[-1]->coincides_with($expected_start_point), 'expected ending point';
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my @polylines = (
|
||||
Slic3r::Polyline->new([59312736,4821067],[64321068,4821067],[64321068,4821067],[64321068,9321068],[59312736,9321068]),
|
||||
Slic3r::Polyline->new([59312736,9321068],[9829401,9321068]),
|
||||
Slic3r::Polyline->new([9829401,9321068],[4821067,9321068],[4821067,4821067],[9829401,4821067]),
|
||||
Slic3r::Polyline->new([9829401,4821067],[59312736,4821067]),
|
||||
);
|
||||
my $loop = Slic3r::ExtrusionLoop->new;
|
||||
$loop->append($_) for (
|
||||
Slic3r::ExtrusionPath->new(polyline => $polylines[0], role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, mm3_per_mm => 1),
|
||||
Slic3r::ExtrusionPath->new(polyline => $polylines[1], role => Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER, mm3_per_mm => 1),
|
||||
Slic3r::ExtrusionPath->new(polyline => $polylines[2], role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, mm3_per_mm => 1),
|
||||
Slic3r::ExtrusionPath->new(polyline => $polylines[3], role => Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER, mm3_per_mm => 1),
|
||||
);
|
||||
my $len = $loop->length;
|
||||
my $point = Slic3r::Point->new(4821067,9321068);
|
||||
$loop->split_at_vertex($point) or $loop->split_at($point);
|
||||
is $loop->length, $len, 'total length is preserved after splitting';
|
||||
is_deeply [ map $_->role, @$loop ], [
|
||||
Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||
Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER,
|
||||
Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||
Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER,
|
||||
Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||
], 'order is correctly preserved after splitting';
|
||||
}
|
||||
|
||||
{
|
||||
my $loop = Slic3r::ExtrusionLoop->new;
|
||||
$loop->append(Slic3r::ExtrusionPath->new(
|
||||
polyline => Slic3r::Polyline->new([15896783,15868739],[24842049,12117558],[33853238,15801279],[37591780,24780128],[37591780,24844970],[33853231,33825297],[24842049,37509013],[15896798,33757841],[12211841,24812544],[15896783,15868739]),
|
||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, mm3_per_mm => 1
|
||||
));
|
||||
my $len = $loop->length;
|
||||
$loop->split_at(Slic3r::Point->new(15896783,15868739));
|
||||
is $loop->length, $len, 'split_at() preserves total length';
|
||||
}
|
||||
|
||||
__END__
|
@ -1,91 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 13;
|
||||
|
||||
my $points = [
|
||||
[100, 100],
|
||||
[200, 100],
|
||||
[200, 200],
|
||||
];
|
||||
|
||||
my $path = Slic3r::ExtrusionPath->new(
|
||||
polyline => Slic3r::Polyline->new(@$points),
|
||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||
mm3_per_mm => 1,
|
||||
);
|
||||
|
||||
my $loop = Slic3r::ExtrusionLoop->new_from_paths(
|
||||
Slic3r::ExtrusionPath->new(
|
||||
polyline => Slic3r::Polygon->new(@$points)->split_at_first_point,
|
||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_FILL,
|
||||
mm3_per_mm => 1,
|
||||
),
|
||||
);
|
||||
|
||||
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
||||
$path,
|
||||
);
|
||||
isa_ok $collection, 'Slic3r::ExtrusionPath::Collection', 'collection object with items in constructor';
|
||||
ok !$collection->no_sort, 'no_sort is false by default';
|
||||
|
||||
$collection->append($collection);
|
||||
is scalar(@$collection), 2, 'append ExtrusionPath::Collection';
|
||||
|
||||
$collection->append($path);
|
||||
is scalar(@$collection), 3, 'append ExtrusionPath';
|
||||
|
||||
$collection->append($loop);
|
||||
is scalar(@$collection), 4, 'append ExtrusionLoop';
|
||||
|
||||
is scalar(@{$collection->[1]}), 1, 'appended collection was duplicated';
|
||||
|
||||
{
|
||||
my $collection_loop = $collection->[3];
|
||||
$collection_loop->polygon->scale(2);
|
||||
is_deeply $collection->[3]->polygon->pp, $collection_loop->polygon->pp, 'items are returned by reference';
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
||||
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1),
|
||||
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
|
||||
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->y, map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ],
|
||||
[20, 18, 15, 10, 8, 5],
|
||||
'chained_path_from';
|
||||
is_deeply
|
||||
[ map $_->y, map @{$_->polyline}, @{$collection->chained_path(0)} ],
|
||||
[15, 18, 20, 10, 8, 5],
|
||||
'chained_path';
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
||||
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1),
|
||||
Slic3r::Polyline->new([15,0], [10,0], [4,0]),
|
||||
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->x, map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ],
|
||||
[reverse 4, 10, 15, 10, 15, 20],
|
||||
'chained_path_from';
|
||||
|
||||
$collection->no_sort(1);
|
||||
my @foo = @{$collection->chained_path(0)};
|
||||
pass 'chained_path with no_sort';
|
||||
}
|
||||
|
||||
{
|
||||
my $coll2 = $collection->clone;
|
||||
ok !$coll2->no_sort, 'expected no_sort value';
|
||||
$coll2->no_sort(1);
|
||||
ok $coll2->clone->no_sort, 'no_sort is kept after clone';
|
||||
}
|
||||
|
||||
__END__
|
@ -1,102 +0,0 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/ExtrusionEntityCollection.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::ExtrusionPath::Collection} class ExtrusionEntityCollection {
|
||||
%name{_new} ExtrusionEntityCollection();
|
||||
~ExtrusionEntityCollection();
|
||||
Clone<ExtrusionEntityCollection> clone()
|
||||
%code{% RETVAL = (ExtrusionEntityCollection*)THIS->clone(); %};
|
||||
void reverse();
|
||||
void clear();
|
||||
ExtrusionEntityCollection* chained_path(bool no_reverse, ExtrusionRole role = erMixed)
|
||||
%code{%
|
||||
if (no_reverse)
|
||||
croak("no_reverse must be false");
|
||||
RETVAL = new ExtrusionEntityCollection();
|
||||
*RETVAL = THIS->chained_path_from(THIS->entities.front()->first_point());
|
||||
%};
|
||||
ExtrusionEntityCollection* chained_path_from(Point* start_near, bool no_reverse, ExtrusionRole role = erMixed)
|
||||
%code{%
|
||||
if (no_reverse)
|
||||
croak("no_reverse must be false");
|
||||
RETVAL = new ExtrusionEntityCollection();
|
||||
*RETVAL = THIS->chained_path_from(*start_near, role);
|
||||
%};
|
||||
Clone<Point> first_point();
|
||||
Clone<Point> last_point();
|
||||
int count()
|
||||
%code{% RETVAL = THIS->entities.size(); %};
|
||||
int items_count()
|
||||
%code{% RETVAL = THIS->items_count(); %};
|
||||
ExtrusionEntityCollection* flatten()
|
||||
%code{%
|
||||
RETVAL = new ExtrusionEntityCollection();
|
||||
*RETVAL = THIS->flatten();
|
||||
%};
|
||||
double min_mm3_per_mm();
|
||||
bool empty()
|
||||
%code{% RETVAL = THIS->entities.empty(); %};
|
||||
Polygons polygons_covered_by_width();
|
||||
Polygons polygons_covered_by_spacing();
|
||||
%{
|
||||
|
||||
SV*
|
||||
ExtrusionEntityCollection::arrayref()
|
||||
CODE:
|
||||
AV* av = newAV();
|
||||
av_fill(av, THIS->entities.size()-1);
|
||||
int i = 0;
|
||||
for (ExtrusionEntitiesPtr::iterator it = THIS->entities.begin(); it != THIS->entities.end(); ++it) {
|
||||
SV* sv = newSV(0);
|
||||
// return our item by reference
|
||||
if (ExtrusionPath* path = dynamic_cast<ExtrusionPath*>(*it)) {
|
||||
sv_setref_pv( sv, perl_class_name_ref(path), path );
|
||||
} else if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(*it)) {
|
||||
sv_setref_pv( sv, perl_class_name_ref(loop), loop );
|
||||
} else if (ExtrusionEntityCollection* collection = dynamic_cast<ExtrusionEntityCollection*>(*it)) {
|
||||
sv_setref_pv( sv, perl_class_name_ref(collection), collection );
|
||||
} else {
|
||||
croak("Unexpected type in ExtrusionEntityCollection");
|
||||
}
|
||||
av_store(av, i++, sv);
|
||||
}
|
||||
RETVAL = newRV_noinc((SV*)av);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
ExtrusionEntityCollection::append(...)
|
||||
CODE:
|
||||
for (unsigned int i = 1; i < items; i++) {
|
||||
if(!sv_isobject( ST(i) ) || (SvTYPE(SvRV( ST(i) )) != SVt_PVMG)) {
|
||||
croak("Argument %d is not object", i);
|
||||
}
|
||||
ExtrusionEntity* entity = (ExtrusionEntity *)SvIV((SV*)SvRV( ST(i) ));
|
||||
// append COPIES
|
||||
if (ExtrusionPath* path = dynamic_cast<ExtrusionPath*>(entity)) {
|
||||
THIS->entities.push_back( new ExtrusionPath(*path) );
|
||||
} else if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(entity)) {
|
||||
THIS->entities.push_back( new ExtrusionLoop(*loop) );
|
||||
} else if(ExtrusionEntityCollection* collection = dynamic_cast<ExtrusionEntityCollection*>(entity)) {
|
||||
THIS->entities.push_back( collection->clone() );
|
||||
} else {
|
||||
croak("Argument %d is of unknown type", i);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ExtrusionEntityCollection::no_sort(...)
|
||||
CODE:
|
||||
if (items > 1) {
|
||||
THIS->no_sort = SvTRUE(ST(1));
|
||||
}
|
||||
RETVAL = THIS->no_sort;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
};
|
@ -1,65 +0,0 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::ExtrusionLoop} class ExtrusionLoop {
|
||||
ExtrusionLoop();
|
||||
~ExtrusionLoop();
|
||||
Clone<ExtrusionLoop> clone()
|
||||
%code{% RETVAL = THIS; %};
|
||||
void reverse();
|
||||
bool make_clockwise();
|
||||
bool make_counter_clockwise();
|
||||
Clone<Point> first_point();
|
||||
Clone<Point> last_point();
|
||||
Clone<Polygon> polygon();
|
||||
void append(ExtrusionPath* path)
|
||||
%code{% THIS->paths.push_back(*path); %};
|
||||
double length();
|
||||
bool split_at_vertex(Point* point)
|
||||
%code{% RETVAL = THIS->split_at_vertex(*point); %};
|
||||
void split_at(Point* point, int prefer_non_overhang = 0, double scaled_epsilon = 0.)
|
||||
%code{% THIS->split_at(*point, prefer_non_overhang != 0, scaled_epsilon); %};
|
||||
ExtrusionPaths clip_end(double distance)
|
||||
%code{% THIS->clip_end(distance, &RETVAL); %};
|
||||
bool has_overhang_point(Point* point)
|
||||
%code{% RETVAL = THIS->has_overhang_point(*point); %};
|
||||
ExtrusionRole role() const;
|
||||
ExtrusionLoopRole loop_role() const;
|
||||
Polygons polygons_covered_by_width();
|
||||
Polygons polygons_covered_by_spacing();
|
||||
%{
|
||||
|
||||
SV*
|
||||
ExtrusionLoop::arrayref()
|
||||
CODE:
|
||||
AV* av = newAV();
|
||||
av_fill(av, THIS->paths.size()-1);
|
||||
for (ExtrusionPaths::iterator it = THIS->paths.begin(); it != THIS->paths.end(); ++it) {
|
||||
av_store(av, it - THIS->paths.begin(), perl_to_SV_ref(*it));
|
||||
}
|
||||
RETVAL = newRV_noinc((SV*)av);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
};
|
||||
|
||||
%package{Slic3r::ExtrusionLoop};
|
||||
%{
|
||||
|
||||
IV
|
||||
_constant()
|
||||
ALIAS:
|
||||
EXTRL_ROLE_DEFAULT = elrDefault
|
||||
EXTRL_ROLE_CONTOUR_INTERNAL_PERIMETER = elrContourInternalPerimeter
|
||||
EXTRL_ROLE_SKIRT = elrSkirt
|
||||
PROTOTYPE:
|
||||
CODE:
|
||||
RETVAL = ix;
|
||||
OUTPUT: RETVAL
|
||||
|
||||
%}
|
@ -1,126 +0,0 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/ExtrusionEntityCollection.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::ExtrusionPath} class ExtrusionPath {
|
||||
~ExtrusionPath();
|
||||
SV* arrayref()
|
||||
%code{% RETVAL = to_AV(&THIS->polyline); %};
|
||||
SV* pp()
|
||||
%code{% RETVAL = to_SV_pureperl(&THIS->polyline); %};
|
||||
void pop_back()
|
||||
%code{% THIS->polyline.points.pop_back(); %};
|
||||
void reverse();
|
||||
Lines lines()
|
||||
%code{% RETVAL = THIS->polyline.lines(); %};
|
||||
Clone<Point> first_point();
|
||||
Clone<Point> last_point();
|
||||
void clip_end(double distance);
|
||||
void simplify(double tolerance);
|
||||
double length();
|
||||
ExtrusionRole role() const;
|
||||
bool is_bridge()
|
||||
%code{% RETVAL = is_bridge(THIS->role()); %};
|
||||
Polygons polygons_covered_by_width();
|
||||
Polygons polygons_covered_by_spacing();
|
||||
%{
|
||||
|
||||
ExtrusionPath*
|
||||
_new(CLASS, polyline_sv, role, mm3_per_mm, width, height)
|
||||
char* CLASS;
|
||||
SV* polyline_sv;
|
||||
ExtrusionRole role;
|
||||
double mm3_per_mm;
|
||||
float width;
|
||||
float height;
|
||||
CODE:
|
||||
RETVAL = new ExtrusionPath (role);
|
||||
from_SV_check(polyline_sv, &RETVAL->polyline);
|
||||
RETVAL->mm3_per_mm = mm3_per_mm;
|
||||
RETVAL->width = width;
|
||||
RETVAL->height = height;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Ref<Polyline>
|
||||
ExtrusionPath::polyline(...)
|
||||
CODE:
|
||||
if (items > 1) {
|
||||
from_SV_check(ST(1), &THIS->polyline);
|
||||
}
|
||||
RETVAL = &(THIS->polyline);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
double
|
||||
ExtrusionPath::mm3_per_mm(...)
|
||||
CODE:
|
||||
if (items > 1) {
|
||||
THIS->mm3_per_mm = (double)SvNV(ST(1));
|
||||
}
|
||||
RETVAL = THIS->mm3_per_mm;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
float
|
||||
ExtrusionPath::width(...)
|
||||
CODE:
|
||||
if (items > 1) {
|
||||
THIS->width = (float)SvNV(ST(1));
|
||||
}
|
||||
RETVAL = THIS->width;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
float
|
||||
ExtrusionPath::height(...)
|
||||
CODE:
|
||||
if (items > 1) {
|
||||
THIS->height = (float)SvNV(ST(1));
|
||||
}
|
||||
RETVAL = THIS->height;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
ExtrusionPath::append(...)
|
||||
CODE:
|
||||
for (unsigned int i = 1; i < items; i++) {
|
||||
Point p;
|
||||
from_SV_check(ST(i), &p);
|
||||
THIS->polyline.points.push_back(p);
|
||||
}
|
||||
|
||||
%}
|
||||
};
|
||||
|
||||
%package{Slic3r::ExtrusionPath};
|
||||
%{
|
||||
|
||||
IV
|
||||
_constant()
|
||||
ALIAS:
|
||||
EXTR_ROLE_NONE = erNone
|
||||
EXTR_ROLE_PERIMETER = erPerimeter
|
||||
EXTR_ROLE_EXTERNAL_PERIMETER = erExternalPerimeter
|
||||
EXTR_ROLE_OVERHANG_PERIMETER = erOverhangPerimeter
|
||||
EXTR_ROLE_FILL = erInternalInfill
|
||||
EXTR_ROLE_SOLIDFILL = erSolidInfill
|
||||
EXTR_ROLE_TOPSOLIDFILL = erTopSolidInfill
|
||||
EXTR_ROLE_BRIDGE = erBridgeInfill
|
||||
EXTR_ROLE_GAPFILL = erGapFill
|
||||
EXTR_ROLE_SKIRT = erSkirt
|
||||
EXTR_ROLE_SUPPORTMATERIAL = erSupportMaterial
|
||||
EXTR_ROLE_SUPPORTMATERIAL_INTERFACE = erSupportMaterialInterface
|
||||
EXTR_ROLE_MIXED = erMixed
|
||||
PROTOTYPE:
|
||||
CODE:
|
||||
RETVAL = ix;
|
||||
OUTPUT: RETVAL
|
||||
|
||||
%}
|
||||
|
@ -1,72 +0,0 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/Layer.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::Layer::Region} class LayerRegion {
|
||||
// owned by Layer, no constructor/destructor
|
||||
|
||||
Ref<Layer> layer();
|
||||
Ref<PrintRegion> region()
|
||||
%code%{ RETVAL = &THIS->region(); %};
|
||||
|
||||
Ref<SurfaceCollection> slices()
|
||||
%code%{ RETVAL = const_cast<SurfaceCollection*>(&THIS->slices()); %};
|
||||
Ref<ExtrusionEntityCollection> thin_fills()
|
||||
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->thin_fills()); %};
|
||||
Ref<SurfaceCollection> fill_surfaces()
|
||||
%code%{ RETVAL = const_cast<SurfaceCollection*>(&THIS->fill_surfaces()); %};
|
||||
Ref<ExtrusionEntityCollection> perimeters()
|
||||
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->perimeters()); %};
|
||||
Ref<ExtrusionEntityCollection> fills()
|
||||
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->fills()); %};
|
||||
|
||||
void prepare_fill_surfaces();
|
||||
void make_perimeters(SurfaceCollection* slices, SurfaceCollection* fill_surfaces)
|
||||
%code%{ THIS->make_perimeters(*slices, fill_surfaces); %};
|
||||
double infill_area_threshold();
|
||||
|
||||
void export_region_slices_to_svg(const char *path) const;
|
||||
void export_region_fill_surfaces_to_svg(const char *path) const;
|
||||
void export_region_slices_to_svg_debug(const char *name) const;
|
||||
void export_region_fill_surfaces_to_svg_debug(const char *name) const;
|
||||
};
|
||||
|
||||
%name{Slic3r::Layer} class Layer {
|
||||
// owned by PrintObject, no constructor/destructor
|
||||
|
||||
Ref<Layer> as_layer()
|
||||
%code%{ RETVAL = THIS; %};
|
||||
|
||||
int id();
|
||||
void set_id(int id);
|
||||
Ref<PrintObject> object();
|
||||
bool slicing_errors()
|
||||
%code%{ RETVAL = THIS->slicing_errors; %};
|
||||
coordf_t slice_z()
|
||||
%code%{ RETVAL = THIS->slice_z; %};
|
||||
coordf_t print_z()
|
||||
%code%{ RETVAL = THIS->print_z; %};
|
||||
coordf_t height()
|
||||
%code%{ RETVAL = THIS->height; %};
|
||||
|
||||
size_t region_count();
|
||||
Ref<LayerRegion> get_region(int idx);
|
||||
Ref<LayerRegion> add_region(PrintRegion* print_region);
|
||||
|
||||
int ptr()
|
||||
%code%{ RETVAL = (int)(intptr_t)THIS; %};
|
||||
|
||||
void make_slices();
|
||||
void backup_untyped_slices();
|
||||
void restore_untyped_slices();
|
||||
void make_perimeters();
|
||||
void make_fills();
|
||||
|
||||
void export_region_slices_to_svg(const char *path);
|
||||
void export_region_fill_surfaces_to_svg(const char *path);
|
||||
void export_region_slices_to_svg_debug(const char *name);
|
||||
void export_region_fill_surfaces_to_svg_debug(const char *name);
|
||||
};
|
@ -21,9 +21,6 @@
|
||||
%code%{ RETVAL = &THIS->config(); %};
|
||||
Clone<BoundingBox> bounding_box();
|
||||
|
||||
size_t layer_count();
|
||||
Ref<Layer> get_layer(int idx);
|
||||
|
||||
void slice();
|
||||
};
|
||||
|
||||
@ -35,10 +32,6 @@
|
||||
%code%{ RETVAL = const_cast<Model*>(&THIS->model()); %};
|
||||
Ref<StaticPrintConfig> config()
|
||||
%code%{ RETVAL = const_cast<GCodeConfig*>(static_cast<const GCodeConfig*>(&THIS->config())); %};
|
||||
Ref<ExtrusionEntityCollection> skirt()
|
||||
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->skirt()); %};
|
||||
Ref<ExtrusionEntityCollection> brim()
|
||||
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->brim()); %};
|
||||
double total_used_filament()
|
||||
%code%{ RETVAL = THIS->print_statistics().total_used_filament; %};
|
||||
double total_extruded_volume()
|
||||
|
@ -70,18 +70,6 @@ ExPolygon* O_OBJECT_SLIC3R
|
||||
Ref<ExPolygon> O_OBJECT_SLIC3R_T
|
||||
Clone<ExPolygon> O_OBJECT_SLIC3R_T
|
||||
|
||||
ExtrusionEntityCollection* O_OBJECT_SLIC3R
|
||||
Ref<ExtrusionEntityCollection> O_OBJECT_SLIC3R_T
|
||||
Clone<ExtrusionEntityCollection> O_OBJECT_SLIC3R_T
|
||||
|
||||
ExtrusionPath* O_OBJECT_SLIC3R
|
||||
Ref<ExtrusionPath> O_OBJECT_SLIC3R_T
|
||||
Clone<ExtrusionPath> O_OBJECT_SLIC3R_T
|
||||
|
||||
ExtrusionLoop* O_OBJECT_SLIC3R
|
||||
Ref<ExtrusionLoop> O_OBJECT_SLIC3R_T
|
||||
Clone<ExtrusionLoop> O_OBJECT_SLIC3R_T
|
||||
|
||||
Surface* O_OBJECT_SLIC3R
|
||||
Ref<Surface> O_OBJECT_SLIC3R_T
|
||||
Clone<Surface> O_OBJECT_SLIC3R_T
|
||||
@ -119,12 +107,6 @@ Print* O_OBJECT_SLIC3R
|
||||
Ref<Print> O_OBJECT_SLIC3R_T
|
||||
Clone<Print> O_OBJECT_SLIC3R_T
|
||||
|
||||
LayerRegion* O_OBJECT_SLIC3R
|
||||
Ref<LayerRegion> O_OBJECT_SLIC3R_T
|
||||
|
||||
Layer* O_OBJECT_SLIC3R
|
||||
Ref<Layer> O_OBJECT_SLIC3R_T
|
||||
|
||||
Axis T_UV
|
||||
ExtrusionLoopRole T_UV
|
||||
ExtrusionRole T_UV
|
||||
@ -137,7 +119,6 @@ Lines T_ARRAYREF
|
||||
Polygons T_ARRAYREF
|
||||
Polylines T_ARRAYREF
|
||||
ExPolygons T_ARRAYREF
|
||||
ExtrusionPaths T_ARRAYREF
|
||||
Surfaces T_ARRAYREF
|
||||
|
||||
# we return these types whenever we want the items to be returned
|
||||
@ -149,7 +130,6 @@ ModelVolumePtrs* T_PTR_ARRAYREF_PTR
|
||||
ModelInstancePtrs* T_PTR_ARRAYREF_PTR
|
||||
PrintRegionPtrs* T_PTR_ARRAYREF_PTR
|
||||
PrintObjectPtrs* T_PTR_ARRAYREF_PTR
|
||||
LayerPtrs* T_PTR_ARRAYREF_PTR
|
||||
|
||||
# we return these types whenever we want the items to be returned
|
||||
# by reference and not marked ::Ref because they're newly allocated
|
||||
|
@ -53,15 +53,6 @@
|
||||
%typemap{Polygon*};
|
||||
%typemap{Ref<Polygon>}{simple};
|
||||
%typemap{Clone<Polygon>}{simple};
|
||||
%typemap{ExtrusionEntityCollection*};
|
||||
%typemap{Ref<ExtrusionEntityCollection>}{simple};
|
||||
%typemap{Clone<ExtrusionEntityCollection>}{simple};
|
||||
%typemap{ExtrusionPath*};
|
||||
%typemap{Ref<ExtrusionPath>}{simple};
|
||||
%typemap{Clone<ExtrusionPath>}{simple};
|
||||
%typemap{ExtrusionLoop*};
|
||||
%typemap{Ref<ExtrusionLoop>}{simple};
|
||||
%typemap{Clone<ExtrusionLoop>}{simple};
|
||||
%typemap{TriangleMesh*};
|
||||
%typemap{Ref<TriangleMesh>}{simple};
|
||||
%typemap{Clone<TriangleMesh>}{simple};
|
||||
@ -86,19 +77,12 @@
|
||||
%typemap{Ref<Print>}{simple};
|
||||
%typemap{Clone<Print>}{simple};
|
||||
|
||||
%typemap{LayerRegion*};
|
||||
%typemap{Ref<LayerRegion>}{simple};
|
||||
|
||||
%typemap{Layer*};
|
||||
%typemap{Ref<Layer>}{simple};
|
||||
|
||||
%typemap{Points};
|
||||
%typemap{Pointfs};
|
||||
%typemap{Lines};
|
||||
%typemap{Polygons};
|
||||
%typemap{Polylines};
|
||||
%typemap{ExPolygons};
|
||||
%typemap{ExtrusionPaths};
|
||||
%typemap{Surfaces};
|
||||
%typemap{Polygons*};
|
||||
%typemap{TriangleMesh*};
|
||||
|
Loading…
Reference in New Issue
Block a user