mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-08 07:27:41 -06:00
Updated inner outer inner algorithm to cater for edge case where an internal island with two perimeters on both sides of an external wall was causing a secondary island to not reorder the walls correctly (#1861)
* Updated inner outer inner algorithm to cater for edge case where an internal island with multiple internal perimeters would cause the external island to fall back to outer-> inner wall ordering. Updated inner outer inner algorithm to cater for edge case where an internal island with multiple internal perimeters would cause the external island to fall back to outer-> inner wall ordering. * Reworked the inner outer inner algorithm to better work with more than 3 perimeters. * Code comment updates. Removed error check code. * Cleaned up code and comments Cleaned up code and comments * Disabled inner outer inner algorithm on first layer Disabling inner outer inner algorithm and using inner to outer wall ordering to promote bed adhesion as having isolated perimeters on the bed has resulted on occasion to warping or incomplete adherence to the bed. * Code optimisation
This commit is contained in:
parent
7a8f020fcf
commit
c20b01f37a
1 changed files with 63 additions and 33 deletions
|
@ -1885,10 +1885,16 @@ void PerimeterGenerator::process_arachne()
|
|||
int end_perimeter = -1;
|
||||
int direction = -1;
|
||||
|
||||
bool is_outer_wall_first =
|
||||
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill;
|
||||
bool is_outer_wall_first =
|
||||
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill;
|
||||
|
||||
if (layer_id == 0){ // disable inner outer inner algorithm after the first layer
|
||||
is_outer_wall_first =
|
||||
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner;
|
||||
}
|
||||
if (is_outer_wall_first) {
|
||||
start_perimeter = 0;
|
||||
end_perimeter = int(perimeters.size());
|
||||
|
@ -2015,45 +2021,69 @@ void PerimeterGenerator::process_arachne()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill) {
|
||||
// printf("New Layer: Layer ID %d\n",layer_id); //debug - new layer
|
||||
if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill && 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
|
||||
int position = 0; // index to run the re-ordering for multiple external perimeters in a single island.
|
||||
int arr_i = 0; // index to run through the walls
|
||||
int outer, first_internal, second_internal; // allocate index values
|
||||
// run the re-ordering for all wall loops in the same 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
|
||||
// scan to find the external perimeter, first internal, second internal and last perimeter in the island
|
||||
while (position < ordered_extrusions.size()) {
|
||||
outer = first_internal = second_internal = -1; // initialise all index values to -1
|
||||
outer = first_internal = second_internal = current_perimeter = -1; // initialise all index values to -1
|
||||
max_internal = ordered_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, ordered_extrusions.size(),outer,first_internal,second_internal);
|
||||
for (arr_i = position; arr_i < ordered_extrusions.size(); ++arr_i) {
|
||||
// printf("Perimeter: extrusion inset index %d, ordered extrusions array position %d\n",ordered_extrusions[arr_i].extrusion->inset_idx, arr_i);
|
||||
switch (ordered_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)
|
||||
first_internal = arr_i;
|
||||
break;
|
||||
case 2: // second internal wall
|
||||
if (ordered_extrusions[arr_i].extrusion->inset_idx == 2 && second_internal == -1 &&
|
||||
arr_i > first_internal)
|
||||
second_internal = arr_i;
|
||||
break;
|
||||
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){ // found all three perimeters to re-order
|
||||
if(ordered_extrusions[arr_i].extrusion->inset_idx == 0){ // found a new external perimeter -> 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
|
||||
}
|
||||
}
|
||||
if (second_internal != -1)
|
||||
break; // found all three perimeters to re-order
|
||||
}
|
||||
if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order?
|
||||
const auto temp = ordered_extrusions[second_internal];
|
||||
ordered_extrusions[second_internal] = ordered_extrusions[first_internal];
|
||||
ordered_extrusions[first_internal] = ordered_extrusions[outer];
|
||||
ordered_extrusions[outer] = temp;
|
||||
} else
|
||||
break; // did not find any more candidates to re-order, so stop the while loop early
|
||||
// go to the next perimeter to continue scanning for external walls in the same island
|
||||
|
||||
// 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<PerimeterGeneratorArachneExtrusion> 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] = ordered_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] = ordered_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 to continue scanning for external walls in the same island
|
||||
position = arr_i + 1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue