Skip to content

Commit e49466b

Browse files
authored
Merge branch 'main' into CURA-12996_top-surface-expansion-on-sketch-sprint
2 parents ae215cc + cd70a6e commit e49466b

82 files changed

Lines changed: 2265 additions & 856 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ set(engine_SRCS # Except main.cpp.
5353
src/GCodePathConfig.cpp
5454
src/GcodeTemplateResolver.cpp
5555
src/infill.cpp
56-
src/InterlockingGenerator.cpp
56+
src/InfillOrderOptimizer.cpp
5757
src/InsetOrderOptimizer.cpp
58+
src/InterlockingGenerator.cpp
5859
src/layerPart.cpp
5960
src/LayerPlan.cpp
6061
src/LayerPlanBuffer.cpp
@@ -187,6 +188,7 @@ set(engine_SRCS # Except main.cpp.
187188
src/utils/scoring/RandomScoringCriterion.cpp
188189
src/utils/scoring/TextureScoringCriterion.cpp
189190

191+
src/geometry/OpenLinesSet.cpp
190192
src/geometry/Point2LL.cpp
191193
src/geometry/Point3LL.cpp
192194
src/geometry/Polygon.cpp

conandata.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ requirements:
99
requirements_arcus:
1010
- "arcus/5.11.1"
1111
requirements_plugins:
12-
- "curaengine_grpc_definitions/0.3.4"
12+
- "curaengine_grpc_definitions/0.4.1"
1313
requirements_cura_resources:
14-
- "cura_resources/5.14.0-alpha.0"
14+
- "cura_resources/5.14.0-alpha.0@ultimaker/testing"

include/ExtruderPlan.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class ExtruderPlan
4343
FRIEND_TEST(ExtruderPlanPathsParameterizedTest, BackPressureCompensationHalf);
4444
FRIEND_TEST(ExtruderPlanTest, BackPressureCompensationEmptyPlan);
4545
friend class DISABLED_FffGcodeWriterTest_SurfaceGetsExtraInfillLinesUnderIt_Test;
46+
FRIEND_TEST(OverhangSpeedTest, SpeedFactorAppliedWhenMasksSet);
47+
FRIEND_TEST(OverhangSpeedTest, SpeedFactorSplitAtOverhangBoundary);
4648
#endif
4749
public:
4850
size_t extruder_nr_{ 0 }; //!< The extruder used for this paths in the current plan.

include/FffGcodeWriter.h

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "ExtruderUse.h"
1111
#include "FanSpeedLayerTime.h"
1212
#include "GCodePathConfig.h"
13+
#include "LayerPlan.h"
1314
#include "LayerPlanBuffer.h"
1415
#include "LinesOrderingMethod.h"
1516
#include "gcodeExport.h"
@@ -28,6 +29,7 @@ class SliceMeshStorage;
2829
class SliceLayer;
2930
class SliceLayerPart;
3031
struct MeshPathConfigs;
32+
class InsetOrderOptimizer;
3133

3234
/*!
3335
* Secondary stage in Fused Filament Fabrication processing: The generated polygons are used in the gcode generation.
@@ -160,6 +162,14 @@ class FffGcodeWriter : public NoCopy
160162
std::string monotonic;
161163
};
162164

165+
/*! Helper structure to pre-process then later add the optimized insets */
166+
struct InsetsPreprocessResult
167+
{
168+
std::shared_ptr<InsetOrderOptimizer> walls_optimizer{}; // Contains the ready-to-add optimized insets
169+
bool spiralize{ false }; // Indicates whether this layer is a regular or a spiral layer
170+
std::vector<LayerPlan::OverhangMask> overhang_masks{}; // Overhang speed masks to be applied only while drawing the walls
171+
};
172+
163173
static const RoofingFlooringSettingsNames roofing_settings_names;
164174
static const RoofingFlooringSettingsNames flooring_settings_names;
165175

@@ -398,6 +408,7 @@ class FffGcodeWriter : public NoCopy
398408
* mesh which should be printed with this extruder.
399409
* \param mesh_config the line config with which to print a print feature.
400410
* \param part The part for which to create gcode.
411+
* \param near_end_location The location where the infill should preferably end close to
401412
* \return Whether this function added anything to the layer plan.
402413
*/
403414
bool processInfill(
@@ -406,7 +417,8 @@ class FffGcodeWriter : public NoCopy
406417
const SliceMeshStorage& mesh,
407418
const size_t extruder_nr,
408419
const MeshPathConfigs& mesh_config,
409-
const SliceLayerPart& part) const;
420+
const SliceLayerPart& part,
421+
const std::optional<Point2LL>& near_end_location = std::nullopt) const;
410422

411423
/*!
412424
* \brief Add thicker (multiple layers) sparse infill for a given part in a
@@ -420,6 +432,8 @@ class FffGcodeWriter : public NoCopy
420432
* \param part The part for which to create gcode.
421433
* \param start_move_inwards_length The length of the extra inwards moves to be added at the start of each infill line
422434
* \param end_move_inwards_length The length of the extra inwards moves to be added at the end of each infill line
435+
* \param near_end_location The location where the infill should preferably end close to
436+
* \param split_near_end_location If true, the infill open polyline that passes closer to the near_end_location will be split to provide a proper start/end position
423437
* \return Whether this function added anything to the layer plan.
424438
*/
425439
bool processMultiLayerInfill(
@@ -429,7 +443,9 @@ class FffGcodeWriter : public NoCopy
429443
const MeshPathConfigs& mesh_config,
430444
const SliceLayerPart& part,
431445
const coord_t start_move_inwards_length = 0,
432-
const coord_t end_move_inwards_length = 0) const;
446+
const coord_t end_move_inwards_length = 0,
447+
const std::optional<Point2LL>& near_end_location = std::nullopt,
448+
const bool split_near_end_location = false) const;
433449

