mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 06:35:57 +08:00
fix #242
This commit is contained in:
parent
07fa80304d
commit
f654b980a9
@ -107,7 +107,6 @@ void PerimeterGenerator::process()
|
||||
Surfaces all_surfaces = this->slices->surfaces;
|
||||
|
||||
//store surface for bridge infill to avoid unsupported perimeters (but the first one, this one is always good)
|
||||
|
||||
if (this->config->no_perimeter_unsupported_algo != npuaNone
|
||||
&& this->lower_slices != NULL && !this->lower_slices->empty()) {
|
||||
|
||||
@ -683,8 +682,10 @@ void PerimeterGenerator::process()
|
||||
// TODO: add test for perimeter order
|
||||
if (this->config->external_perimeters_first ||
|
||||
(this->layer->id() == 0 && this->object_config->brim_width.value > 0)) {
|
||||
if (this->config->external_perimeters_nothole.value) {
|
||||
if (this->config->external_perimeters_hole.value) {
|
||||
if (this->config->external_perimeters_nothole.value ||
|
||||
(this->layer->id() == 0 && this->object_config->brim_width.value > 0)) {
|
||||
if (this->config->external_perimeters_hole.value ||
|
||||
(this->layer->id() == 0 && this->object_config->brim_width.value > 0)) {
|
||||
entities.reverse();
|
||||
} else {
|
||||
//reverse only not-hole perimeters
|
||||
@ -926,31 +927,44 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
|
||||
coll.append(tw.entities);
|
||||
thin_walls.clear();
|
||||
}
|
||||
|
||||
|
||||
// traverse children and build the final collection
|
||||
Point zero_point(0, 0);
|
||||
//result is [idx, needReverse] ?
|
||||
std::vector<std::pair<size_t, bool>> chain = chain_extrusion_entities(coll.entities, &zero_point);
|
||||
ExtrusionEntityCollection entities;
|
||||
for (const std::pair<size_t, bool> &idx : chain) {
|
||||
ExtrusionEntityCollection coll_out;
|
||||
|
||||
//little check: if you have external holes with only one extrusion and internal things, please draw the internal first, just in case it can help print the hole better.
|
||||
std::vector<std::pair<size_t, bool>> better_chain;
|
||||
for (const std::pair<size_t, bool>& idx : chain) {
|
||||
if (!loops[idx.first].is_external() || (!loops[idx.first].is_contour && !loops[idx.first].children.empty()))
|
||||
better_chain.push_back(idx);
|
||||
}
|
||||
for (const std::pair<size_t, bool>& idx : chain) {
|
||||
if (loops[idx.first].is_external() && !(!loops[idx.first].is_contour && !loops[idx.first].children.empty()))
|
||||
better_chain.push_back(idx);
|
||||
}
|
||||
|
||||
//move from coll to coll_out and gettign children of each in the same time. (deep first)
|
||||
for (const std::pair<size_t, bool> &idx : better_chain) {
|
||||
|
||||
if (idx.first >= loops.size()) {
|
||||
// this is a thin wall
|
||||
// let's get it from the sorted collection as it might have been reversed
|
||||
entities.entities.reserve(entities.entities.size() + 1);
|
||||
entities.entities.emplace_back(coll.entities[idx.first]);
|
||||
coll_out.entities.reserve(coll_out.entities.size() + 1);
|
||||
coll_out.entities.emplace_back(coll.entities[idx.first]);
|
||||
coll.entities[idx.first] = nullptr;
|
||||
if (idx.second)
|
||||
entities.entities.back()->reverse();
|
||||
coll_out.entities.back()->reverse();
|
||||
//if thin extrusion is a loop, make it ccw like a normal contour.
|
||||
if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(entities.entities.back())) {
|
||||
if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(coll_out.entities.back())) {
|
||||
loop->make_counter_clockwise();
|
||||
}
|
||||
} else {
|
||||
const PerimeterGeneratorLoop &loop = loops[idx.first];
|
||||
assert(thin_walls.empty());
|
||||
ExtrusionEntityCollection children = this->_traverse_loops(loop.children, thin_walls);
|
||||
entities.entities.reserve(entities.entities.size() + children.entities.size() + 1);
|
||||
coll_out.entities.reserve(coll_out.entities.size() + children.entities.size() + 1);
|
||||
ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]);
|
||||
coll.entities[idx.first] = nullptr;
|
||||
if (loop.is_contour) {
|
||||
@ -959,16 +973,16 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
|
||||
eloop->make_clockwise();
|
||||
else
|
||||
eloop->make_counter_clockwise();
|
||||
entities.append(std::move(children.entities));
|
||||
entities.append(*eloop);
|
||||
coll_out.append(std::move(children.entities));
|
||||
coll_out.append(*eloop);
|
||||
} else {
|
||||
eloop->make_clockwise();
|
||||
entities.append(*eloop);
|
||||
entities.append(std::move(children.entities));
|
||||
coll_out.append(*eloop);
|
||||
coll_out.append(std::move(children.entities));
|
||||
}
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
return coll_out;
|
||||
}
|
||||
|
||||
PerimeterIntersectionPoint
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
polygon(polygon), is_contour(is_contour), depth(depth), is_steep_overhang(is_steep_overhang) {}
|
||||
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
|
||||
bool is_external() const { return this->depth == 0; }
|
||||
// An island, which may have holes, but it does not have another internal island.
|
||||
// it's the last loop of the contour (not hol), so the first to be printed (if all goes well)
|
||||
bool is_internal_contour() const;
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#define CATCH_CONFIG_DISABLE
|
||||
//#define CATCH_CONFIG_DISABLE
|
||||
|
||||
//#include <catch_main.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
@ -176,3 +176,41 @@ SCENARIO("Print: Brim generation") {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Print: perimeter generation") {
|
||||
GIVEN("cube with hole, just enough space for two loops at a point") {
|
||||
DynamicPrintConfig& config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
Slic3r::Model model{};
|
||||
config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(0.42, false));
|
||||
config.set_deserialize("nozzle_diameter", "0.4");
|
||||
config.set_deserialize("layer_height", "0.2");
|
||||
config.set_deserialize("first_layer_height", "0.2");
|
||||
config.set_key_value("only_one_perimeter_top", new ConfigOptionBool(false));
|
||||
Print print{};
|
||||
auto facets = std::vector<Vec3i32>{
|
||||
Vec3i32(1,4,3),Vec3i32(4,1,2),Vec3i32(16,12,14),Vec3i32(16,10,12),Vec3i32(10,4,6),Vec3i32(4,10,16),Vec3i32(8,14,12),Vec3i32(8,2,14),
|
||||
Vec3i32(6,2,8),Vec3i32(2,6,4),Vec3i32(14,15,16),Vec3i32(15,14,13),Vec3i32(15,4,16),Vec3i32(4,15,3),Vec3i32(13,11,15),Vec3i32(13,7,11),
|
||||
Vec3i32(7,1,5),Vec3i32(1,7,13),Vec3i32(9,15,11),Vec3i32(9,3,15),Vec3i32(5,3,9),Vec3i32(3,5,1),Vec3i32(1,14,2),Vec3i32(14,1,13),
|
||||
Vec3i32(9,12,10),Vec3i32(12,9,11),Vec3i32(6,9,10),Vec3i32(9,6,5),Vec3i32(8,5,6),Vec3i32(5,8,7),Vec3i32(7,12,11),Vec3i32(12,7,8)
|
||||
};
|
||||
for (Vec3i32& vec : facets)
|
||||
vec -= Vec3i32(1, 1, 1);
|
||||
TriangleMesh tm = TriangleMesh{ std::vector<Vec3d>{Vec3d(-5,-5,-0.1),Vec3d(-5,-5,0.1),Vec3d(-5,5,-0.1),Vec3d(-5,5,0.1),
|
||||
Vec3d(-1.328430,0,-0.1),Vec3d(-1.328430,0,0.1),Vec3d(1.5,-2.828430,-0.1),Vec3d(1.5,-2.828430,0.1),
|
||||
Vec3d(1.5,2.828430,-0.1),Vec3d(1.5,2.828430,0.1),Vec3d(4.328430,0,-0.1),Vec3d(4.328430,0,0.1),
|
||||
Vec3d(5,-5,-0.1),Vec3d(5,-5,0.1),Vec3d(5,5,-0.1),Vec3d(5,5,0.1)},
|
||||
facets };
|
||||
Slic3r::Test::init_print(print, {tm}, model, &config);
|
||||
print.process();
|
||||
THEN("hole perimeter should not be printed first") {
|
||||
ExtrusionEntity* loop = print.objects()[0]->layers()[0]->regions()[0]->perimeters.entities[0];
|
||||
REQUIRE(loop->is_collection());
|
||||
loop = ((ExtrusionEntityCollection*)loop)->entities.front();
|
||||
REQUIRE(loop->is_loop());
|
||||
// what we don't want in first is something that is (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0 && loop->role() == elrExternalPerimeter
|
||||
REQUIRE( (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) == 0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user