mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-16 18:11:49 +08:00
restore most loop orientation to ccw.
add test_model and test_print tests. Work is needed for them
This commit is contained in:
parent
4e1e4cff73
commit
c03564f218
@ -89,7 +89,7 @@ Then `cd` into the `deps` directory and use these commands to build:
|
|||||||
You can also use the Visual Studio GUI or other generators as mentioned above.
|
You can also use the Visual Studio GUI or other generators as mentioned above.
|
||||||
|
|
||||||
The `DESTDIR` option is the location where the bundle will be installed.
|
The `DESTDIR` option is the location where the bundle will be installed.
|
||||||
This may be customized. If you leave it empty, the `DESTDIR` will be places inside the same `build` directory.
|
This may be customized. If you leave it empty, the `DESTDIR` will be places inside the same `build` directory. For using your newly compile deps, use -DCMAKE_INSTALL_PREFIX=<path_of_build\destdir\usr\local> in your cmake command for slic3r.
|
||||||
|
|
||||||
Warning: If the `build` directory is nested too deep inside other folders, various file paths during the build
|
Warning: If the `build` directory is nested too deep inside other folders, various file paths during the build
|
||||||
become too long and the build might fail due to file writing errors. For this reason, it is recommended to
|
become too long and the build might fail due to file writing errors. For this reason, it is recommended to
|
||||||
|
@ -473,7 +473,10 @@ inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons
|
|||||||
ExtrusionPath path(role, mm3_per_mm, width, height);
|
ExtrusionPath path(role, mm3_per_mm, width, height);
|
||||||
path.polyline.points = std::move(poly.points);
|
path.polyline.points = std::move(poly.points);
|
||||||
path.polyline.points.push_back(path.polyline.points.front());
|
path.polyline.points.push_back(path.polyline.points.front());
|
||||||
dst.emplace_back(new ExtrusionLoop(std::move(path)));
|
ExtrusionLoop *loop = new ExtrusionLoop(std::move(path));
|
||||||
|
//default to ccw
|
||||||
|
loop->make_counter_clockwise();
|
||||||
|
dst.emplace_back(loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loops.clear();
|
loops.clear();
|
||||||
|
@ -2022,6 +2022,17 @@ std::vector<float> polygon_angles_at_vertices(const Polygon &polygon, const std:
|
|||||||
|
|
||||||
std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::string &description, double speed, std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid)
|
std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::string &description, double speed, std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid)
|
||||||
{
|
{
|
||||||
|
#if DEBUG_EXTRUSION_OUTPUT
|
||||||
|
std::cout << "extrude loop_" << (original_loop.polygon().is_counter_clockwise() ? "ccw" : "clw") << ": ";
|
||||||
|
for (const ExtrusionPath &path : original_loop.paths) {
|
||||||
|
std::cout << ", path{ ";
|
||||||
|
for (const Point &pt : path.polyline.points) {
|
||||||
|
std::cout << ", " << floor(100 * unscale<double>(pt.x())) / 100.0 << ":" << floor(100 * unscale<double>(pt.y())) / 100.0;
|
||||||
|
}
|
||||||
|
std::cout << "}";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
#endif
|
||||||
// get a copy; don't modify the orientation of the original loop object otherwise
|
// get a copy; don't modify the orientation of the original loop object otherwise
|
||||||
// next copies (if any) would not detect the correct orientation
|
// next copies (if any) would not detect the correct orientation
|
||||||
ExtrusionLoop loop = original_loop;
|
ExtrusionLoop loop = original_loop;
|
||||||
|
@ -670,45 +670,49 @@ void ModelObject::assign_new_unique_ids_recursive()
|
|||||||
// return new ModelObject(parent, *this, true);
|
// return new ModelObject(parent, *this, true);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
ModelVolume* ModelObject::add_volume(const TriangleMesh &mesh)
|
ModelVolume* ModelObject::add_volume(const TriangleMesh &mesh, bool centered)
|
||||||
{
|
{
|
||||||
ModelVolume* v = new ModelVolume(this, mesh);
|
ModelVolume* v = new ModelVolume(this, mesh);
|
||||||
this->volumes.push_back(v);
|
this->volumes.push_back(v);
|
||||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||||
v->center_geometry();
|
if(centered)
|
||||||
|
v->center_geometry();
|
||||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||||
this->invalidate_bounding_box();
|
this->invalidate_bounding_box();
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume* ModelObject::add_volume(TriangleMesh &&mesh)
|
ModelVolume* ModelObject::add_volume(TriangleMesh &&mesh, bool centered)
|
||||||
{
|
{
|
||||||
ModelVolume* v = new ModelVolume(this, std::move(mesh));
|
ModelVolume* v = new ModelVolume(this, std::move(mesh));
|
||||||
this->volumes.push_back(v);
|
this->volumes.push_back(v);
|
||||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||||
v->center_geometry();
|
if (centered)
|
||||||
|
v->center_geometry();
|
||||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||||
this->invalidate_bounding_box();
|
this->invalidate_bounding_box();
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume* ModelObject::add_volume(const ModelVolume &other)
|
ModelVolume* ModelObject::add_volume(const ModelVolume &other, bool centered)
|
||||||
{
|
{
|
||||||
ModelVolume* v = new ModelVolume(this, other);
|
ModelVolume* v = new ModelVolume(this, other);
|
||||||
this->volumes.push_back(v);
|
this->volumes.push_back(v);
|
||||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||||
v->center_geometry();
|
if (centered)
|
||||||
|
v->center_geometry();
|
||||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||||
this->invalidate_bounding_box();
|
this->invalidate_bounding_box();
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume* ModelObject::add_volume(const ModelVolume &other, TriangleMesh &&mesh)
|
ModelVolume* ModelObject::add_volume(const ModelVolume &other, TriangleMesh &&mesh, bool centered)
|
||||||
{
|
{
|
||||||
ModelVolume* v = new ModelVolume(this, other, std::move(mesh));
|
ModelVolume* v = new ModelVolume(this, other, std::move(mesh));
|
||||||
this->volumes.push_back(v);
|
this->volumes.push_back(v);
|
||||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||||
v->center_geometry();
|
if (centered)
|
||||||
|
v->center_geometry();
|
||||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||||
this->invalidate_bounding_box();
|
this->invalidate_bounding_box();
|
||||||
return v;
|
return v;
|
||||||
|
@ -193,10 +193,10 @@ public:
|
|||||||
Model* get_model() { return m_model; };
|
Model* get_model() { return m_model; };
|
||||||
const Model* get_model() const { return m_model; };
|
const Model* get_model() const { return m_model; };
|
||||||
|
|
||||||
ModelVolume* add_volume(const TriangleMesh &mesh);
|
ModelVolume* add_volume(const TriangleMesh &mesh, bool centered = true);
|
||||||
ModelVolume* add_volume(TriangleMesh &&mesh);
|
ModelVolume* add_volume(TriangleMesh &&mesh, bool centered = true);
|
||||||
ModelVolume* add_volume(const ModelVolume &volume);
|
ModelVolume* add_volume(const ModelVolume &volume, bool centered = true);
|
||||||
ModelVolume* add_volume(const ModelVolume &volume, TriangleMesh &&mesh);
|
ModelVolume* add_volume(const ModelVolume &volume, TriangleMesh &&mesh, bool centered = true);
|
||||||
void delete_volume(size_t idx);
|
void delete_volume(size_t idx);
|
||||||
void clear_volumes();
|
void clear_volumes();
|
||||||
bool is_multiparts() const { return volumes.size() > 1; }
|
bool is_multiparts() const { return volumes.size() > 1; }
|
||||||
|
@ -744,6 +744,10 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
|
|||||||
// let's get it from the sorted collection as it might have been reversed
|
// let's get it from the sorted collection as it might have been reversed
|
||||||
size_t i = idx - sorted_coll.orig_indices.begin();
|
size_t i = idx - sorted_coll.orig_indices.begin();
|
||||||
entities.append(*sorted_coll.entities[i]);
|
entities.append(*sorted_coll.entities[i]);
|
||||||
|
//if thin extrusion is a loop, make it ccw like a normal contour.
|
||||||
|
if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(entities.entities.back())) {
|
||||||
|
loop->make_counter_clockwise();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const PerimeterGeneratorLoop &loop = loops[*idx];
|
const PerimeterGeneratorLoop &loop = loops[*idx];
|
||||||
ExtrusionLoop eloop = *dynamic_cast<ExtrusionLoop*>(coll.entities[*idx]);
|
ExtrusionLoop eloop = *dynamic_cast<ExtrusionLoop*>(coll.entities[*idx]);
|
||||||
|
@ -1720,6 +1720,8 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
|
|||||||
first_layer_height // this will be overridden at G-code export time
|
first_layer_height // this will be overridden at G-code export time
|
||||||
)));
|
)));
|
||||||
eloop.paths.back().polyline = loop.split_at_first_point();
|
eloop.paths.back().polyline = loop.split_at_first_point();
|
||||||
|
//we make it clowkwise, but as it will be reversed, it will be ccw
|
||||||
|
eloop.make_clockwise();
|
||||||
out.append(eloop);
|
out.append(eloop);
|
||||||
if (m_config.min_skirt_length.value > 0) {
|
if (m_config.min_skirt_length.value > 0) {
|
||||||
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
|
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
|
||||||
|
@ -57,4 +57,5 @@
|
|||||||
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
|
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
|
||||||
|
|
||||||
|
|
||||||
|
#define DEBUG_EXTRUSION_OUTPUT 0
|
||||||
#endif // _technologies_h_
|
#endif // _technologies_h_
|
||||||
|
@ -1826,6 +1826,22 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
|
|||||||
stl_get_size(&lower->stl);
|
stl_get_size(&lower->stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pointf3s TriangleMesh::vertices()
|
||||||
|
{
|
||||||
|
Pointf3s tmp{};
|
||||||
|
if (this->repaired) {
|
||||||
|
if (this->stl.v_shared == nullptr)
|
||||||
|
stl_generate_shared_vertices(&stl); // build the list of vertices
|
||||||
|
for (auto i = 0; i < this->stl.stats.shared_vertices; i++) {
|
||||||
|
const auto& v = this->stl.v_shared[i];
|
||||||
|
tmp.emplace_back(Vec3d(v.x(), v.y(), v.z()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "TriangleMesh", "vertices() requires repair()";
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
// Generate the vertex list for a cube solid of arbitrary size in X/Y/Z.
|
// Generate the vertex list for a cube solid of arbitrary size in X/Y/Z.
|
||||||
TriangleMesh make_cube(double x, double y, double z) {
|
TriangleMesh make_cube(double x, double y, double z) {
|
||||||
Vec3d pv[8] = {
|
Vec3d pv[8] = {
|
||||||
|
@ -77,6 +77,9 @@ public:
|
|||||||
|
|
||||||
stl_file stl;
|
stl_file stl;
|
||||||
bool repaired;
|
bool repaired;
|
||||||
|
|
||||||
|
/// --- for tests ----- ///
|
||||||
|
Pointf3s vertices();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void require_shared_vertices();
|
void require_shared_vertices();
|
||||||
|
@ -15,6 +15,8 @@ set(SLIC3R_TEST_SOURCES
|
|||||||
libslic3r/test_flow.cpp
|
libslic3r/test_flow.cpp
|
||||||
libslic3r/test_gcodewriter.cpp
|
libslic3r/test_gcodewriter.cpp
|
||||||
libslic3r/test_geometry.cpp
|
libslic3r/test_geometry.cpp
|
||||||
|
libslic3r/test_model.cpp
|
||||||
|
libslic3r/test_print.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (NOT TARGET Catch)
|
if (NOT TARGET Catch)
|
||||||
|
@ -42,8 +42,8 @@ SCENARIO("Extrusion width specifics", "[!mayfail]") {
|
|||||||
std::string gcode_filepath("");
|
std::string gcode_filepath("");
|
||||||
Slic3r::Test::gcode(gcode_filepath, print);
|
Slic3r::Test::gcode(gcode_filepath, print);
|
||||||
GCodeReader parser {Slic3r::GCodeReader()};
|
GCodeReader parser {Slic3r::GCodeReader()};
|
||||||
const auto layer_height { config->opt_float("layer_height") };
|
const double layer_height = config->opt_float("layer_height");
|
||||||
std::string gcode_from_file{ read_to_string(gcode_filepath) };
|
std::string gcode_from_file= read_to_string(gcode_filepath);
|
||||||
parser.parse_buffer(gcode_from_file, [&E_per_mm_bottom, layer_height] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line)
|
parser.parse_buffer(gcode_from_file, [&E_per_mm_bottom, layer_height] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line)
|
||||||
{
|
{
|
||||||
if (self.z() == Approx(layer_height).margin(0.01)) { // only consider first layer
|
if (self.z() == Approx(layer_height).margin(0.01)) { // only consider first layer
|
||||||
|
@ -1,47 +1,55 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include "Model.hpp"
|
#include "../../libslic3r/Config.hpp"
|
||||||
#include "test_data.hpp" // get access to init_print, etc
|
#include "../../libslic3r/Model.hpp"
|
||||||
|
#include "../test_data.hpp" // get access to init_print, etc
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
using namespace Slic3r::Test;
|
using namespace Slic3r::Test;
|
||||||
|
|
||||||
SCENARIO("Model construction") {
|
SCENARIO("Model construction") {
|
||||||
GIVEN("A Slic3r Model") {
|
GIVEN("A Slic3r Model") {
|
||||||
auto model {Slic3r::Model()};
|
Model model;
|
||||||
auto sample_mesh {Slic3r::TriangleMesh::make_cube(20,20,20)};
|
TriangleMesh sample_mesh = make_cube(20,20,20);
|
||||||
sample_mesh.repair();
|
sample_mesh.repair();
|
||||||
|
|
||||||
auto config {Slic3r::Config::new_from_defaults()};
|
DynamicPrintConfig *config = Slic3r::DynamicPrintConfig::new_from_defaults();
|
||||||
std::shared_ptr<Slic3r::Print> print = std::make_shared<Slic3r::Print>();
|
Slic3r::Print print;
|
||||||
print->apply_config(config);
|
print.apply_config(*config);
|
||||||
|
//Slic3r::Test::init_print(print, { sample_mesh }, model, config);
|
||||||
|
|
||||||
WHEN("Model object is added") {
|
WHEN("Model object is added") {
|
||||||
ModelObject* mo {model.add_object()};
|
ModelObject* mo = model.add_object();
|
||||||
|
mo->name = "cube20";
|
||||||
THEN("Model object list == 1") {
|
THEN("Model object list == 1") {
|
||||||
REQUIRE(model.objects.size() == 1);
|
REQUIRE(model.objects.size() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mo->add_volume(sample_mesh);
|
mo->add_volume(sample_mesh, false);
|
||||||
THEN("Model volume list == 1") {
|
THEN("Model volume list == 1") {
|
||||||
REQUIRE(mo->volumes.size() == 1);
|
REQUIRE(mo->volumes.size() == 1);
|
||||||
}
|
}
|
||||||
THEN("Model volume modifier is false") {
|
THEN("Model volume modifier is false") {
|
||||||
REQUIRE(mo->volumes.front()->modifier == false);
|
REQUIRE(mo->volumes.front()->is_modifier() == false);
|
||||||
}
|
}
|
||||||
THEN("Mesh is equivalent to input mesh.") {
|
THEN("Mesh is equivalent to input mesh.") {
|
||||||
REQUIRE(sample_mesh.vertices() == mo->volumes.front()->mesh.vertices());
|
REQUIRE(sample_mesh.vertices() == mo->volumes.front()->mesh.vertices());
|
||||||
}
|
}
|
||||||
ModelInstance* inst {mo->add_instance()};
|
ModelInstance* inst = mo->add_instance();
|
||||||
inst->rotation = 0;
|
inst->set_rotation(Vec3d(0,0,0));
|
||||||
inst->scaling_factor = 1.0;
|
inst->set_scaling_factor(Vec3d(1, 1, 1));
|
||||||
model.arrange_objects(print->config.min_object_distance());
|
model.arrange_objects(print.config().min_object_distance());
|
||||||
model.center_instances_around_point(Slic3r::Pointf(100,100));
|
model.center_instances_around_point(Slic3r::Vec2d(100,100));
|
||||||
print->auto_assign_extruders(mo);
|
print.auto_assign_extruders(mo);
|
||||||
print->add_model_object(mo);
|
//print.add_model_object(mo);
|
||||||
|
print.apply(model, *config);
|
||||||
|
print.validate();
|
||||||
THEN("Print works?") {
|
THEN("Print works?") {
|
||||||
print->process();
|
std::string gcode_filepath("");
|
||||||
auto gcode {std::stringstream("")};
|
Slic3r::Test::gcode(gcode_filepath, print);
|
||||||
print->export_gcode(gcode, true);
|
std::cout << "gcode generation done\n";
|
||||||
REQUIRE(gcode.str().size() > 0);
|
std::string gcode_from_file = read_to_string(gcode_filepath);
|
||||||
|
REQUIRE(gcode_from_file.size() > 0);
|
||||||
|
clean_file(gcode_filepath, "gcode");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,60 +1,70 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "test_data.hpp"
|
#include "../test_data.hpp"
|
||||||
#include "libslic3r.h"
|
#include "../../libslic3r/libslic3r.h"
|
||||||
|
|
||||||
using namespace Slic3r::Test;
|
using namespace Slic3r::Test;
|
||||||
|
using namespace Slic3r;
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
SCENARIO("PrintObject: Perimeter generation") {
|
SCENARIO("PrintObject: Perimeter generation") {
|
||||||
GIVEN("20mm cube and default config") {
|
GIVEN("20mm cube and default config") {
|
||||||
auto config {Slic3r::Config::new_from_defaults()};
|
DynamicPrintConfig *config = Slic3r::DynamicPrintConfig::new_from_defaults();
|
||||||
TestMesh m { TestMesh::cube_20x20x20 };
|
TestMesh m = TestMesh::cube_20x20x20;
|
||||||
Slic3r::Model model;
|
Model model;
|
||||||
auto event_counter {0U};
|
unsigned int event_counter = 0U;
|
||||||
std::string stage;
|
std::string stage;
|
||||||
int value {0};
|
int value = 0;
|
||||||
auto callback {[&event_counter, &stage, &value] (int a, const char* b) { stage = std::string(b); event_counter++; value = a; }};
|
auto callback {[&event_counter, &stage, &value] (int a, const char* b) { stage = std::string(b); event_counter++; value = a; }};
|
||||||
config->set("fill_density", 0);
|
config->set_key_value("fill_density", new ConfigOptionPercent(0));
|
||||||
|
|
||||||
WHEN("make_perimeters() is called") {
|
WHEN("make_perimeters() is called") {
|
||||||
auto print {Slic3r::Test::init_print({m}, model, config)};
|
Print print;
|
||||||
const auto& object = *(print->objects.at(0));
|
Slic3r::Test::init_print(print, { m }, model, config);
|
||||||
print->objects[0]->make_perimeters();
|
PrintObject& object = *(print.objects().at(0));
|
||||||
|
print.process();
|
||||||
|
// there are 66.66666.... layers for 0.3mm in 20mm
|
||||||
|
//slic3r is rounded (slice at half-layer), slic3rPE is less?
|
||||||
|
//TODO: check the slic32r why it's not cut at half-layer
|
||||||
THEN("67 layers exist in the model") {
|
THEN("67 layers exist in the model") {
|
||||||
REQUIRE(object.layers.size() == 67);
|
REQUIRE(object.layers().size() == 67);
|
||||||
}
|
}
|
||||||
THEN("Every layer in region 0 has 1 island of perimeters") {
|
THEN("Every layer in region 0 has 1 island of perimeters") {
|
||||||
for(auto* layer : object.layers) {
|
for(Layer* layer : object.layers()) {
|
||||||
REQUIRE(layer->regions[0]->perimeters.size() == 1);
|
REQUIRE(layer->regions()[0]->perimeters.entities.size() == 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
THEN("Every layer in region 0 has 3 paths in its perimeters list.") {
|
THEN("Every layer (but top) in region 0 has 3 paths in its perimeters list.") {
|
||||||
for(auto* layer : object.layers) {
|
LayerPtrs layers = object.layers();
|
||||||
REQUIRE(layer->regions[0]->perimeters.items_count() == 3);
|
for (auto layer = layers.begin(); layer != layers.end() - 1; ++layer) {
|
||||||
|
REQUIRE((*layer)->regions()[0]->perimeters.items_count() == 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
THEN("Top layer in region 0 has 1 path in its perimeters list (only 1 perimeter on top).") {
|
||||||
|
REQUIRE(object.layers().back()->regions()[0]->perimeters.items_count() == 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SCENARIO("Print: Skirt generation") {
|
SCENARIO("Print: Skirt generation") {
|
||||||
GIVEN("20mm cube and default config") {
|
GIVEN("20mm cube and default config") {
|
||||||
auto config {Slic3r::Config::new_from_defaults()};
|
DynamicPrintConfig *config = Slic3r::DynamicPrintConfig::new_from_defaults();
|
||||||
TestMesh m { TestMesh::cube_20x20x20 };
|
TestMesh m = TestMesh::cube_20x20x20;
|
||||||
Slic3r::Model model;
|
Slic3r::Model model;
|
||||||
auto event_counter {0U};
|
unsigned int event_counter = 0U;
|
||||||
std::string stage;
|
std::string stage;
|
||||||
int value {0};
|
int value = 0;
|
||||||
config->set("skirt_height", 1);
|
config->set_key_value("skirt_height", new ConfigOptionInt(1));
|
||||||
config->set("skirt_distance", 1);
|
config->set_key_value("skirt_distance", new ConfigOptionFloat(1));
|
||||||
WHEN("Skirts is set to 2 loops") {
|
WHEN("Skirts is set to 2 loops") {
|
||||||
config->set("skirts", 2);
|
config->set_key_value("skirts", new ConfigOptionInt(2));
|
||||||
auto print {Slic3r::Test::init_print({m}, model, config)};
|
Print print;
|
||||||
print->make_skirt();
|
Slic3r::Test::init_print(print, { m }, model, config);
|
||||||
|
print.process();
|
||||||
THEN("Skirt Extrusion collection has 2 loops in it") {
|
THEN("Skirt Extrusion collection has 2 loops in it") {
|
||||||
REQUIRE(print->skirt.items_count() == 2);
|
REQUIRE(print.skirt().items_count() == 2);
|
||||||
REQUIRE(print->skirt.flatten().entities.size() == 2);
|
REQUIRE(print.skirt().flatten().entities.size() == 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,36 +72,40 @@ SCENARIO("Print: Skirt generation") {
|
|||||||
|
|
||||||
SCENARIO("Print: Brim generation") {
|
SCENARIO("Print: Brim generation") {
|
||||||
GIVEN("20mm cube and default config, 1mm first layer width") {
|
GIVEN("20mm cube and default config, 1mm first layer width") {
|
||||||
auto config {Slic3r::Config::new_from_defaults()};
|
DynamicPrintConfig *config = Slic3r::DynamicPrintConfig::new_from_defaults();
|
||||||
TestMesh m { TestMesh::cube_20x20x20 };
|
TestMesh m = TestMesh::cube_20x20x20;
|
||||||
Slic3r::Model model;
|
Slic3r::Model model;
|
||||||
auto event_counter {0U};
|
unsigned int event_counter = 0U;
|
||||||
std::string stage;
|
std::string stage;
|
||||||
int value {0};
|
int value = 0;
|
||||||
config->set("first_layer_extrusion_width", 1);
|
config->set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(1, false));
|
||||||
WHEN("Brim is set to 3mm") {
|
WHEN("Brim is set to 3mm") {
|
||||||
config->set("brim_width", 3);
|
config->set_key_value("brim_width", new ConfigOptionFloat(3));
|
||||||
auto print {Slic3r::Test::init_print({m}, model, config)};
|
Print print;
|
||||||
print->make_brim();
|
Slic3r::Test::init_print(print, { m }, model, config);
|
||||||
|
print.process();
|
||||||
THEN("Brim Extrusion collection has 3 loops in it") {
|
THEN("Brim Extrusion collection has 3 loops in it") {
|
||||||
REQUIRE(print->brim.items_count() == 3);
|
REQUIRE(print.brim().items_count() == 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WHEN("Brim is set to 6mm") {
|
WHEN("Brim is set to 6mm") {
|
||||||
config->set("brim_width", 6);
|
config->set_key_value("brim_width", new ConfigOptionFloat(6));
|
||||||
auto print {Slic3r::Test::init_print({m}, model, config)};
|
Print print;
|
||||||
print->make_brim();
|
Slic3r::Test::init_print(print, { m }, model, config);
|
||||||
|
print.process();
|
||||||
THEN("Brim Extrusion collection has 6 loops in it") {
|
THEN("Brim Extrusion collection has 6 loops in it") {
|
||||||
REQUIRE(print->brim.items_count() == 6);
|
REQUIRE(print.brim().items_count() == 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WHEN("Brim is set to 6mm, extrusion width 0.5mm") {
|
WHEN("Brim is set to 6mm, extrusion width 0.5mm") {
|
||||||
config->set("brim_width", 6);
|
config->set_key_value("brim_width", new ConfigOptionFloat(6));
|
||||||
config->set("first_layer_extrusion_width", 0.5);
|
config->set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.5, false));
|
||||||
auto print {Slic3r::Test::init_print({m}, model, config)};
|
Print print;
|
||||||
print->make_brim();
|
Slic3r::Test::init_print(print, { m }, model, config);
|
||||||
THEN("Brim Extrusion collection has 12 loops in it") {
|
print.process();
|
||||||
REQUIRE(print->brim.items_count() == 12);
|
double nbLoops = 6.0 / print.brim_flow().spacing();
|
||||||
|
THEN("Brim Extrusion collection has " + std::to_string(nbLoops) + " loops in it (flow="+ std::to_string(print.brim_flow().spacing())+")") {
|
||||||
|
REQUIRE(print.brim().items_count() == floor(nbLoops));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user