434450
/*!
435451
* \brief Add normal sparse infill for a given part in a layer.
@@ -441,6 +457,8 @@ class FffGcodeWriter : public NoCopy
441457
* \param part The part for which to create gcode.
442458
* \param start_move_inwards_length The length of the extra inwards moves to be added at the start of each infill line
443459
* \param end_move_inwards_length The length of the extra inwards moves to be added at the end of each infill line
460+
* \param near_end_location The location where the infill should preferably end close to
461+
* \param split_near_end_location If true, the infill open polyline that passes closer to the near_end_location will be split to provide a proper start/end position
444462
* \return Whether this function added anything to the layer plan.
445463
*/
446464
bool processSingleLayerInfill(
@@ -451,25 +469,51 @@ class FffGcodeWriter : public NoCopy
451469
const MeshPathConfigs& mesh_config,
452470
const SliceLayerPart& part,
453471
const coord_t start_move_inwards_length = 0,
454-
const coord_t end_move_inwards_length = 0) const;
472+
const coord_t end_move_inwards_length = 0,
473+
const std::optional<Point2LL>& near_end_location = std::nullopt,
474+
const bool split_near_end_location = false) const;
455475

456476
/*!
457-
* Generate the insets for the walls of a given layer part.
477+
* Generate the insets for the walls of a given layer part, without inserting them to the layer plan
458478
* \param[in] storage where the slice data is stored.
459479
* \param gcodeLayer The initial planning of the gcode of the layer.
460480
* \param mesh The mesh for which to add to the layer plan \p gcodeLayer.
461481
* \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder
462-
* \param mesh_config the line config with which to print a print feature
482+
* \param mesh_config The extruder for which to print all features of the mesh which should be printed with this extruder
463483
* \param part The part for which to create gcode
464-
* \return Whether this function added anything to the layer plan
484+
* \param end_infill_close_to_seam Indicates whether the infill will end close to the seam, in which case we can slightly adjust the insets ordering
485+
* \return The content to be later inserted
465486
*/
466-
bool processInsets(
487+
InsetsPreprocessResult preProcessInsets(
467488
const SliceDataStorage& storage,
468489
LayerPlan& gcodeLayer,
469490
const SliceMeshStorage& mesh,
470491
const size_t extruder_nr,
471492
const MeshPathConfigs& mesh_config,
472-
SliceLayerPart& part) const;
493+
SliceLayerPart& part,
494+
const bool end_infill_close_to_seam) const;
495+
496+
/*!
497+
* Inserts the previously processed insets
498+
* @param preprocess_result The pre-processed insets to be added
499+
* @param storage storage where the slice data is stored.
500+
* @param gcode_layer The initial planning of the gcode of the layer.
501+
* @param mesh The mesh for which to add to the layer plan \p gcodeLayer.
502+
* @param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder
503+
* @param mesh_config The extruder for which to print all features of the mesh which should be printed with this extruder
504+
* @param part The part for which to create gcode
505+
* @param infill_added Indicates whether infill was added just before
506+
* @return Whether this function added anything to the layer plan
507+
*/
508+
bool endProcessInsets(
509+
InsetsPreprocessResult& preprocess_result,
510+
const SliceDataStorage& storage,
511+
LayerPlan& gcode_layer,
512+
const SliceMeshStorage& mesh,
513+
const size_t extruder_nr,
514+
const MeshPathConfigs& mesh_config,
515+
SliceLayerPart& part,
516+
const bool infill_added) const;
473517

