Skip to content

Commit cd70a6e

Browse files
authored
CURA-12992 Fix slicing crashes (#2301)
2 parents 62efbe0 + 956e63c commit cd70a6e

12 files changed

Lines changed: 218 additions & 77 deletions

include/WallToolPaths.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ class WallToolPaths
102102
*
103103
* Works on both toolpaths and inner contours simultaneously.
104104
*
105-
* \param settings The settings as provided by the user
105+
* \param stitch_distance The stitch distance to be used
106106
*/
107-
static void stitchToolPaths(std::vector<VariableWidthLines>& toolpaths, const Settings& settings);
107+
static void stitchToolPaths(std::vector<VariableWidthLines>& toolpaths, const coord_t stitch_distance);
108108

109109
/*!
110110
* Remove polylines shorter than half the smallest line width along that polyline, if that polyline isn't part of an outer wall.
@@ -128,8 +128,16 @@ class WallToolPaths
128128
bool print_thin_walls_; //<! Whether to enable the widening beading meta-strategy for thin features
129129
coord_t min_feature_size_; //<! The minimum size of the features that can be widened by the widening beading meta-strategy. Features thinner than that will not be printed
130130
coord_t min_bead_width_; //<! The minimum bead size to use when widening thin model features with the widening beading meta-strategy
131-
double small_area_length_; //<! The length of the small features which are to be filtered out, this is squared into a surface
132-
coord_t transition_length_; //<! The transitioning length when the amount of extrusion lines changes
131+
const AngleRadians wall_transition_angle_;
132+
const coord_t wall_transition_length_;
133+
const double min_even_wall_line_width_;
134+
const double wall_line_width_0_;
135+
const double min_odd_wall_line_width_;
136+
const double wall_line_width_x_;
137+
const int wall_distribution_count_;
138+
const coord_t wall_transition_filter_distance_;
139+
const coord_t wall_transition_filter_deviation_;
140+
const coord_t stitch_distance_;
133141
bool toolpaths_generated_; //<! Are the toolpaths generated
134142
std::vector<VariableWidthLines> toolpaths_; //<! The generated toolpaths binned by inset_idx.
135143
Shape inner_contour_; //<! The inner contour of the generated toolpaths

include/arachne/SkeletalTrapezoidation.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "utils/ExtrusionJunction.h"
2121
#include "utils/ExtrusionLine.h"
2222
#include "utils/PolygonsSegmentIndex.h"
23+
#include "utils/VoronoiUtils.h"
2324
#include "utils/section_type.h"
2425

2526
namespace cura
@@ -46,8 +47,8 @@ deposition modeling" by Kuipers et al.
4647
*/
4748
class SkeletalTrapezoidation
4849
{
49-
using pos_t = double;
50-
using vd_t = boost::polygon::voronoi_diagram<pos_t>;
50+
using pos_t = VoronoiUtils::voronoi_data_t;
51+
using vd_t = VoronoiUtils::vd_t;
5152
using graph_t = SkeletalTrapezoidationGraph;
5253
using edge_t = STHalfEdge;
5354
using node_t = STHalfEdgeNode;
@@ -248,7 +249,8 @@ class SkeletalTrapezoidation
248249
vd_t::edge_type*& starting_vd_edge,
249250
vd_t::edge_type*& ending_vd_edge,
250251
const std::vector<Point2LL>& points,
251-
const std::vector<Segment>& segments);
252+
const std::vector<Segment>& segments,
253+
const Shape& polys);
252254

253255
/*!
254256
* Compute the range of line segments that surround a cell of the skeletal

include/arachne/SkeletalTrapezoidationEdge.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ class SkeletalTrapezoidationEdge
123123
{
124124
extrusion_junctions_ = storage;
125125
}
126-
std::shared_ptr<LineJunctions> getExtrusionJunctions()
126+
std::shared_ptr<LineJunctions> getExtrusionJunctions() const
127127
{
128-
return extrusion_junctions_.lock();
128+
return const_cast<SkeletalTrapezoidationEdge*>(this)->extrusion_junctions_.lock();
129129
}
130130

131131
Central is_central; //! whether the edge is significant; whether the source segments have a sharp angle; -1 is unknown

include/infill.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ class Infill
384384
Shape& result_polygons,
385385
OpenLinesSet& result_lines,
386386
const Settings& settings,
387+
const int layer_idx,
387388
const std::shared_ptr<SierpinskiFillProvider>& cross_fill_pattern,
388389
const std::shared_ptr<LightningLayer>& lightning_layer,
389390
const SliceMeshStorage* mesh,
@@ -398,6 +399,7 @@ class Infill
398399
Shape& result_polygons,
399400
OpenLinesSet& result_lines,
400401
const Settings& settings,
402+
const int layer_idx,
401403
const std::shared_ptr<SierpinskiFillProvider>& cross_fill_pattern,
402404
const std::shared_ptr<LightningLayer>& lightning_layer,
403405
const SliceMeshStorage* mesh);
@@ -446,10 +448,11 @@ class Infill
446448
/*!
447449
* Generate sparse concentric infill
448450
*
449-
* \param toolpaths (output) The resulting toolpaths. Binned by inset_idx.
450-
* \param inset_value The offset between each consecutive two polygons
451+
* \param[out] toolpaths The resulting toolpaths. Binned by inset_idx.
452+
* \param settings The settings to be used for processing
453+
* \param layer_idx The current layer index
451454
*/
452-
void generateConcentricInfill(const Shape& outline, std::vector<VariableWidthLines>& toolpaths, const Settings& settings);
455+
void generateConcentricInfill(const Shape& outline, std::vector<VariableWidthLines>& toolpaths, const Settings& settings, const int layer_idx);
453456

454457
/*!
455458
* Generate a rectangular grid of infill lines

include/utils/SVG.h

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Point2D;
2121
class MixedLinesSet;
2222
class SkeletalTrapezoidationGraph;
2323
class STHalfEdge;
24+
class STHalfEdgeNode;
2425

2526
class SVG : NoCopy
2627
{
@@ -144,6 +145,10 @@ class SVG : NoCopy
144145

145146
~LineAttributes() override = default;
146147

148+
static LineAttributes hidden()
149+
{
150+
return LineAttributes(ColorObject(), 0.0);
151+
}
147152
bool isDisplayed() const override
148153
{
149154
return ElementAttributes::isDisplayed() && width > 0.0;
@@ -158,6 +163,14 @@ class SVG : NoCopy
158163

159164
VerticesAttributes() = default;
160165

166+
VerticesAttributes(const ColorObject& color, const double radius, const bool write_coords, const double font_size)
167+
: ElementAttributes(color)
168+
, radius(radius)
169+
, write_coords(write_coords)
170+
, font_size(font_size)
171+
{
172+
}
173+
161174
VerticesAttributes(const ColorObject& color, const double radius)
162175
: ElementAttributes(color)
163176
, radius(radius)
@@ -183,6 +196,11 @@ class SVG : NoCopy
183196

184197
~VerticesAttributes() override = default;
185198

199+
static VerticesAttributes hidden()
200+
{
201+
return VerticesAttributes(SVG::ColorObject(), 0.0);
202+
}
203+
186204
bool isDisplayed() const override
187205
{
188206
return ElementAttributes::isDisplayed() && (radius > 0.0 || (write_coords && font_size > 0.0));
@@ -196,6 +214,33 @@ class SVG : NoCopy
196214
VerticesAttributes vertices{ ColorObject(), 0.0 };
197215
};
198216

217+
struct DiagramVisualAttributes : VisualAttributes
218+
{
219+
bool edges_arrows{ true };
220+
221+
DiagramVisualAttributes(const VisualAttributes& visual_attributes, const bool edges_arrows = true)
222+
: VisualAttributes(visual_attributes)
223+
, edges_arrows(edges_arrows)
224+
{
225+
}
226+
};
227+
228+
struct STVisualAttributes : DiagramVisualAttributes
229+
{
230+
VerticesAttributes beads_count;
231+
VerticesAttributes junctions;
232+
233+
STVisualAttributes(
234+
const DiagramVisualAttributes& diagram_attributes,
235+
const VerticesAttributes& beads_count = VerticesAttributes::hidden(),
236+
const VerticesAttributes& junctions = VerticesAttributes::hidden())
237+
: DiagramVisualAttributes(diagram_attributes)
238+
, beads_count(beads_count)
239+
, junctions(junctions)
240+
{
241+
}
242+
};
243+
199244
private:
200245
static std::string toString(const ColorObject& color);
201246
static std::string toString(const std::vector<int>& dash_array);
@@ -260,18 +305,18 @@ class SVG : NoCopy
260305

261306
void write(const std::string& text, const Point2LL& p, const VerticesAttributes& vertices_attributes, const bool flush = true) const;
262307

263-
void write(const SkeletalTrapezoidationGraph& graph, const VisualAttributes& visual_attributes, const bool flush = true) const;
308+
void write(const SkeletalTrapezoidationGraph& graph, const STVisualAttributes& visual_attributes, const bool flush = true) const;
264309

265-
void write(const STHalfEdge& edge, const VisualAttributes& visual_attributes, const bool flush = true) const;
310+
void write(const STHalfEdge& edge, const STVisualAttributes& visual_attributes, const bool flush = true, const std::set<const STHalfEdgeNode*>& drawn_nodes = {}) const;
266311

267312
template<typename T>
268-
void write(const boost::polygon::voronoi_diagram<T>& voronoi_diagram, const VisualAttributes& visual_attributes, const bool flush = true) const;
313+
void write(const boost::polygon::voronoi_diagram<T>& voronoi_diagram, const DiagramVisualAttributes& visual_attributes, const bool flush = true) const;
269314

270315
template<typename T>
271-
void write(const boost::polygon::voronoi_edge<T>& edge, const VisualAttributes& visual_attributes, const bool flush = true) const;
316+
void write(const boost::polygon::voronoi_edge<T>& edge, const DiagramVisualAttributes& visual_attributes, const bool flush = true) const;
272317

273318
template<typename T>
274-
void write(const boost::polygon::voronoi_cell<T>& cell, const VisualAttributes& visual_attributes, const bool flush = true) const;
319+
void write(const boost::polygon::voronoi_cell<T>& cell, const DiagramVisualAttributes& visual_attributes, const bool flush = true) const;
275320

276321
void writeArrow(const Point2LL& a, const Point2LL& b, const ColorObject color = Color::BLACK, const double stroke_width = 1.0, const double head_size = 5.0) const;
277322

include/utils/VoronoiUtils.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,27 @@
1212
#include "PolygonsSegmentIndex.h"
1313

1414

15+
namespace boost::polygon
16+
{
17+
template<>
18+
struct voronoi_diagram_traits<cura::coord_t>
19+
{
20+
typedef cura::coord_t coordinate_type;
21+
typedef voronoi_cell<coordinate_type> cell_type;
22+
typedef voronoi_vertex<coordinate_type> vertex_type;
23+
typedef voronoi_edge<coordinate_type> edge_type;
24+
25+
class vertex_equality_predicate_type
26+
{
27+
public:
28+
bool operator()(const vertex_type& v1, const vertex_type& v2) const
29+
{
30+
return v1.x() == v2.x() && v1.y() == v2.y();
31+
}
32+
};
33+
};
34+
} // namespace boost::polygon
35+
1536
namespace cura
1637
{
1738

@@ -21,7 +42,7 @@ class VoronoiUtils
2142
{
2243
public:
2344
using Segment = PolygonsSegmentIndex;
24-
using voronoi_data_t = double;
45+
using voronoi_data_t = coord_t;
2546
using vd_t = boost::polygon::voronoi_diagram<voronoi_data_t>;
2647

2748
static Point2LL getSourcePoint(const vd_t::cell_type& cell, const std::vector<Point2LL>& points, const std::vector<Segment>& segments);
@@ -30,9 +51,9 @@ class VoronoiUtils
3051

3152
static Point2LL p(const vd_t::vertex_type* node);
3253

33-
static bool isSourcePoint(Point2LL p, const vd_t::cell_type& cell, const std::vector<Point2LL>& points, const std::vector<Segment>& segments, coord_t snap_dist = 10);
54+
static bool isSourcePoint(const Point2LL& p, const vd_t::cell_type& cell, const std::vector<Point2LL>& points, const std::vector<Segment>& segments, coord_t snap_dist = 10);
3455

35-
static coord_t getDistance(Point2LL p, const vd_t::cell_type& cell, const std::vector<Point2LL>& points, const std::vector<Segment>& segments);
56+
static coord_t getDistance(const Point2LL& p, const vd_t::cell_type& cell, const std::vector<Point2LL>& points, const std::vector<Segment>& segments);
3657

3758
/*!
3859
* Discretize a parabola based on (approximate) step size.

src/TreeModelVolumes.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -902,15 +902,17 @@ void TreeModelVolumes::calculateCollisionAvoidance(const std::deque<RadiusLayerP
902902
// defined by the collision when offsetting to fast.
903903
Shape TreeModelVolumes::safeOffset(const Shape& me, coord_t distance, ClipperLib::JoinType jt, coord_t max_safe_step_distance, const Shape& collision) const
904904
{
905-
const size_t steps = std::abs(distance / std::max(min_offset_per_step_, std::abs(max_safe_step_distance)));
906-
assert(distance * max_safe_step_distance >= 0);
905+
assert(distance * max_safe_step_distance >= 0); // Make sure they are the same sign (or one of them is null)
906+
const uint8_t offset_sign = sign(distance);
907+
const coord_t step_distance = offset_sign * std::max(min_offset_per_step_, std::abs(max_safe_step_distance));
908+
const size_t steps = std::abs(distance / step_distance);
907909
Shape ret = me;
908910

909911
for (size_t i = 0; i < steps; ++i)
910912
{
911-
ret = ret.offset(max_safe_step_distance, jt).unionPolygons(collision);
913+
ret = ret.offset(step_distance, jt).unionPolygons(collision);
912914
}
913-
ret = ret.offset(distance % max_safe_step_distance, jt);
915+
ret = ret.offset(distance % step_distance, jt);
914916

915917
return ret.unionPolygons(collision);
916918
}

src/WallToolPaths.cpp

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,18 @@ WallToolPaths::WallToolPaths(
3636
, inset_count_(inset_count)
3737
, wall_0_inset_(wall_0_inset)
3838
, print_thin_walls_(settings.get<bool>("fill_outline_gaps"))
39-
, min_feature_size_(settings.get<coord_t>("min_feature_size"))
40-
, min_bead_width_(settings.get<coord_t>("min_bead_width"))
41-
, small_area_length_(INT2MM(static_cast<double>(nominal_bead_width) / 2))
39+
, min_feature_size_(nominal_bead_width / 4)
40+
, min_bead_width_(std::min(min_even_wall_line_width_, min_odd_wall_line_width_))
41+
, wall_transition_angle_(AngleDegrees(10))
42+
, wall_transition_length_(nominal_bead_width)
43+
, min_even_wall_line_width_(std::llrint(nominal_bead_width * 0.85))
44+
, wall_line_width_0_(nominal_bead_width)
45+
, min_odd_wall_line_width_(min_even_wall_line_width_)
46+
, wall_line_width_x_(nominal_bead_width)
47+
, wall_distribution_count_(1)
48+
, wall_transition_filter_distance_(MM2INT(100))
49+
, wall_transition_filter_deviation_(nominal_bead_width / 4)
50+
, stitch_distance_(nominal_bead_width - 1)
4251
, toolpaths_generated_(false)
4352
, settings_(settings)
4453
, layer_idx_(layer_idx)
@@ -63,7 +72,16 @@ WallToolPaths::WallToolPaths(
6372
, print_thin_walls_(settings.get<bool>("fill_outline_gaps"))
6473
, min_feature_size_(settings.get<coord_t>("min_feature_size"))
6574
, min_bead_width_(settings.get<coord_t>("min_bead_width"))
66-
, small_area_length_(INT2MM(static_cast<double>(bead_width_0) / 2))
75+
, wall_transition_angle_(settings.get<AngleRadians>("wall_transition_angle"))
76+
, wall_transition_length_(settings.get<coord_t>("wall_transition_length"))
77+
, min_even_wall_line_width_(settings.get<double>("min_even_wall_line_width"))
78+
, wall_line_width_0_(settings.get<double>("wall_line_width_0"))
79+
, min_odd_wall_line_width_(settings.get<double>("min_odd_wall_line_width"))
80+
, wall_line_width_x_(settings.get<double>("wall_line_width_x"))
81+
, wall_distribution_count_(settings.get<int>("wall_distribution_count"))
82+
, wall_transition_filter_distance_(settings.get<coord_t>("wall_transition_filter_distance"))
83+
, wall_transition_filter_deviation_(settings.get<coord_t>("wall_transition_filter_deviation"))
84+
, stitch_distance_(settings.get<coord_t>("wall_line_width_x") - 1) // In 0-width contours, junctions can cause up to 1-line-width gaps. Don't stitch more than 1 line width.
6785
, toolpaths_generated_(false)
6886
, settings_(settings)
6987
, layer_idx_(layer_idx)
@@ -80,45 +98,37 @@ const std::vector<VariableWidthLines>& WallToolPaths::generate()
8098
return toolpaths_;
8199
}
82100

83-
const auto transitioning_angle = settings_.get<AngleRadians>("wall_transition_angle");
101+
84102
constexpr coord_t discretization_step_size = MM2INT(0.8);
85-
const coord_t wall_transition_length = settings_.get<coord_t>("wall_transition_length");
86103

87104
// When to split the middle wall into two:
88-
const double min_even_wall_line_width = settings_.get<double>("min_even_wall_line_width");
89-
const double wall_line_width_0 = settings_.get<double>("wall_line_width_0");
90-
const Ratio wall_split_middle_threshold = std::max(1.0, std::min(99.0, 100.0 * (2.0 * min_even_wall_line_width - wall_line_width_0) / wall_line_width_0)) / 100.0;
105+
const Ratio wall_split_middle_threshold = std::max(1.0, std::min(99.0, 100.0 * (2.0 * min_even_wall_line_width_ - wall_line_width_0_) / wall_line_width_0_)) / 100.0;
91106

92107
// When to add a new middle in between the innermost two walls:
93-
const double min_odd_wall_line_width = settings_.get<double>("min_odd_wall_line_width");
94-
const double wall_line_width_x = settings_.get<double>("wall_line_width_x");
95-
const Ratio wall_add_middle_threshold = std::max(1.0, std::min(99.0, 100.0 * min_odd_wall_line_width / wall_line_width_x)) / 100.0;
108+
const Ratio wall_add_middle_threshold = std::max(1.0, std::min(99.0, 100.0 * min_odd_wall_line_width_ / wall_line_width_x_)) / 100.0;
96109

97-
const int wall_distribution_count = settings_.get<int>("wall_distribution_count");
98110
const size_t max_bead_count = (inset_count_ < std::numeric_limits<size_t>::max() / 2) ? 2 * inset_count_ : std::numeric_limits<size_t>::max();
99111
const auto beading_strat = BeadingStrategyFactory::makeStrategy(
100112
bead_width_0_,
101113
bead_width_x_,
102-
wall_transition_length,
103-
transitioning_angle,
114+
wall_transition_length_,
115+
wall_transition_angle_,
104116
print_thin_walls_,
105117
min_bead_width_,
106118
min_feature_size_,
107119
wall_split_middle_threshold,
108120
wall_add_middle_threshold,
109121
max_bead_count,
110122
wall_0_inset_,
111-
wall_distribution_count);
112-
const auto transition_filter_dist = settings_.get<coord_t>("wall_transition_filter_distance");
113-
const auto allowed_filter_deviation = settings_.get<coord_t>("wall_transition_filter_deviation");
123+
wall_distribution_count_);
114124
SkeletalTrapezoidation wall_maker(
115125
prepared_outline,
116126
*beading_strat,
117127
beading_strat->getTransitioningAngle(),
118128
discretization_step_size,
119-
transition_filter_dist,
120-
allowed_filter_deviation,
121-
wall_transition_length,
129+
wall_transition_filter_distance_,
130+
wall_transition_filter_deviation_,
131+
wall_transition_length_,
122132
layer_idx_,
123133
section_type_);
124134
wall_maker.generateToolpaths(toolpaths_);
@@ -133,7 +143,7 @@ const std::vector<VariableWidthLines>& WallToolPaths::generate()
133143
scripta::PointVDI{ "width", &ExtrusionJunction::w_ },
134144
scripta::PointVDI{ "perimeter_index", &ExtrusionJunction::perimeter_index_ });
135145

136-
stitchToolPaths(toolpaths_, settings_);
146+
stitchToolPaths(toolpaths_, stitch_distance_);
137147
scripta::log(
138148
"toolpaths_1",
139149
toolpaths_,
@@ -206,11 +216,8 @@ const std::vector<VariableWidthLines>& WallToolPaths::generate()
206216
}
207217

208218

209-
void WallToolPaths::stitchToolPaths(std::vector<VariableWidthLines>& toolpaths, const Settings& settings)
219+
void WallToolPaths::stitchToolPaths(std::vector<VariableWidthLines>& toolpaths, const coord_t stitch_distance)
210220
{
211-
const coord_t stitch_distance
212-
= settings.get<coord_t>("wall_line_width_x") - 1; // In 0-width contours, junctions can cause up to 1-line-width gaps. Don't stitch more than 1 line width.
213-
214221
for (unsigned int wall_idx = 0; wall_idx < toolpaths.size(); wall_idx++)
215222
{
216223
VariableWidthLines& wall_lines = toolpaths[wall_idx];

0 commit comments

Comments
 (0)