mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-02 06:50:40 +08:00
Merge remote-tracking branch 'samir/Samir55-support_porting' into test_merge_samir
# Conflicts: # src/CMakeLists.txt
This commit is contained in:
commit
575faf3231
@ -60,7 +60,7 @@ sub generate {
|
|||||||
$self->clip_with_shape($interface, $shape) if @$shape;
|
$self->clip_with_shape($interface, $shape) if @$shape;
|
||||||
|
|
||||||
# Propagate contact layers and interface layers downwards to generate
|
# Propagate contact layers and interface layers downwards to generate
|
||||||
# the main support layers.
|
# the main support layers.
|
||||||
my ($base) = $self->generate_base_layers($support_z, $contact, $interface, $top);
|
my ($base) = $self->generate_base_layers($support_z, $contact, $interface, $top);
|
||||||
$self->clip_with_object($base, $support_z, $object);
|
$self->clip_with_object($base, $support_z, $object);
|
||||||
$self->clip_with_shape($base, $shape) if @$shape;
|
$self->clip_with_shape($base, $shape) if @$shape;
|
||||||
@ -108,7 +108,7 @@ sub contact_area {
|
|||||||
|
|
||||||
# determine contact areas
|
# determine contact areas
|
||||||
my %contact = (); # contact_z => [ polygons ]
|
my %contact = (); # contact_z => [ polygons ]
|
||||||
my %overhang = (); # contact_z => [ polygons ] - this stores the actual overhang supported by each contact layer
|
my %overhang = (); # contact_z => [ polygons ] - this stores the actual overhang supported by each contact layer
|
||||||
for my $layer_id (0 .. $#{$object->layers}) {
|
for my $layer_id (0 .. $#{$object->layers}) {
|
||||||
# note $layer_id might != $layer->id when raft_layers > 0
|
# note $layer_id might != $layer->id when raft_layers > 0
|
||||||
# so $layer_id == 0 means first object layer
|
# so $layer_id == 0 means first object layer
|
||||||
@ -224,7 +224,7 @@ sub contact_area {
|
|||||||
|
|
||||||
# Get all perimeters as polylines.
|
# Get all perimeters as polylines.
|
||||||
# TODO: split_at_first_point() (called by as_polyline() for ExtrusionLoops)
|
# TODO: split_at_first_point() (called by as_polyline() for ExtrusionLoops)
|
||||||
# could split a bridge mid-way
|
# could split a bridge mid-way
|
||||||
my @overhang_perimeters = map $_->as_polyline, @{$layerm->perimeters->flatten};
|
my @overhang_perimeters = map $_->as_polyline, @{$layerm->perimeters->flatten};
|
||||||
|
|
||||||
# Only consider the overhang parts of such perimeters,
|
# Only consider the overhang parts of such perimeters,
|
||||||
@ -374,7 +374,7 @@ sub object_top {
|
|||||||
# we considered)
|
# we considered)
|
||||||
my $min_top = min(keys %top) // max(keys %$contact);
|
my $min_top = min(keys %top) // max(keys %$contact);
|
||||||
# use <= instead of just < because otherwise we'd ignore any contact regions
|
# use <= instead of just < because otherwise we'd ignore any contact regions
|
||||||
# having the same Z of top layers
|
# having the same Z of top layers
|
||||||
push @$projection, map @{$contact->{$_}}, grep { $_ > $layer->print_z && $_ <= $min_top } keys %$contact;
|
push @$projection, map @{$contact->{$_}}, grep { $_ > $layer->print_z && $_ <= $min_top } keys %$contact;
|
||||||
|
|
||||||
# now find whether any projection falls onto this top surface
|
# now find whether any projection falls onto this top surface
|
||||||
@ -511,7 +511,7 @@ sub generate_bottom_interface_layers {
|
|||||||
my $interface_layers = 0;
|
my $interface_layers = 0;
|
||||||
|
|
||||||
# loop through support layers until we find the one(s) right above the top
|
# loop through support layers until we find the one(s) right above the top
|
||||||
# surface
|
# surface
|
||||||
foreach my $layer_id (0 .. $#$support_z) {
|
foreach my $layer_id (0 .. $#$support_z) {
|
||||||
my $z = $support_z->[$layer_id];
|
my $z = $support_z->[$layer_id];
|
||||||
next unless $z > $top_z;
|
next unless $z > $top_z;
|
||||||
@ -581,7 +581,7 @@ sub generate_base_layers {
|
|||||||
|
|
||||||
# This method removes object silhouette from support material
|
# This method removes object silhouette from support material
|
||||||
# (it's used with interface and base only). It removes a bit more,
|
# (it's used with interface and base only). It removes a bit more,
|
||||||
# leaving a thin gap between object and support in the XY plane.
|
# leaving a thin gap between object and support in the XY plane.
|
||||||
sub clip_with_object {
|
sub clip_with_object {
|
||||||
my ($self, $support, $support_z, $object) = @_;
|
my ($self, $support, $support_z, $object) = @_;
|
||||||
|
|
||||||
@ -595,7 +595,7 @@ sub clip_with_object {
|
|||||||
|
|
||||||
# $layer->slices contains the full shape of layer, thus including
|
# $layer->slices contains the full shape of layer, thus including
|
||||||
# perimeter's width. $support contains the full shape of support
|
# perimeter's width. $support contains the full shape of support
|
||||||
# material, thus including the width of its foremost extrusion.
|
# material, thus including the width of its foremost extrusion.
|
||||||
# We leave a gap equal to a full extrusion width.
|
# We leave a gap equal to a full extrusion width.
|
||||||
$support->{$i} = diff(
|
$support->{$i} = diff(
|
||||||
$support->{$i},
|
$support->{$i},
|
||||||
@ -825,7 +825,7 @@ sub generate_toolpaths {
|
|||||||
$base_flow = $self->first_layer_flow;
|
$base_flow = $self->first_layer_flow;
|
||||||
|
|
||||||
# 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
|
||||||
$filler->set_min_spacing($base_flow->spacing);
|
$filler->set_min_spacing($base_flow->spacing);
|
||||||
|
|
||||||
# subtract brim so that it goes around the object fully (and support gets its own brim)
|
# subtract brim so that it goes around the object fully (and support gets its own brim)
|
||||||
|
@ -89,7 +89,7 @@ include_directories(${LIBDIR}/poly2tri/common)
|
|||||||
add_library(ZipArchive STATIC
|
add_library(ZipArchive STATIC
|
||||||
${LIBDIR}/Zip/ZipArchive.cpp
|
${LIBDIR}/Zip/ZipArchive.cpp
|
||||||
)
|
)
|
||||||
|
target_compile_features(ZipArchive PUBLIC cxx_std_11)
|
||||||
|
|
||||||
add_library(libslic3r STATIC
|
add_library(libslic3r STATIC
|
||||||
${LIBDIR}/libslic3r/BoundingBox.cpp
|
${LIBDIR}/libslic3r/BoundingBox.cpp
|
||||||
@ -146,12 +146,11 @@ add_library(libslic3r STATIC
|
|||||||
${LIBDIR}/libslic3r/SurfaceCollection.cpp
|
${LIBDIR}/libslic3r/SurfaceCollection.cpp
|
||||||
${LIBDIR}/libslic3r/SVG.cpp
|
${LIBDIR}/libslic3r/SVG.cpp
|
||||||
${LIBDIR}/libslic3r/TriangleMesh.cpp
|
${LIBDIR}/libslic3r/TriangleMesh.cpp
|
||||||
|
${LIBDIR}/libslic3r/SupportMaterial.cpp
|
||||||
${LIBDIR}/libslic3r/utils.cpp
|
${LIBDIR}/libslic3r/utils.cpp
|
||||||
)
|
)
|
||||||
target_compile_features(libslic3r PUBLIC cxx_std_11)
|
target_compile_features(libslic3r PUBLIC cxx_std_11)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add_library(BSpline STATIC
|
add_library(BSpline STATIC
|
||||||
${LIBDIR}/BSpline/BSpline.cpp
|
${LIBDIR}/BSpline/BSpline.cpp
|
||||||
)
|
)
|
||||||
@ -172,6 +171,8 @@ add_library(expat STATIC
|
|||||||
${LIBDIR}/expat/xmlrole.c
|
${LIBDIR}/expat/xmlrole.c
|
||||||
${LIBDIR}/expat/xmltok.c
|
${LIBDIR}/expat/xmltok.c
|
||||||
)
|
)
|
||||||
|
target_compile_features(clipper PUBLIC cxx_std_11)
|
||||||
|
|
||||||
add_library(polypartition STATIC ${LIBDIR}/polypartition.cpp)
|
add_library(polypartition STATIC ${LIBDIR}/polypartition.cpp)
|
||||||
add_library(poly2tri STATIC
|
add_library(poly2tri STATIC
|
||||||
${LIBDIR}/poly2tri/common/shapes.cc
|
${LIBDIR}/poly2tri/common/shapes.cc
|
||||||
@ -200,6 +201,7 @@ set(SLIC3R_TEST_SOURCES
|
|||||||
${TESTDIR}/test_data.cpp
|
${TESTDIR}/test_data.cpp
|
||||||
${TESTDIR}/libslic3r/test_trianglemesh.cpp
|
${TESTDIR}/libslic3r/test_trianglemesh.cpp
|
||||||
${TESTDIR}/libslic3r/test_config.cpp
|
${TESTDIR}/libslic3r/test_config.cpp
|
||||||
|
${TESTDIR}/libslic3r/test_support_material.cpp
|
||||||
)
|
)
|
||||||
add_executable(slic3r slic3r.cpp)
|
add_executable(slic3r slic3r.cpp)
|
||||||
#set_target_properties(slic3r PROPERTIES LINK_SEARCH_START_STATIC 1)
|
#set_target_properties(slic3r PROPERTIES LINK_SEARCH_START_STATIC 1)
|
||||||
|
296
src/test/libslic3r/test_support_material.cpp
Normal file
296
src/test/libslic3r/test_support_material.cpp
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
//#include <catch.hpp>
|
||||||
|
#include <libslic3r/IO.hpp>
|
||||||
|
#include <libslic3r/GCodeReader.hpp>
|
||||||
|
#include "/home/ahmedsamir/Work/SamirSlic3r/Slic3r/build/external/Catch/include/catch.hpp"
|
||||||
|
|
||||||
|
#include "libslic3r.h"
|
||||||
|
#include "TriangleMesh.hpp"
|
||||||
|
#include "Model.hpp"
|
||||||
|
#include "SupportMaterial.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Slic3r;
|
||||||
|
|
||||||
|
void test_1_checks(Print &print, bool &a, bool &b, bool &c, bool &d);
|
||||||
|
bool test_6_checks(Print &print);
|
||||||
|
|
||||||
|
// Testing 0.1: supports material member functions.
|
||||||
|
TEST_CASE("", "")
|
||||||
|
{
|
||||||
|
// Create a mesh & modelObject.
|
||||||
|
TriangleMesh mesh = TriangleMesh::make_cube(20, 20, 20);
|
||||||
|
|
||||||
|
// Create modelObject.
|
||||||
|
Model model = Model();
|
||||||
|
ModelObject *object = model.add_object();
|
||||||
|
object->add_volume(mesh);
|
||||||
|
model.add_default_instances();
|
||||||
|
|
||||||
|
// Align to origin.
|
||||||
|
model.align_instances_to_origin();
|
||||||
|
|
||||||
|
// Create Print.
|
||||||
|
Print print = Print();
|
||||||
|
vector<coordf_t> contact_z = {1.9};
|
||||||
|
vector<coordf_t> top_z = {1.1};
|
||||||
|
print.default_object_config.support_material = 1;
|
||||||
|
print.default_object_config.set_deserialize("raft_layers", "3");
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
print.objects.front()->_slice();
|
||||||
|
|
||||||
|
|
||||||
|
SupportMaterial *support = print.objects.front()->_support_material();
|
||||||
|
|
||||||
|
support->generate(print.objects.front());
|
||||||
|
REQUIRE(print.objects.front()->support_layer_count() == 3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 1.
|
||||||
|
SCENARIO("SupportMaterial: support_layers_z and contact_distance")
|
||||||
|
{
|
||||||
|
GIVEN("A print object having one modelObject") {
|
||||||
|
// Create a mesh & modelObject.
|
||||||
|
TriangleMesh mesh = TriangleMesh::make_cube(20, 20, 20);
|
||||||
|
|
||||||
|
// Create modelObject.
|
||||||
|
Model model = Model();
|
||||||
|
ModelObject *object = model.add_object();
|
||||||
|
object->add_volume(mesh);
|
||||||
|
model.add_default_instances();
|
||||||
|
|
||||||
|
// Align to origin.
|
||||||
|
model.align_instances_to_origin();
|
||||||
|
// Create Print.
|
||||||
|
Print print = Print();
|
||||||
|
print.default_object_config.set_deserialize("support_material", "1");
|
||||||
|
|
||||||
|
WHEN("First layer height = 0.4") {
|
||||||
|
print.default_object_config.set_deserialize("layer_height", "0.2");
|
||||||
|
print.default_object_config.set_deserialize("first_layer_height", "0.4");
|
||||||
|
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
print.objects.front()->_slice();
|
||||||
|
bool a, b, c, d;
|
||||||
|
|
||||||
|
test_1_checks(print, a, b, c, d);
|
||||||
|
THEN("First layer height is honored") {
|
||||||
|
REQUIRE(a == true);
|
||||||
|
}
|
||||||
|
THEN("No null or negative support layers") {
|
||||||
|
REQUIRE(b == true);
|
||||||
|
}
|
||||||
|
THEN("No layers thicker than nozzle diameter") {
|
||||||
|
REQUIRE(c == true);
|
||||||
|
}
|
||||||
|
THEN("Layers above top surfaces are spaced correctly") {
|
||||||
|
REQUIRE(d == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("Layer height = 0.2 and, first layer height = 0.3") {
|
||||||
|
print.default_object_config.set_deserialize("layer_height", "0.2");
|
||||||
|
print.default_object_config.set_deserialize("first_layer_height", "0.3");
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
print.objects.front()->_slice();
|
||||||
|
bool a, b, c, d;
|
||||||
|
|
||||||
|
test_1_checks(print, a, b, c, d);
|
||||||
|
THEN("First layer height is honored") {
|
||||||
|
REQUIRE(a == true);
|
||||||
|
}
|
||||||
|
THEN("No null or negative support layers") {
|
||||||
|
REQUIRE(b == true);
|
||||||
|
}
|
||||||
|
THEN("No layers thicker than nozzle diameter") {
|
||||||
|
REQUIRE(c == true);
|
||||||
|
}
|
||||||
|
THEN("Layers above top surfaces are spaced correctly") {
|
||||||
|
REQUIRE(d == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WHEN("Layer height = nozzle_diameter[0]") {
|
||||||
|
print.default_object_config.set_deserialize("layer_height", "0.2");
|
||||||
|
print.default_object_config.set_deserialize("first_layer_height", "0.3");
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
print.objects.front()->_slice();
|
||||||
|
bool a, b, c, d;
|
||||||
|
|
||||||
|
test_1_checks(print, a, b, c, d);
|
||||||
|
THEN("First layer height is honored") {
|
||||||
|
REQUIRE(a == true);
|
||||||
|
}
|
||||||
|
THEN("No null or negative support layers") {
|
||||||
|
REQUIRE(b == true);
|
||||||
|
}
|
||||||
|
THEN("No layers thicker than nozzle diameter") {
|
||||||
|
REQUIRE(c == true);
|
||||||
|
}
|
||||||
|
THEN("Layers above top surfaces are spaced correctly") {
|
||||||
|
REQUIRE(d == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 8.
|
||||||
|
TEST_CASE("SupportMaterial: forced support is generated", "")
|
||||||
|
{
|
||||||
|
// Create a mesh & modelObject.
|
||||||
|
TriangleMesh mesh = TriangleMesh::make_cube(20, 20, 20);
|
||||||
|
|
||||||
|
Model model = Model();
|
||||||
|
ModelObject *object = model.add_object();
|
||||||
|
object->add_volume(mesh);
|
||||||
|
model.add_default_instances();
|
||||||
|
model.align_instances_to_origin();
|
||||||
|
|
||||||
|
Print print = Print();
|
||||||
|
|
||||||
|
vector<coordf_t> contact_z = {1.9};
|
||||||
|
vector<coordf_t> top_z = {1.1};
|
||||||
|
print.default_object_config.support_material_enforce_layers = 100;
|
||||||
|
print.default_object_config.support_material = 0;
|
||||||
|
print.default_object_config.layer_height = 0.2;
|
||||||
|
print.default_object_config.set_deserialize("first_layer_height", "0.3");
|
||||||
|
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
print.objects.front()->_slice();
|
||||||
|
|
||||||
|
SupportMaterial *support = print.objects.front()->_support_material();
|
||||||
|
auto support_z = support->support_layers_z(contact_z, top_z, print.default_object_config.layer_height);
|
||||||
|
|
||||||
|
bool check = true;
|
||||||
|
for (size_t i = 1; i < support_z.size(); i++) {
|
||||||
|
if (support_z[i] - support_z[i - 1] <= 0)
|
||||||
|
check = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(check == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 6.
|
||||||
|
SCENARIO("SupportMaterial: Checking bridge speed")
|
||||||
|
{
|
||||||
|
GIVEN("Print object") {
|
||||||
|
// Create a mesh & modelObject.
|
||||||
|
TriangleMesh mesh = TriangleMesh::make_cube(20, 20, 20);
|
||||||
|
|
||||||
|
Model model = Model();
|
||||||
|
ModelObject *object = model.add_object();
|
||||||
|
object->add_volume(mesh);
|
||||||
|
model.add_default_instances();
|
||||||
|
model.align_instances_to_origin();
|
||||||
|
|
||||||
|
Print print = Print();
|
||||||
|
print.config.brim_width = 0;
|
||||||
|
print.config.skirts = 0;
|
||||||
|
print.config.skirts = 0;
|
||||||
|
print.default_object_config.support_material = 1;
|
||||||
|
print.default_region_config.top_solid_layers = 0; // so that we don't have the internal bridge over infill.
|
||||||
|
print.default_region_config.bridge_speed = 99;
|
||||||
|
print.config.cooling = 0;
|
||||||
|
print.config.set_deserialize("first_layer_speed", "100%");
|
||||||
|
|
||||||
|
WHEN("support_material_contact_distance = 0.2") {
|
||||||
|
print.default_object_config.support_material_contact_distance = 0.2;
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
|
||||||
|
bool check = test_6_checks(print);
|
||||||
|
REQUIRE(check == true); // bridge speed is used.
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("support_material_contact_distance = 0") {
|
||||||
|
print.default_object_config.support_material_contact_distance = 0;
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
|
||||||
|
bool check = test_6_checks(print);
|
||||||
|
REQUIRE(check == true); // bridge speed is not used.
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("support_material_contact_distance = 0.2 & raft_layers = 5") {
|
||||||
|
print.default_object_config.support_material_contact_distance = 0.2;
|
||||||
|
print.default_object_config.raft_layers = 5;
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
|
||||||
|
bool check = test_6_checks(print);
|
||||||
|
REQUIRE(check == true); // bridge speed is used.
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("support_material_contact_distance = 0 & raft_layers = 5") {
|
||||||
|
print.default_object_config.support_material_contact_distance = 0;
|
||||||
|
print.default_object_config.raft_layers = 5;
|
||||||
|
print.add_model_object(model.objects[0]);
|
||||||
|
|
||||||
|
bool check = test_6_checks(print);
|
||||||
|
|
||||||
|
REQUIRE(check == true); // bridge speed is not used.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_1_checks(Print &print, bool &a, bool &b, bool &c, bool &d)
|
||||||
|
{
|
||||||
|
vector<coordf_t> contact_z = {1.9};
|
||||||
|
vector<coordf_t> top_z = {1.1};
|
||||||
|
|
||||||
|
SupportMaterial *support = print.objects.front()->_support_material();
|
||||||
|
|
||||||
|
vector<coordf_t>
|
||||||
|
support_z = support->support_layers_z(contact_z, top_z, print.default_object_config.layer_height);
|
||||||
|
|
||||||
|
a = (support_z[0] == print.default_object_config.first_layer_height.value);
|
||||||
|
|
||||||
|
b = true;
|
||||||
|
for (size_t i = 1; i < support_z.size(); ++i)
|
||||||
|
if (support_z[i] - support_z[i - 1] <= 0) b = false;
|
||||||
|
|
||||||
|
|
||||||
|
c = true;
|
||||||
|
for (size_t i = 1; i < support_z.size(); ++i)
|
||||||
|
if (support_z[i] - support_z[i - 1] > print.config.nozzle_diameter.get_at(0) + EPSILON)
|
||||||
|
c = false;
|
||||||
|
|
||||||
|
coordf_t expected_top_spacing = support
|
||||||
|
->contact_distance(print.default_object_config.layer_height,
|
||||||
|
print.config.nozzle_diameter.get_at(0));
|
||||||
|
|
||||||
|
bool wrong_top_spacing = 0;
|
||||||
|
for (coordf_t top_z_el : top_z) {
|
||||||
|
// find layer index of this top surface.
|
||||||
|
size_t layer_id = -1;
|
||||||
|
for (size_t i = 0; i < support_z.size(); i++) {
|
||||||
|
if (abs(support_z[i] - top_z_el) < EPSILON) {
|
||||||
|
layer_id = i;
|
||||||
|
i = static_cast<int>(support_z.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that first support layer above this top surface (or the next one) is spaced with nozzle diameter
|
||||||
|
if (abs(support_z[layer_id + 1] - support_z[layer_id] - expected_top_spacing) > EPSILON
|
||||||
|
&& abs(support_z[layer_id + 2] - support_z[layer_id] - expected_top_spacing) > EPSILON) {
|
||||||
|
wrong_top_spacing = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d = !wrong_top_spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
bool test_6_checks(Print &print)
|
||||||
|
{
|
||||||
|
bool has_bridge_speed = true;
|
||||||
|
|
||||||
|
// Pre-Processing.
|
||||||
|
PrintObject *print_object = print.objects.front();
|
||||||
|
print_object->_infill();
|
||||||
|
SupportMaterial *support_material = print.objects.front()->_support_material();
|
||||||
|
support_material->generate(print_object);
|
||||||
|
// TODO but not needed in test 6 (make brims and make skirts).
|
||||||
|
|
||||||
|
// Exporting gcode.
|
||||||
|
// TODO validation found in Simple.pm
|
||||||
|
|
||||||
|
|
||||||
|
return has_bridge_speed;
|
||||||
|
}
|
@ -15,6 +15,7 @@
|
|||||||
#include "PlaceholderParser.hpp"
|
#include "PlaceholderParser.hpp"
|
||||||
#include "SlicingAdaptive.hpp"
|
#include "SlicingAdaptive.hpp"
|
||||||
#include "LayerHeightSpline.hpp"
|
#include "LayerHeightSpline.hpp"
|
||||||
|
#include "SupportMaterial.hpp"
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ class InvalidObjectException : public std::exception {};
|
|||||||
class Print;
|
class Print;
|
||||||
class PrintObject;
|
class PrintObject;
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
|
class SupportMaterial;
|
||||||
|
|
||||||
// Print step IDs for keeping track of the print state.
|
// Print step IDs for keeping track of the print state.
|
||||||
enum PrintStep {
|
enum PrintStep {
|
||||||
@ -132,6 +134,8 @@ class PrintObject
|
|||||||
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
||||||
void delete_layer(int idx);
|
void delete_layer(int idx);
|
||||||
|
|
||||||
|
SupportMaterial* _support_material();
|
||||||
|
Flow _support_material_flow(FlowRole role = frSupportMaterial);
|
||||||
size_t support_layer_count() const;
|
size_t support_layer_count() const;
|
||||||
void clear_support_layers();
|
void clear_support_layers();
|
||||||
SupportLayer* get_support_layer(int idx) { return this->support_layers.at(idx); };
|
SupportLayer* get_support_layer(int idx) { return this->support_layers.at(idx); };
|
||||||
@ -232,7 +236,6 @@ class Print
|
|||||||
void auto_assign_extruders(ModelObject* model_object) const;
|
void auto_assign_extruders(ModelObject* model_object) const;
|
||||||
std::string output_filename();
|
std::string output_filename();
|
||||||
std::string output_filepath(const std::string &path);
|
std::string output_filepath(const std::string &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clear_regions();
|
void clear_regions();
|
||||||
void delete_region(size_t idx);
|
void delete_region(size_t idx);
|
||||||
|
@ -1095,4 +1095,55 @@ PrintObject::_infill()
|
|||||||
this->state.set_done(posInfill);
|
this->state.set_done(posInfill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SupportMaterial *
|
||||||
|
PrintObject::_support_material()
|
||||||
|
{
|
||||||
|
// TODO what does this line do //= FLOW_ROLE_SUPPORT_MATERIAL;
|
||||||
|
Flow first_layer_flow = Flow::new_from_config_width(
|
||||||
|
frSupportMaterial,
|
||||||
|
print()->config
|
||||||
|
.first_layer_extrusion_width, // check why this line is put || config.support_material_extrusion_width,
|
||||||
|
static_cast<float>(print()->config.nozzle_diameter.get_at(static_cast<size_t>(
|
||||||
|
config.support_material_extruder
|
||||||
|
- 1))), // Check why this is put in perl "// $self->print->config->nozzle_diameter->[0]"
|
||||||
|
static_cast<float>(config.get_abs_value("first_layer_height")),
|
||||||
|
0 // No bridge flow ratio.
|
||||||
|
);
|
||||||
|
|
||||||
|
return new SupportMaterial(
|
||||||
|
&print()->config,
|
||||||
|
&config,
|
||||||
|
first_layer_flow,
|
||||||
|
_support_material_flow(),
|
||||||
|
_support_material_flow(frSupportMaterialInterface)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Flow
|
||||||
|
PrintObject::_support_material_flow(FlowRole role)
|
||||||
|
{
|
||||||
|
// Create support flow.
|
||||||
|
int extruder =
|
||||||
|
(role == frSupportMaterial) ?
|
||||||
|
config.support_material_extruder.value : config
|
||||||
|
.support_material_interface_extruder.value;
|
||||||
|
|
||||||
|
auto width = config.support_material_extrusion_width; // || config.extrusion_width;
|
||||||
|
|
||||||
|
if (role == frSupportMaterialInterface)
|
||||||
|
width = config.support_material_interface_extrusion_width; // || width;
|
||||||
|
|
||||||
|
// We use a bogus layer_height because we use the same flow for all
|
||||||
|
// support material layers.
|
||||||
|
Flow support_flow = Flow::new_from_config_width(
|
||||||
|
role,
|
||||||
|
width,
|
||||||
|
static_cast<float>(print()->config.nozzle_diameter
|
||||||
|
.get_at(static_cast<size_t>(extruder - 1))), // Check this line $self->print->config->nozzle_diameter->[0].
|
||||||
|
static_cast<float>(config.layer_height.value),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
return support_flow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
1225
xs/src/libslic3r/SupportMaterial.cpp
Normal file
1225
xs/src/libslic3r/SupportMaterial.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,164 @@
|
|||||||
#ifndef slic3r_SupportMaterial_hpp_
|
#ifndef slic3r_SupportMaterial_hpp_
|
||||||
#define slic3r_SupportMaterial_hpp_
|
#define slic3r_SupportMaterial_hpp_
|
||||||
|
|
||||||
namespace Slic3r {
|
#include <numeric>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "libslic3r.h"
|
||||||
|
#include "PrintConfig.hpp"
|
||||||
|
#include "Flow.hpp"
|
||||||
|
#include "Layer.hpp"
|
||||||
|
#include "Geometry.hpp"
|
||||||
|
#include "Print.hpp"
|
||||||
|
#include "ClipperUtils.hpp"
|
||||||
|
#include "ExPolygon.hpp"
|
||||||
|
#include "SVG.hpp"
|
||||||
|
#include <libslic3r/Fill/Fill.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Slic3r
|
||||||
|
{
|
||||||
|
|
||||||
// how much we extend support around the actual contact area
|
// how much we extend support around the actual contact area
|
||||||
constexpr coordf_t SUPPORT_MATERIAL_MARGIN = 1.5;
|
constexpr coordf_t SUPPORT_MATERIAL_MARGIN = 1.5;
|
||||||
|
|
||||||
|
constexpr coordf_t MARGIN_STEP = SUPPORT_MATERIAL_MARGIN / 3;
|
||||||
|
|
||||||
|
constexpr coordf_t PILLAR_SIZE = 2.5;
|
||||||
|
|
||||||
|
constexpr coordf_t PILLAR_SPACING = 10;
|
||||||
|
|
||||||
|
/// Struct for carrying the toolpaths parameters needed for each thread.
|
||||||
|
struct toolpaths_params
|
||||||
|
{
|
||||||
|
int contact_loops;
|
||||||
|
coordf_t circle_radius;
|
||||||
|
coordf_t circle_distance;
|
||||||
|
Polygon circle;
|
||||||
|
SupportMaterialPattern pattern;
|
||||||
|
vector<int> angles;
|
||||||
|
double interface_angle{};
|
||||||
|
double interface_spacing{};
|
||||||
|
float interface_density{};
|
||||||
|
double support_spacing{};
|
||||||
|
double support_density{};
|
||||||
|
|
||||||
|
toolpaths_params(int contact_loops = 0,
|
||||||
|
coordf_t circle_radius = 0,
|
||||||
|
coordf_t circle_distance = 0,
|
||||||
|
const Polygon &circle = Polygon(),
|
||||||
|
const SupportMaterialPattern &pattern = SupportMaterialPattern(),
|
||||||
|
const vector<int> &angles = vector<int>())
|
||||||
|
: contact_loops(contact_loops),
|
||||||
|
circle_radius(circle_radius),
|
||||||
|
circle_distance(circle_distance),
|
||||||
|
circle(circle),
|
||||||
|
pattern(pattern),
|
||||||
|
angles(angles)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SupportMaterial
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend PrintObject;
|
||||||
|
|
||||||
|
PrintConfig *config; ///< The print config
|
||||||
|
PrintObjectConfig *object_config; ///< The object print config.
|
||||||
|
Flow flow; ///< The intermediate layers print flow.
|
||||||
|
Flow first_layer_flow; ///< The first (base) layers print flow.
|
||||||
|
Flow interface_flow; ///< The interface layers print flow.
|
||||||
|
|
||||||
|
/// Generate the extrusions paths for the support matterial generated for the given print object.
|
||||||
|
void generate_toolpaths(PrintObject *object,
|
||||||
|
map<coordf_t, Polygons> overhang,
|
||||||
|
map<coordf_t, Polygons> contact,
|
||||||
|
map<int, Polygons> interface,
|
||||||
|
map<int, Polygons> base);
|
||||||
|
|
||||||
|
/// Generate support material for the given print object.
|
||||||
|
void generate(PrintObject *object);
|
||||||
|
|
||||||
|
/// Generate the support layers slicing z coordinates.
|
||||||
|
vector<coordf_t> support_layers_z(vector<coordf_t> contact_z,
|
||||||
|
vector<coordf_t> top_z,
|
||||||
|
coordf_t max_object_layer_height);
|
||||||
|
|
||||||
|
pair<map<coordf_t, Polygons>, map<coordf_t, Polygons>> contact_area(PrintObject *object);
|
||||||
|
|
||||||
|
map<coordf_t, Polygons> object_top(PrintObject *object, map<coordf_t, Polygons> *contact);
|
||||||
|
|
||||||
|
void generate_pillars_shape(const map<coordf_t, Polygons> &contact,
|
||||||
|
const vector<coordf_t> &support_z,
|
||||||
|
map<int, Polygons> &shape);
|
||||||
|
|
||||||
|
map<int, Polygons> generate_base_layers(vector<coordf_t> support_z,
|
||||||
|
map<coordf_t, Polygons> contact,
|
||||||
|
map<int, Polygons> interface,
|
||||||
|
map<coordf_t, Polygons> top);
|
||||||
|
|
||||||
|
map<int, Polygons> generate_interface_layers(vector<coordf_t> support_z,
|
||||||
|
map<coordf_t, Polygons> contact,
|
||||||
|
map<coordf_t, Polygons> top);
|
||||||
|
|
||||||
|
void generate_bottom_interface_layers(const vector<coordf_t> &support_z,
|
||||||
|
map<int, Polygons> &base,
|
||||||
|
map<coordf_t, Polygons> &top,
|
||||||
|
map<int, Polygons> &interface);
|
||||||
|
|
||||||
|
coordf_t contact_distance(coordf_t layer_height, coordf_t nozzle_diameter);
|
||||||
|
|
||||||
|
/// This method returns the indices of the layers overlapping with the given one.
|
||||||
|
vector<int> overlapping_layers(int layer_idx, const vector<coordf_t> &support_z);
|
||||||
|
|
||||||
|
void clip_with_shape(map<int, Polygons> &support, map<int, Polygons> &shape);
|
||||||
|
|
||||||
|
// This method removes object silhouette from support material
|
||||||
|
// (it's used with interface and base only). It removes a bit more,
|
||||||
|
// leaving a thin gap between object and support in the XY plane.
|
||||||
|
void clip_with_object(map<int, Polygons> &support, vector<coordf_t> support_z, PrintObject &object);
|
||||||
|
|
||||||
|
void process_layer(int layer_id, toolpaths_params params);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// SupportMaterial is generated by PrintObject.
|
||||||
|
SupportMaterial(PrintConfig *print_config,
|
||||||
|
PrintObjectConfig *print_object_config,
|
||||||
|
Flow flow,
|
||||||
|
Flow first_layer_flow,
|
||||||
|
Flow interface_flow)
|
||||||
|
: config(print_config),
|
||||||
|
object_config(print_object_config),
|
||||||
|
flow(Flow(0, 0, 0)),
|
||||||
|
first_layer_flow(Flow(0, 0, 0)),
|
||||||
|
interface_flow(Flow(0, 0, 0)),
|
||||||
|
object(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Get the maximum layer height given a print object.
|
||||||
|
coordf_t get_max_layer_height(PrintObject *object);
|
||||||
|
|
||||||
|
// (Deprecated) use append_to instead
|
||||||
|
void append_polygons(Polygons &dst, Polygons &src);
|
||||||
|
|
||||||
|
// Return polygon vector given a vector of surfaces.
|
||||||
|
Polygons p(SurfacesPtr &surfaces);
|
||||||
|
|
||||||
|
vector<coordf_t> get_keys_sorted(map<coordf_t, Polygons> _map);
|
||||||
|
|
||||||
|
Polygon create_circle(coordf_t radius);
|
||||||
|
|
||||||
|
// Used during generate_toolpaths function.
|
||||||
|
PrintObject *object;
|
||||||
|
map<coordf_t, Polygons> overhang;
|
||||||
|
map<coordf_t, Polygons> contact;
|
||||||
|
map<int, Polygons> interface;
|
||||||
|
map<int, Polygons> base;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user