474518
/*!
475519
* Generate the a spiralized wall for a given layer part.

include/ForceRetract.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) 2026 UltiMaker B.V.
2+
// CuraEngine is released under the terms of the AGPLv3 or higher.
3+
4+
#ifndef FORCERETRACT_H
5+
#define FORCERETRACT_H
6+
7+
namespace cura
8+
{
9+
10+
/*!
11+
* Whether to force a retracted or unretracted travel move
12+
*/
13+
enum class ForceRetract
14+
{
15+
AUTOMATIC, // Let retraction be calculated automatically for the travel move
16+
RETRACTED, // Force travel move to be retracted
17+
NOT_RETRACTED, // Force travel move not to be retracted
18+
};
19+
20+
} // namespace cura
21+
22+
#endif

include/GCodePathConfig.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
#ifndef G_CODE_PATH_CONFIG_H
55
#define G_CODE_PATH_CONFIG_H
66

7+
#include <optional>
8+
79
#include "PrintFeature.h"
810
#include "pathPlanning/SpeedDerivatives.h"
911
#include "settings/types/Ratio.h"
12+
#include "settings/types/Temperature.h"
1013
#include "settings/types/Velocity.h"
1114
#include "utils/Coord_t.h"
1215

@@ -29,6 +32,7 @@ struct GCodePathConfig
2932
bool is_bridge_path{ false }; //!< whether current config is used when bridging
3033
double fan_speed{ FAN_SPEED_DEFAULT }; //!< fan speed override for this path, value should be within range 0-100 (inclusive) and ignored otherwise
3134
double extrusion_mm3_per_mm{ calculateExtrusion() }; //!< current mm^3 filament moved per mm line traversed
35+
Temperature temperature_delta;
3236

3337
[[nodiscard]] constexpr bool operator==(const GCodePathConfig& other) const noexcept = default;
3438
[[nodiscard]] constexpr auto operator<=>(const GCodePathConfig& other) const = default;
@@ -67,6 +71,8 @@ struct GCodePathConfig
6771

6872
[[nodiscard]] PrintFeatureType getPrintFeatureType() const noexcept;
6973

74+
[[nodiscard]] const Temperature& getTemperatureDelta() const noexcept;
75+
7076
private:
7177
[[nodiscard]] double calculateExtrusion() const noexcept;
7278
};

