From 57a7172a39b895ec6a19751a82f4518ce01422f7 Mon Sep 17 00:00:00 2001 From: igiannakas Date: Mon, 4 Mar 2024 12:23:01 +0000 Subject: [PATCH 1/6] Squashed commit of the following: commit cf39ba04566a46de295178843e882415bc87b1ff Author: igiannakas Date: Mon Mar 4 12:22:39 2024 +0000 Update PerimeterGenerator.cpp commit ff4347f8825d7737e0bd25f3c53932e4b5c47d23 Author: igiannakas Date: Mon Mar 4 12:09:03 2024 +0000 Middle Outer Inner implementation commit 00486f73adf2bb42a3f836caf58a0000fc7600c0 Merge: 3b34635f8 1cb88d0b9 Author: igiannakas Date: Mon Mar 4 11:34:25 2024 +0000 Merge branch 'middle-outer-inner' of https://github.com/igiannakas/OrcaSlicer into middle-outer-inner commit 3b34635f80ec8a6e53924a52f03549cabca20fda Author: igiannakas Date: Mon Mar 4 11:34:20 2024 +0000 Update PerimeterGenerator.cpp commit 1cb88d0b952f18c118363470e1511ad2c6cdc462 Merge: 78e23b663 27439ed54 Author: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Date: Mon Mar 4 11:23:00 2024 +0000 Merge branch 'SoftFever:main' into middle-outer-inner commit 78e23b66395c07636fad2fd46ae2a76cfc209e9d Merge: 4e7a0f9a7 5dab9b20b Author: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Date: Sat Mar 2 11:36:57 2024 +0000 Merge branch 'SoftFever:main' into middle-outer-inner commit 4e7a0f9a70bbb317143be8e2d81fab27d534264d Author: igiannakas Date: Mon Feb 5 10:01:26 2024 +0000 First commit - MiddleOuterInner --- src/libslic3r/PerimeterGenerator.cpp | 127 ++++++++++++++++++++++++++- src/libslic3r/PrintConfig.cpp | 5 +- src/libslic3r/PrintConfig.hpp | 1 + 3 files changed, 128 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index efa3936d89e..a26f71c9b64 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -1443,7 +1443,7 @@ void PerimeterGenerator::process_classic() coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing(); coord_t ext_perimeter_spacing2; // Orca: ignore precise_outer_wall if wall_sequence is not InnerOuter - if(config->precise_outer_wall && this->config->wall_sequence == WallSequence::InnerOuter) + if(config->precise_outer_wall && ((this->config->wall_sequence == WallSequence::InnerOuter)||(this->config->wall_sequence == WallSequence::MiddleOuterInner)) ) ext_perimeter_spacing2 = scaled(0.5f * (this->ext_perimeter_flow.width() + this->perimeter_flow.width())); else ext_perimeter_spacing2 = scaled(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing())); @@ -1754,7 +1754,24 @@ void PerimeterGenerator::process_classic() this->object_config->brim_type == BrimType::btOuterOnly && this->object_config->brim_width.value > 0)) entities.reverse(); - // SoftFever: sandwich mode + else if (this->config->wall_sequence == WallSequence::MiddleOuterInner){ + if (entities.entities.size() > 1) { + entities.reverse(); + + int index; + + for (index=0; index < entities.entities.size(); index++) { + if (entities.entities[index]->role() == erExternalPerimeter) { + if ( ( (index+1) < entities.entities.size() ) && (entities.entities[index+1]->role() == erPerimeter) ) { + std::swap(entities.entities[index], entities.entities[index+1]); + // Skip next item (which we swapped) + index++; + } + } + } + } + } + // SoftFever: sandwich mode else if (this->config->wall_sequence == WallSequence::InnerOuterInner) if (entities.entities.size() > 1){ int last_outer=0; @@ -2183,7 +2200,7 @@ void PerimeterGenerator::process_arachne() if (is_topmost_layer && loop_number > 0 && config->only_one_wall_top) loop_number = 0; - auto apply_precise_outer_wall = config->precise_outer_wall && this->config->wall_sequence == WallSequence::InnerOuter; + auto apply_precise_outer_wall = config->precise_outer_wall && ((this->config->wall_sequence == WallSequence::InnerOuter) || (this->config->wall_sequence == WallSequence::MiddleOuterInner)); // Orca: properly adjust offset for the outer wall if precise_outer_wall is enabled. ExPolygons last = offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution), apply_precise_outer_wall? -float(ext_perimeter_width - ext_perimeter_spacing ) @@ -2294,7 +2311,8 @@ void PerimeterGenerator::process_arachne() bool is_outer_wall_first = this->config->wall_sequence == WallSequence::OuterInner || - this->config->wall_sequence == WallSequence::InnerOuterInner; + this->config->wall_sequence == WallSequence::InnerOuterInner || + this->config->wall_sequence == WallSequence::MiddleOuterInner; if (layer_id == 0){ // disable inner outer inner algorithm after the first layer is_outer_wall_first = @@ -2530,6 +2548,107 @@ void PerimeterGenerator::process_arachne() } } + if (this->config->wall_sequence == WallSequence::MiddleOuterInner && layer_id > 0) { // only enable middle outer inner algorithm after first layer + if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do middle outer inner ordering + int position = 0; // index to run the re-ordering for multiple external perimeters in a single island. + int arr_i, arr_j = 0; // indexes to run through the walls in the for loops + int outer, first_internal, second_internal, max_internal, current_perimeter; // allocate index values + + // Initiate reorder sequence to bring any index 1 (first internal) perimeters ahead of any second internal perimeters + // Leaving these out of order will result in print defects on the external wall as they will be extruded prior to any + // external wall. To do the re-ordering, we are creating two extrusion arrays - reordered_extrusions which will contain + // the reordered extrusions and skipped_extrusions will contain the ones that were skipped in the scan + std::vector reordered_extrusions, skipped_extrusions; + bool found_second_internal = false; // helper variable to indicate the start of a new island + + for(auto extrusion_to_reorder : ordered_extrusions){ //scan the perimeters to reorder + switch (extrusion_to_reorder.extrusion->inset_idx) { + case 0: // external perimeter + if(found_second_internal){ //new island - move skipped extrusions to reordered array + for(auto extrusion_skipped : skipped_extrusions) + reordered_extrusions.emplace_back(extrusion_skipped); + skipped_extrusions.clear(); + } + reordered_extrusions.emplace_back(extrusion_to_reorder); + break; + case 1: // first internal perimeter + reordered_extrusions.emplace_back(extrusion_to_reorder); + break; + default: // second internal+ perimeter -> put them in the skipped extrusions array + skipped_extrusions.emplace_back(extrusion_to_reorder); + found_second_internal = true; + break; + } + } + if(ordered_extrusions.size()>reordered_extrusions.size()){ + // we didnt find any more islands, so lets move the remaining skipped perimeters to the reordered extrusions list. + for(auto extrusion_skipped : skipped_extrusions) + reordered_extrusions.emplace_back(extrusion_skipped); + skipped_extrusions.clear(); + } + + // Now start the sandwich mode wall re-ordering using the reordered_extrusions as the basis + // scan to find the external perimeter, first internal, second internal and last perimeter in the island. + // We then advance the position index to move to the second island and continue until there are no more + // perimeters left. + while (position < reordered_extrusions.size()) { + outer = first_internal = second_internal = current_perimeter = -1; // initialise all index values to -1 + max_internal = reordered_extrusions.size()-1; // initialise the maximum internal perimeter to the last perimeter on the extrusion list + // run through the walls to get the index values that need re-ordering until the first one for each + // is found. Start at "position" index to enable the for loop to iterate for multiple external + // perimeters in a single island + // printf("Reorder Loop. Position %d, extrusion list size: %d, Outer index %d, inner index %d, second inner index %d\n", position, reordered_extrusions.size(),outer,first_internal,second_internal); + for (arr_i = position; arr_i < reordered_extrusions.size(); ++arr_i) { + switch (reordered_extrusions[arr_i].extrusion->inset_idx) { + case 0: // external perimeter + if (outer == -1) + outer = arr_i; + break; + case 1: // first internal wall + if (first_internal==-1 && arr_i>outer && outer!=-1){ + first_internal = arr_i; + } + break; + case 2: // second internal wall + if (second_internal == -1 && arr_i > first_internal && outer!=-1){ + second_internal = arr_i; + } + break; + } + if(outer >-1 && first_internal>-1 && second_internal>-1 && ordered_extrusions[arr_i].extrusion->inset_idx == 0){ // found a new external perimeter after we've found all three perimeters to re-order -> this means we entered a new island. + arr_i=arr_i-1; //step back one perimeter + max_internal = arr_i; // new maximum internal perimeter is now this as we have found a new external perimeter, hence a new island. + break; // exit the for loop + } + } + + // printf("Layer ID %d, Outer index %d, inner index %d, second inner index %d, maximum internal perimeter %d \n",layer_id,outer,first_internal,second_internal, max_internal); + if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order? + std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering + + for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out for all perimers except any that have inset index 2 (second internal). These will be printed last + if(reordered_extrusions[arr_j].extrusion->inset_idx!=2){ + //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); + inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); + } + } + for (arr_j = max_internal; arr_j >=position; --arr_j){ // print any inset index 2 perimeters that were skipped before + if(reordered_extrusions[arr_j].extrusion->inset_idx==2){ + //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); + inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); + } + } + + for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array + ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; + } else + break; + // go to the next perimeter from the current position to continue scanning for external walls in the same island + position = arr_i + 1; + } + } + } + bool steep_overhang_contour = false; bool steep_overhang_hole = false; const WallDirection wall_direction = config->wall_direction; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 984192bd9f6..3aab02e6bde 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -185,7 +185,8 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallInfillOrder) static t_config_enum_values s_keys_map_WallSequence { { "inner wall/outer wall", int(WallSequence::InnerOuter) }, { "outer wall/inner wall", int(WallSequence::OuterInner) }, - { "inner-outer-inner wall", int(WallSequence::InnerOuterInner)} + { "inner-outer-inner wall", int(WallSequence::InnerOuterInner)}, + { "middle-outer-inner wall", int(WallSequence::MiddleOuterInner)} }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallSequence) @@ -1492,9 +1493,11 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("inner wall/outer wall"); def->enum_values.push_back("outer wall/inner wall"); def->enum_values.push_back("inner-outer-inner wall"); + def->enum_values.push_back("middle-outer-inner wall"); def->enum_labels.push_back(L("Inner/Outer")); def->enum_labels.push_back(L("Outer/Inner")); def->enum_labels.push_back(L("Inner/Outer/Inner")); + def->enum_labels.push_back(L("Middle/Outer/Inner")); def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(WallSequence::InnerOuter)); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 07be77ab3d8..ef429d79823 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -96,6 +96,7 @@ enum class WallSequence { InnerOuter, OuterInner, InnerOuterInner, + MiddleOuterInner, Count, }; From 450452e4c4ea83d338c77660e994b8ae3330b9cd Mon Sep 17 00:00:00 2001 From: igiannakas Date: Mon, 4 Mar 2024 12:37:46 +0000 Subject: [PATCH 2/6] Code clean up and consolidation --- src/libslic3r/PerimeterGenerator.cpp | 154 +++++++-------------------- 1 file changed, 37 insertions(+), 117 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index a26f71c9b64..55e05456cab 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -2444,8 +2444,9 @@ void PerimeterGenerator::process_arachne() } // printf("New Layer: Layer ID %d\n",layer_id); //debug - new layer - if (this->config->wall_sequence == WallSequence::InnerOuterInner && layer_id > 0) { // only enable inner outer inner algorithm after first layer - if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do inner outer inner ordering + if ( ((this->config->wall_sequence == WallSequence::InnerOuterInner) || (this->config->wall_sequence == WallSequence::MiddleOuterInner)) + && layer_id > 0) { // only enable inner outer inner or middle outer inner algorithm after first layer + if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do inner outer inner / middle outer nner ordering int position = 0; // index to run the re-ordering for multiple external perimeters in a single island. int arr_i, arr_j = 0; // indexes to run through the walls in the for loops int outer, first_internal, second_internal, max_internal, current_perimeter; // allocate index values @@ -2483,7 +2484,7 @@ void PerimeterGenerator::process_arachne() skipped_extrusions.clear(); } - // Now start the sandwich mode wall re-ordering using the reordered_extrusions as the basis + // Now start the sandwich mode / middle outer inner wall re-ordering using the reordered_extrusions as the basis // scan to find the external perimeter, first internal, second internal and last perimeter in the island. // We then advance the position index to move to the second island and continue until there are no more // perimeters left. @@ -2521,126 +2522,44 @@ void PerimeterGenerator::process_arachne() // printf("Layer ID %d, Outer index %d, inner index %d, second inner index %d, maximum internal perimeter %d \n",layer_id,outer,first_internal,second_internal, max_internal); if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order? - std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering - inner_outer_extrusions.reserve(max_internal - position + 1); // reserve array containing the number of perimeters before a new island. Variables are array indexes hence need to add +1 to convert to position allocations - // printf("Allocated array size %d, max_internal index %d, start position index %d \n",max_internal-position+1,max_internal,position); - - for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out towards the external perimeter (perimeters in reverse order) and store all internal perimeters until the first one identified with inset index 2 - if(arr_j >= second_internal){ - //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); - inner_outer_extrusions[max_internal-arr_j] = reordered_extrusions[arr_j]; - current_perimeter++; + if(this->config->wall_sequence == WallSequence::InnerOuterInner){ + std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering + inner_outer_extrusions.reserve(max_internal - position + 1); // reserve array containing the number of perimeters before a new island. Variables are array indexes hence need to add +1 to convert to position allocations + // printf("Allocated array size %d, max_internal index %d, start position index %d \n",max_internal-position+1,max_internal,position); + + for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out towards the external perimeter (perimeters in reverse order) and store all internal perimeters until the first one identified with inset index 2 + if(arr_j >= second_internal){ + //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); + inner_outer_extrusions[max_internal-arr_j] = reordered_extrusions[arr_j]; + current_perimeter++; + } } - } - - for (arr_j = position; arr_j < second_internal; ++arr_j){ // go outside in and map the remaining perimeters (external and first internal wall(s)) using the outside in wall order - // printf("Outside in loop: Mapped perimeter index %d to array position %d\n", arr_j, current_perimeter+1); - inner_outer_extrusions[++current_perimeter] = reordered_extrusions[arr_j]; - } - - for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array - ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; - } else - break; - // go to the next perimeter from the current position to continue scanning for external walls in the same island - position = arr_i + 1; - } - } - } - - if (this->config->wall_sequence == WallSequence::MiddleOuterInner && layer_id > 0) { // only enable middle outer inner algorithm after first layer - if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do middle outer inner ordering - int position = 0; // index to run the re-ordering for multiple external perimeters in a single island. - int arr_i, arr_j = 0; // indexes to run through the walls in the for loops - int outer, first_internal, second_internal, max_internal, current_perimeter; // allocate index values - - // Initiate reorder sequence to bring any index 1 (first internal) perimeters ahead of any second internal perimeters - // Leaving these out of order will result in print defects on the external wall as they will be extruded prior to any - // external wall. To do the re-ordering, we are creating two extrusion arrays - reordered_extrusions which will contain - // the reordered extrusions and skipped_extrusions will contain the ones that were skipped in the scan - std::vector reordered_extrusions, skipped_extrusions; - bool found_second_internal = false; // helper variable to indicate the start of a new island - - for(auto extrusion_to_reorder : ordered_extrusions){ //scan the perimeters to reorder - switch (extrusion_to_reorder.extrusion->inset_idx) { - case 0: // external perimeter - if(found_second_internal){ //new island - move skipped extrusions to reordered array - for(auto extrusion_skipped : skipped_extrusions) - reordered_extrusions.emplace_back(extrusion_skipped); - skipped_extrusions.clear(); + + for (arr_j = position; arr_j < second_internal; ++arr_j){ // go outside in and map the remaining perimeters (external and first internal wall(s)) using the outside in wall order + // printf("Outside in loop: Mapped perimeter index %d to array position %d\n", arr_j, current_perimeter+1); + inner_outer_extrusions[++current_perimeter] = reordered_extrusions[arr_j]; } - reordered_extrusions.emplace_back(extrusion_to_reorder); - break; - case 1: // first internal perimeter - reordered_extrusions.emplace_back(extrusion_to_reorder); - break; - default: // second internal+ perimeter -> put them in the skipped extrusions array - skipped_extrusions.emplace_back(extrusion_to_reorder); - found_second_internal = true; - break; - } - } - if(ordered_extrusions.size()>reordered_extrusions.size()){ - // we didnt find any more islands, so lets move the remaining skipped perimeters to the reordered extrusions list. - for(auto extrusion_skipped : skipped_extrusions) - reordered_extrusions.emplace_back(extrusion_skipped); - skipped_extrusions.clear(); - } + + for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array + ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; + }else + if(this->config->wall_sequence == WallSequence::MiddleOuterInner){ + std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering - // Now start the sandwich mode wall re-ordering using the reordered_extrusions as the basis - // scan to find the external perimeter, first internal, second internal and last perimeter in the island. - // We then advance the position index to move to the second island and continue until there are no more - // perimeters left. - while (position < reordered_extrusions.size()) { - outer = first_internal = second_internal = current_perimeter = -1; // initialise all index values to -1 - max_internal = reordered_extrusions.size()-1; // initialise the maximum internal perimeter to the last perimeter on the extrusion list - // run through the walls to get the index values that need re-ordering until the first one for each - // is found. Start at "position" index to enable the for loop to iterate for multiple external - // perimeters in a single island - // printf("Reorder Loop. Position %d, extrusion list size: %d, Outer index %d, inner index %d, second inner index %d\n", position, reordered_extrusions.size(),outer,first_internal,second_internal); - for (arr_i = position; arr_i < reordered_extrusions.size(); ++arr_i) { - switch (reordered_extrusions[arr_i].extrusion->inset_idx) { - case 0: // external perimeter - if (outer == -1) - outer = arr_i; - break; - case 1: // first internal wall - if (first_internal==-1 && arr_i>outer && outer!=-1){ - first_internal = arr_i; + for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out for all perimers except any that have inset index 2 (second internal). These will be printed last + if(reordered_extrusions[arr_j].extrusion->inset_idx!=2){ + inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); + } } - break; - case 2: // second internal wall - if (second_internal == -1 && arr_i > first_internal && outer!=-1){ - second_internal = arr_i; + for (arr_j = max_internal; arr_j >=position; --arr_j){ // print any inset index 2 perimeters that were skipped before + if(reordered_extrusions[arr_j].extrusion->inset_idx==2){ + inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); + } } - break; - } - if(outer >-1 && first_internal>-1 && second_internal>-1 && ordered_extrusions[arr_i].extrusion->inset_idx == 0){ // found a new external perimeter after we've found all three perimeters to re-order -> this means we entered a new island. - arr_i=arr_i-1; //step back one perimeter - max_internal = arr_i; // new maximum internal perimeter is now this as we have found a new external perimeter, hence a new island. - break; // exit the for loop - } - } - - // printf("Layer ID %d, Outer index %d, inner index %d, second inner index %d, maximum internal perimeter %d \n",layer_id,outer,first_internal,second_internal, max_internal); - if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order? - std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering - - for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out for all perimers except any that have inset index 2 (second internal). These will be printed last - if(reordered_extrusions[arr_j].extrusion->inset_idx!=2){ - //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); - inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); - } - } - for (arr_j = max_internal; arr_j >=position; --arr_j){ // print any inset index 2 perimeters that were skipped before - if(reordered_extrusions[arr_j].extrusion->inset_idx==2){ - //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); - inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); + + for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array + ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; } - } - - for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array - ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; } else break; // go to the next perimeter from the current position to continue scanning for external walls in the same island @@ -2648,6 +2567,7 @@ void PerimeterGenerator::process_arachne() } } } + bool steep_overhang_contour = false; bool steep_overhang_hole = false; From 48fb9ecbf81d6136a82be42b8618f9435e4f07ce Mon Sep 17 00:00:00 2001 From: igiannakas Date: Mon, 4 Mar 2024 12:23:01 +0000 Subject: [PATCH 3/6] Squashed commit of the following: commit cf39ba04566a46de295178843e882415bc87b1ff Author: igiannakas Date: Mon Mar 4 12:22:39 2024 +0000 Update PerimeterGenerator.cpp commit ff4347f8825d7737e0bd25f3c53932e4b5c47d23 Author: igiannakas Date: Mon Mar 4 12:09:03 2024 +0000 Middle Outer Inner implementation commit 00486f73adf2bb42a3f836caf58a0000fc7600c0 Merge: 3b34635f8 1cb88d0b9 Author: igiannakas Date: Mon Mar 4 11:34:25 2024 +0000 Merge branch 'middle-outer-inner' of https://github.com/igiannakas/OrcaSlicer into middle-outer-inner commit 3b34635f80ec8a6e53924a52f03549cabca20fda Author: igiannakas Date: Mon Mar 4 11:34:20 2024 +0000 Update PerimeterGenerator.cpp commit 1cb88d0b952f18c118363470e1511ad2c6cdc462 Merge: 78e23b663 27439ed54 Author: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Date: Mon Mar 4 11:23:00 2024 +0000 Merge branch 'SoftFever:main' into middle-outer-inner commit 78e23b66395c07636fad2fd46ae2a76cfc209e9d Merge: 4e7a0f9a7 5dab9b20b Author: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Date: Sat Mar 2 11:36:57 2024 +0000 Merge branch 'SoftFever:main' into middle-outer-inner commit 4e7a0f9a70bbb317143be8e2d81fab27d534264d Author: igiannakas Date: Mon Feb 5 10:01:26 2024 +0000 First commit - MiddleOuterInner --- src/libslic3r/PerimeterGenerator.cpp | 101 +++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 55e05456cab..97488756062 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -2569,6 +2569,107 @@ void PerimeterGenerator::process_arachne() } + if (this->config->wall_sequence == WallSequence::MiddleOuterInner && layer_id > 0) { // only enable middle outer inner algorithm after first layer + if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do middle outer inner ordering + int position = 0; // index to run the re-ordering for multiple external perimeters in a single island. + int arr_i, arr_j = 0; // indexes to run through the walls in the for loops + int outer, first_internal, second_internal, max_internal, current_perimeter; // allocate index values + + // Initiate reorder sequence to bring any index 1 (first internal) perimeters ahead of any second internal perimeters + // Leaving these out of order will result in print defects on the external wall as they will be extruded prior to any + // external wall. To do the re-ordering, we are creating two extrusion arrays - reordered_extrusions which will contain + // the reordered extrusions and skipped_extrusions will contain the ones that were skipped in the scan + std::vector reordered_extrusions, skipped_extrusions; + bool found_second_internal = false; // helper variable to indicate the start of a new island + + for(auto extrusion_to_reorder : ordered_extrusions){ //scan the perimeters to reorder + switch (extrusion_to_reorder.extrusion->inset_idx) { + case 0: // external perimeter + if(found_second_internal){ //new island - move skipped extrusions to reordered array + for(auto extrusion_skipped : skipped_extrusions) + reordered_extrusions.emplace_back(extrusion_skipped); + skipped_extrusions.clear(); + } + reordered_extrusions.emplace_back(extrusion_to_reorder); + break; + case 1: // first internal perimeter + reordered_extrusions.emplace_back(extrusion_to_reorder); + break; + default: // second internal+ perimeter -> put them in the skipped extrusions array + skipped_extrusions.emplace_back(extrusion_to_reorder); + found_second_internal = true; + break; + } + } + if(ordered_extrusions.size()>reordered_extrusions.size()){ + // we didnt find any more islands, so lets move the remaining skipped perimeters to the reordered extrusions list. + for(auto extrusion_skipped : skipped_extrusions) + reordered_extrusions.emplace_back(extrusion_skipped); + skipped_extrusions.clear(); + } + + // Now start the sandwich mode wall re-ordering using the reordered_extrusions as the basis + // scan to find the external perimeter, first internal, second internal and last perimeter in the island. + // We then advance the position index to move to the second island and continue until there are no more + // perimeters left. + while (position < reordered_extrusions.size()) { + outer = first_internal = second_internal = current_perimeter = -1; // initialise all index values to -1 + max_internal = reordered_extrusions.size()-1; // initialise the maximum internal perimeter to the last perimeter on the extrusion list + // run through the walls to get the index values that need re-ordering until the first one for each + // is found. Start at "position" index to enable the for loop to iterate for multiple external + // perimeters in a single island + // printf("Reorder Loop. Position %d, extrusion list size: %d, Outer index %d, inner index %d, second inner index %d\n", position, reordered_extrusions.size(),outer,first_internal,second_internal); + for (arr_i = position; arr_i < reordered_extrusions.size(); ++arr_i) { + switch (reordered_extrusions[arr_i].extrusion->inset_idx) { + case 0: // external perimeter + if (outer == -1) + outer = arr_i; + break; + case 1: // first internal wall + if (first_internal==-1 && arr_i>outer && outer!=-1){ + first_internal = arr_i; + } + break; + case 2: // second internal wall + if (second_internal == -1 && arr_i > first_internal && outer!=-1){ + second_internal = arr_i; + } + break; + } + if(outer >-1 && first_internal>-1 && second_internal>-1 && ordered_extrusions[arr_i].extrusion->inset_idx == 0){ // found a new external perimeter after we've found all three perimeters to re-order -> this means we entered a new island. + arr_i=arr_i-1; //step back one perimeter + max_internal = arr_i; // new maximum internal perimeter is now this as we have found a new external perimeter, hence a new island. + break; // exit the for loop + } + } + + // printf("Layer ID %d, Outer index %d, inner index %d, second inner index %d, maximum internal perimeter %d \n",layer_id,outer,first_internal,second_internal, max_internal); + if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order? + std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering + + for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out for all perimers except any that have inset index 2 (second internal). These will be printed last + if(reordered_extrusions[arr_j].extrusion->inset_idx!=2){ + //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); + inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); + } + } + for (arr_j = max_internal; arr_j >=position; --arr_j){ // print any inset index 2 perimeters that were skipped before + if(reordered_extrusions[arr_j].extrusion->inset_idx==2){ + //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); + inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); + } + } + + for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array + ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; + } else + break; + // go to the next perimeter from the current position to continue scanning for external walls in the same island + position = arr_i + 1; + } + } + } + bool steep_overhang_contour = false; bool steep_overhang_hole = false; const WallDirection wall_direction = config->wall_direction; From 1e5e5d078f0c692b0c8fe09dd9360b0648418798 Mon Sep 17 00:00:00 2001 From: igiannakas Date: Mon, 4 Mar 2024 12:37:46 +0000 Subject: [PATCH 4/6] Code clean up and consolidation --- src/libslic3r/PerimeterGenerator.cpp | 101 --------------------------- 1 file changed, 101 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 97488756062..55e05456cab 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -2569,107 +2569,6 @@ void PerimeterGenerator::process_arachne() } - if (this->config->wall_sequence == WallSequence::MiddleOuterInner && layer_id > 0) { // only enable middle outer inner algorithm after first layer - if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do middle outer inner ordering - int position = 0; // index to run the re-ordering for multiple external perimeters in a single island. - int arr_i, arr_j = 0; // indexes to run through the walls in the for loops - int outer, first_internal, second_internal, max_internal, current_perimeter; // allocate index values - - // Initiate reorder sequence to bring any index 1 (first internal) perimeters ahead of any second internal perimeters - // Leaving these out of order will result in print defects on the external wall as they will be extruded prior to any - // external wall. To do the re-ordering, we are creating two extrusion arrays - reordered_extrusions which will contain - // the reordered extrusions and skipped_extrusions will contain the ones that were skipped in the scan - std::vector reordered_extrusions, skipped_extrusions; - bool found_second_internal = false; // helper variable to indicate the start of a new island - - for(auto extrusion_to_reorder : ordered_extrusions){ //scan the perimeters to reorder - switch (extrusion_to_reorder.extrusion->inset_idx) { - case 0: // external perimeter - if(found_second_internal){ //new island - move skipped extrusions to reordered array - for(auto extrusion_skipped : skipped_extrusions) - reordered_extrusions.emplace_back(extrusion_skipped); - skipped_extrusions.clear(); - } - reordered_extrusions.emplace_back(extrusion_to_reorder); - break; - case 1: // first internal perimeter - reordered_extrusions.emplace_back(extrusion_to_reorder); - break; - default: // second internal+ perimeter -> put them in the skipped extrusions array - skipped_extrusions.emplace_back(extrusion_to_reorder); - found_second_internal = true; - break; - } - } - if(ordered_extrusions.size()>reordered_extrusions.size()){ - // we didnt find any more islands, so lets move the remaining skipped perimeters to the reordered extrusions list. - for(auto extrusion_skipped : skipped_extrusions) - reordered_extrusions.emplace_back(extrusion_skipped); - skipped_extrusions.clear(); - } - - // Now start the sandwich mode wall re-ordering using the reordered_extrusions as the basis - // scan to find the external perimeter, first internal, second internal and last perimeter in the island. - // We then advance the position index to move to the second island and continue until there are no more - // perimeters left. - while (position < reordered_extrusions.size()) { - outer = first_internal = second_internal = current_perimeter = -1; // initialise all index values to -1 - max_internal = reordered_extrusions.size()-1; // initialise the maximum internal perimeter to the last perimeter on the extrusion list - // run through the walls to get the index values that need re-ordering until the first one for each - // is found. Start at "position" index to enable the for loop to iterate for multiple external - // perimeters in a single island - // printf("Reorder Loop. Position %d, extrusion list size: %d, Outer index %d, inner index %d, second inner index %d\n", position, reordered_extrusions.size(),outer,first_internal,second_internal); - for (arr_i = position; arr_i < reordered_extrusions.size(); ++arr_i) { - switch (reordered_extrusions[arr_i].extrusion->inset_idx) { - case 0: // external perimeter - if (outer == -1) - outer = arr_i; - break; - case 1: // first internal wall - if (first_internal==-1 && arr_i>outer && outer!=-1){ - first_internal = arr_i; - } - break; - case 2: // second internal wall - if (second_internal == -1 && arr_i > first_internal && outer!=-1){ - second_internal = arr_i; - } - break; - } - if(outer >-1 && first_internal>-1 && second_internal>-1 && ordered_extrusions[arr_i].extrusion->inset_idx == 0){ // found a new external perimeter after we've found all three perimeters to re-order -> this means we entered a new island. - arr_i=arr_i-1; //step back one perimeter - max_internal = arr_i; // new maximum internal perimeter is now this as we have found a new external perimeter, hence a new island. - break; // exit the for loop - } - } - - // printf("Layer ID %d, Outer index %d, inner index %d, second inner index %d, maximum internal perimeter %d \n",layer_id,outer,first_internal,second_internal, max_internal); - if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order? - std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering - - for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out for all perimers except any that have inset index 2 (second internal). These will be printed last - if(reordered_extrusions[arr_j].extrusion->inset_idx!=2){ - //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); - inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); - } - } - for (arr_j = max_internal; arr_j >=position; --arr_j){ // print any inset index 2 perimeters that were skipped before - if(reordered_extrusions[arr_j].extrusion->inset_idx==2){ - //printf("Inside out loop: Mapped perimeter index %d to array position %d\n", arr_j, max_internal-arr_j); - inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); - } - } - - for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array - ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; - } else - break; - // go to the next perimeter from the current position to continue scanning for external walls in the same island - position = arr_i + 1; - } - } - } - bool steep_overhang_contour = false; bool steep_overhang_hole = false; const WallDirection wall_direction = config->wall_direction; From 25defe94fc21a42d64fc3c07b8946c645528509c Mon Sep 17 00:00:00 2001 From: igiannakas Date: Mon, 4 Mar 2024 12:40:13 +0000 Subject: [PATCH 5/6] Comments & code clean up --- src/libslic3r/PerimeterGenerator.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 55e05456cab..aea5b5ea8f0 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -2522,8 +2522,9 @@ void PerimeterGenerator::process_arachne() // printf("Layer ID %d, Outer index %d, inner index %d, second inner index %d, maximum internal perimeter %d \n",layer_id,outer,first_internal,second_internal, max_internal); if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order? + std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering + //Inner Outer Inner wall mode if(this->config->wall_sequence == WallSequence::InnerOuterInner){ - std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering inner_outer_extrusions.reserve(max_internal - position + 1); // reserve array containing the number of perimeters before a new island. Variables are array indexes hence need to add +1 to convert to position allocations // printf("Allocated array size %d, max_internal index %d, start position index %d \n",max_internal-position+1,max_internal,position); @@ -2542,10 +2543,8 @@ void PerimeterGenerator::process_arachne() for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; - }else + }else //Middle Outer Inner wall mode if(this->config->wall_sequence == WallSequence::MiddleOuterInner){ - std::vector inner_outer_extrusions; // temporary array to hold extrusions for reordering - for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out for all perimers except any that have inset index 2 (second internal). These will be printed last if(reordered_extrusions[arr_j].extrusion->inset_idx!=2){ inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); @@ -2556,7 +2555,6 @@ void PerimeterGenerator::process_arachne() inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); } } - for(arr_j = position; arr_j <= max_internal; ++arr_j) // replace perimeter array with the new re-ordered array ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; } From adc94a38bae30c0d364f07e6bc11185e7480d61d Mon Sep 17 00:00:00 2001 From: igiannakas Date: Wed, 6 Mar 2024 17:28:43 +0000 Subject: [PATCH 6/6] Changed wall ordering to go outside-in for the internal perimeters. --- src/libslic3r/PerimeterGenerator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index aea5b5ea8f0..4f95088ac36 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -2545,13 +2545,13 @@ void PerimeterGenerator::process_arachne() ordered_extrusions[arr_j] = inner_outer_extrusions[arr_j-position]; }else //Middle Outer Inner wall mode if(this->config->wall_sequence == WallSequence::MiddleOuterInner){ - for (arr_j = max_internal; arr_j >=position; --arr_j){ // go inside out for all perimers except any that have inset index 2 (second internal). These will be printed last - if(reordered_extrusions[arr_j].extrusion->inset_idx!=2){ + for (arr_j = max_internal; arr_j >=position; --arr_j){ // print the first internal and external perimeters inside out + if(reordered_extrusions[arr_j].extrusion->inset_idx<2){ inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); } } - for (arr_j = max_internal; arr_j >=position; --arr_j){ // print any inset index 2 perimeters that were skipped before - if(reordered_extrusions[arr_j].extrusion->inset_idx==2){ + for (arr_j = position; arr_j <=max_internal; ++arr_j){ // print the remaining perimeters outside in + if(reordered_extrusions[arr_j].extrusion->inset_idx>=2){ inner_outer_extrusions.emplace_back(reordered_extrusions[arr_j]); } }