forked from Ultimaker/CuraEngine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
WallsComputation.cpp
131 lines (117 loc) · 5.33 KB
/
WallsComputation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//Copyright (c) 2020 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#include "ExtruderTrain.h"
#include "sliceDataStorage.h"
#include "WallsComputation.h"
#include "settings/types/Ratio.h"
#include "WallToolPaths.h"
#include "utils/polygonUtils.h"
#include "Application.h"
#include "Slice.h"
namespace cura {
WallsComputation::WallsComputation(const Settings& settings, const LayerIndex layer_nr)
: settings(settings)
, layer_nr(layer_nr)
{
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateWalls only reads and writes data for the current layer
*/
void WallsComputation::generateWalls(SliceLayerPart* part)
{
size_t wall_count = settings.get<size_t>("wall_line_count");
if (wall_count == 0) // Early out if no walls are to be generated
{
part->print_outline = part->outline;
part->inner_area = part->outline;
return;
}
const bool spiralize = settings.get<bool>("magic_spiralize");
const size_t alternate = ((layer_nr % 2) + 2) % 2;
if (spiralize && layer_nr < LayerIndex(settings.get<size_t>("initial_bottom_layers")) && alternate == 1) //Add extra insets every 2 layers when spiralizing. This makes bottoms of cups watertight.
{
wall_count += 5;
}
if (settings.get<bool>("alternate_extra_perimeter"))
{
wall_count += alternate;
}
const bool first_layer = layer_nr == 0;
const Ratio line_width_0_factor = first_layer ? settings.get<ExtruderTrain&>("wall_0_extruder_nr").settings.get<Ratio>("initial_layer_line_width_factor") : 1.0_r;
const coord_t line_width_0 = settings.get<coord_t>("wall_line_width_0") * line_width_0_factor;
const coord_t wall_0_inset = settings.get<coord_t>("wall_0_inset");
const Ratio line_width_x_factor = first_layer ? settings.get<ExtruderTrain&>("wall_x_extruder_nr").settings.get<Ratio>("initial_layer_line_width_factor") : 1.0_r;
const coord_t line_width_x = settings.get<coord_t>("wall_line_width_x") * line_width_x_factor;
// When spiralizing, generate the spiral insets using simple offsets instead of generating toolpaths
if (spiralize)
{
const bool recompute_outline_based_on_outer_wall =
settings.get<bool>("support_enable") && !settings.get<bool>("fill_outline_gaps");
generateSpiralInsets(part, line_width_0, wall_0_inset, recompute_outline_based_on_outer_wall);
if (layer_nr <= static_cast<LayerIndex>(settings.get<size_t>("bottom_layers")))
{
WallToolPaths wall_tool_paths(part->outline, line_width_0, line_width_x, wall_count, settings);
part->wall_toolpaths = wall_tool_paths.getToolPaths();
part->inner_area = wall_tool_paths.getInnerContour();
}
}
else
{
WallToolPaths wall_tool_paths(part->outline, line_width_0, line_width_x, wall_count, wall_0_inset, settings);
part->wall_toolpaths = wall_tool_paths.getToolPaths();
part->inner_area = wall_tool_paths.getInnerContour();
}
part->print_outline = part->outline;
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateWalls only reads and writes data for the current layer
*/
void WallsComputation::generateWalls(SliceLayer* layer)
{
for(SliceLayerPart& part : layer->parts)
{
generateWalls(&part);
}
//Remove the parts which did not generate a wall. As these parts are too small to print,
// and later code can now assume that there is always minimal 1 wall line.
if(settings.get<size_t>("wall_line_count") >= 1 && !settings.get<bool>("fill_outline_gaps"))
{
for(size_t part_idx = 0; part_idx < layer->parts.size(); part_idx++)
{
if (layer->parts[part_idx].wall_toolpaths.empty() && layer->parts[part_idx].spiral_wall.empty())
{
if (part_idx != layer->parts.size() - 1)
{ // move existing part into part to be deleted
layer->parts[part_idx] = std::move(layer->parts.back());
}
layer->parts.pop_back(); // always remove last element from array (is more efficient)
part_idx -= 1; // check the part we just moved here
}
}
}
}
void WallsComputation::generateSpiralInsets(SliceLayerPart *part, coord_t line_width_0, coord_t wall_0_inset, bool recompute_outline_based_on_outer_wall)
{
part->spiral_wall = part->outline.offset(-line_width_0 / 2 - wall_0_inset);
//Optimize the wall. This prevents buffer underruns in the printer firmware, and reduces processing time in CuraEngine.
const ExtruderTrain& train_wall = settings.get<ExtruderTrain&>("wall_0_extruder_nr");
const coord_t maximum_resolution = train_wall.settings.get<coord_t>("meshfix_maximum_resolution");
const coord_t maximum_deviation = train_wall.settings.get<coord_t>("meshfix_maximum_deviation");
part->spiral_wall.simplify(maximum_resolution, maximum_deviation);
part->spiral_wall.removeDegenerateVerts();
if (recompute_outline_based_on_outer_wall)
{
part->print_outline = part->spiral_wall.offset(line_width_0 / 2, ClipperLib::jtSquare);
}
else
{
part->print_outline = part->outline;
}
}
}//namespace cura