include/InfillOrderOptimizer.h

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// Copyright (c) 2026 Ultimaker B.V.
2+
// CuraEngine is released under the terms of the AGPLv3 or higher
3+
4+
#ifndef INFILL_ORDER_OPTIMIZER_H
5+
#define INFILL_ORDER_OPTIMIZER_H
6+
7+
#include <optional>
8+
#include <unordered_map>
9+
10+
#include "utils/ExtrusionLine.h"
11+
12+
namespace cura
13+
{
14+
15+
enum class EFillMethod;
16+
class OpenLinesSet;
17+
class Shape;
18+
class LayerPlan;
19+
class Settings;
20+
class SliceDataStorage;
21+
class SliceMeshStorage;
22+
struct MeshPathConfigs;
23+
24+
/*!
25+
* Optimizer for infill lines ordering. When an end position is given, infill extrusions are optimized in a way that ending printing the infill
26+
* will always end as close as possible to the seam of the wall that is printed after.
27+
* We also try to consider the following rules, if applicable and possible:
28+
* - It is better to print the skin support after the rest, so that bridging lines have more printed material
29+
* to stick to. This is ensured by setting the initial ordering of the infill_parts_.
30+
* - We consider that infill walls are printed on the contour, thus they will always contain the closest location
31+
* to the nearest incoming seam., and will always be printed at last.
32+
*/
33+
class InfillOrderOptimizer
34+
{
35+
public:
36+
/*! Types of infill areas. The order determines the preferred printing order. */
37+
enum class InfillPartArea
38+
{
39+
Infill,
40+
SkinSupport,
41+
};
42+
43+
/*! Constructor for infill ordering optimizer. */
44+
InfillOrderOptimizer();
45+
46+
/*! Add a set of open polylines to be printed consecutively. */
47+
void addPart(InfillPartArea part_area, OpenLinesSet& lines);
48+
49+
/*! Add a set of closed polylines to be printed consecutively. */
50+
void addPart(InfillPartArea part_area, const Shape& polygons);
51+
52+
/*! Add a set of extrusion lines to be printed consecutively. */
53+
void addPart(InfillPartArea part_area, const std::vector<std::vector<VariableWidthLines>>& walls);
54+
55+
/*! Process the paths ordering optimization. */
56+
void optimize(const bool skin_support_interlace_lines, const std::optional<Point2LL>& near_end_location = std::nullopt);
57+
58+
/*!
59+
* Adds the ordered infill parts to the given layer plan.
60+
* \return Whether anything was added to the layer plan.
61+
*/
62+
bool addToLayer(
63+
LayerPlan& layer_plan,
64+
const Settings& settings,
65+
const std::optional<Point2LL>& near_end_location,
66+
const EFillMethod infill_pattern,
67+
const MeshPathConfigs& mesh_config,
68+
const SliceDataStorage& storage,
69+
const SliceMeshStorage& mesh,
70+
const size_t extruder_nr,
71+
const coord_t start_move_inwards_length,
72+
const coord_t end_move_inwards_length,
73+
const Shape& infill_inner_contour,
74+
const coord_t skin_support_line_distance,
75+
const Shape& infill_below_skin,
76+
const AngleDegrees& skin_support_angle) const;
77+
78+
private:
79+
/*! Types of infill print types. The order determines the preferred printing order. */
80+
enum class InfillPartType
81+
{
82+
Lines,
83+
Polygons,
84+
ExtrusionLines,
85+
};
86+
87+
/*! Helper structure that holds an infill part to be printed as a whole. */
88+
struct InfillPart
89+
{
90+
InfillPartArea area;
91+
InfillPartType type;
92+
union
93+
{
94+
const Shape* polygons;
95+
OpenLinesSet* lines;
96+
const std::vector<std::vector<VariableWidthLines>>* extrusion_lines;
97+
} paths;
98+
};
99+
100+
private:
101+
/*!
102+
* Calculates whether the given lines set has a vertex closer to the given location
103+
* @param line_set The lines set to be printed
104+
* @param location The target location that we should be close to
105+
* @param[in,out] closest_point The index of the line and vertex that is closest to the given location, which will be updated if we found a closer vertex
106+
* @param[in,out] closest_distance_squared The global closest distance to the given location, which will be updated if we found a closer vertex
107+
* @return Whether we have found a vertex in the lines set closer to the given location than the actual closest location
108+
*/
109+
template<class LinesSetType>
110+
bool isCloserTo(const LinesSetType& line_set, const Point2LL& location, std::optional<std::pair<size_t, size_t>>& closest_point, coord_t& closest_distance_squared);
111+
112+
/*! Add the given part to the layer plan using the given settings */
113+
void addToLayer(
114+
const InfillPart& part,
115+
LayerPlan& layer_plan,
116+
const Settings& settings,
117+
const std::optional<Point2LL>& near_start_location,
118+
const bool reverse_print_direction,
119+
const EFillMethod infill_pattern,
120+
const MeshPathConfigs& mesh_config,
121+
const SliceDataStorage& storage,
122+
const SliceMeshStorage& mesh,
123+
const size_t extruder_nr,
124+
const coord_t start_move_inwards_length,
125+
const coord_t end_move_inwards_length,
126+
const Shape& infill_inner_contour,
127+
const coord_t skin_support_line_distance,
128+
const Shape& infill_below_skin,
129+
const AngleDegrees& skin_support_angle) const;
130+
131+
/*! Add the given infill lines to the layer plan using the given settings */
132+
void addInfillLinesToLayer(
133+
const OpenLinesSet& lines,
134+
LayerPlan& layer_plan,
135+
const Settings& settings,
136+
const std::optional<Point2LL>& near_start_location,
137+
const bool reverse_print_direction,
138+
const EFillMethod infill_pattern,
139+
const MeshPathConfigs& mesh_config,
140+
const coord_t start_move_inwards_length,
141+
const coord_t end_move_inwards_length,
142+
const Shape& infill_inner_contour,
143+
const bool enable_travel_optimization,
144+
const Ratio& flow_ratio,
145+
const double fan_speed,
146+
const std::unordered_multimap<const Polyline*, const Polyline*>& order_requirements) const;
147+
148+
/*! Add the given skin support lines to the layer plan using the given settings */
149+
void addSkinSupportLinesToLayer(
150+
const OpenLinesSet& lines,
151+
LayerPlan& layer_plan,
152+
const Settings& settings,
153+
const std::optional<Point2LL>& near_start_location,
154+
const bool reverse_print_direction,
155+
const MeshPathConfigs& mesh_config,
156+
const coord_t skin_support_line_distance,
157+
const Shape& infill_below_skin,
158+
const AngleDegrees& skin_support_angle,
159+
const bool enable_travel_optimization,
160+
const Ratio& flow_ratio) const;
161+
162+
/*! Indicates whether part1 should be printed by default before part2 */
163+
static bool shouldPrintBefore(const InfillPart& part1, const InfillPart& part2);
164+
165+
private:
166+
std::vector<InfillPart> infill_parts_;
167+
};
168+
} // namespace cura
169+
170+
#endif // INSET_ORDER_OPTIMIZER_H

0 commit comments

Comments
 (0)