Skip to content
This repository has been archived by the owner on Jun 15, 2023. It is now read-only.

Commit

Permalink
Merge branch 'master' of https://github.com/ultimaker/curaengine
Browse files Browse the repository at this point in the history
  • Loading branch information
GitHub committed Aug 7, 2021
2 parents d4a7d68 + 042911f commit 9527c1c
Show file tree
Hide file tree
Showing 33 changed files with 1,459 additions and 233 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ set(engine_SRCS # Except main.cpp.
src/MeshGroup.cpp
src/Mold.cpp
src/multiVolumes.cpp
src/PathOrder.cpp
src/pathOrderOptimizer.cpp
src/Preheat.cpp
src/PrimeTower.cpp
Expand Down Expand Up @@ -201,6 +202,7 @@ set(engine_SRCS # Except main.cpp.
src/settings/FlowTempGraph.cpp
src/settings/PathConfigStorage.cpp
src/settings/Settings.cpp
src/settings/ZSeamConfig.cpp

src/utils/AABB.cpp
src/utils/AABB3D.cpp
Expand Down Expand Up @@ -228,10 +230,9 @@ set(engine_TEST
InfillTest
LayerPlanTest
MergeInfillLinesTest
PathOrderMonotonicTest
TimeEstimateCalculatorTest
)
set(engine_TEST_INFILL
)
set(engine_TEST_INTEGRATION
SlicePhaseTest
)
Expand Down
4 changes: 2 additions & 2 deletions src/ConicalOverhang.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//Copyright (c) 2016 Tim Kuipers
//Copyright (c) 2018 Ultimaker B.V.
//Copyright (c) 2021 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "ConicalOverhang.h"
#include "mesh.h"
#include "slicer.h"
#include "settings/types/AngleRadians.h" //To process the overhang angle.
#include "settings/types/Angle.h" //To process the overhang angle.

namespace cura {

Expand Down
59 changes: 40 additions & 19 deletions src/FffGcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2297,7 +2297,8 @@ void FffGcodeWriter::processRoofing(const SliceDataStorage& storage, LayerPlan&
const Ratio skin_density = 1.0;
const coord_t skin_overlap = 0; // skinfill already expanded over the roofing areas; don't overlap with perimeters
Polygons* perimeter_gaps_output = (fill_perimeter_gaps) ? &concentric_perimeter_gaps : nullptr;
processSkinPrintFeature(storage, gcode_layer, mesh, extruder_nr, skin_part.roofing_fill, mesh_config.roofing_config, pattern, roofing_angle, skin_overlap, skin_density, perimeter_gaps_output, added_something);
const bool monotonic = mesh.settings.get<bool>("roofing_monotonic");
processSkinPrintFeature(storage, gcode_layer, mesh, extruder_nr, skin_part.roofing_fill, mesh_config.roofing_config, pattern, roofing_angle, skin_overlap, skin_density, monotonic, perimeter_gaps_output, added_something);
}

void FffGcodeWriter::processTopBottom(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SkinPart& skin_part, Polygons& concentric_perimeter_gaps, bool& added_something) const
Expand Down Expand Up @@ -2465,10 +2466,11 @@ void FffGcodeWriter::processTopBottom(const SliceDataStorage& storage, LayerPlan
// calculate polygons and lines
Polygons* perimeter_gaps_output = (generate_perimeter_gaps) ? &concentric_perimeter_gaps : nullptr;

processSkinPrintFeature(storage, gcode_layer, mesh, extruder_nr, skin_part.inner_infill, *skin_config, pattern, skin_angle, skin_overlap, skin_density, perimeter_gaps_output, added_something, fan_speed);
const bool monotonic = mesh.settings.get<bool>("skin_monotonic");
processSkinPrintFeature(storage, gcode_layer, mesh, extruder_nr, skin_part.inner_infill, *skin_config, pattern, skin_angle, skin_overlap, skin_density, monotonic, perimeter_gaps_output, added_something, fan_speed);
}

void FffGcodeWriter::processSkinPrintFeature(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const Polygons& area, const GCodePathConfig& config, EFillMethod pattern, const AngleDegrees skin_angle, const coord_t skin_overlap, const Ratio skin_density, Polygons* perimeter_gaps_output, bool& added_something, double fan_speed) const
void FffGcodeWriter::processSkinPrintFeature(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const Polygons& area, const GCodePathConfig& config, EFillMethod pattern, const AngleDegrees skin_angle, const coord_t skin_overlap, const Ratio skin_density, const bool monotonic, Polygons* perimeter_gaps_output, bool& added_something, double fan_speed) const
{
Polygons skin_polygons;
Polygons skin_lines;
Expand Down Expand Up @@ -2509,26 +2511,45 @@ void FffGcodeWriter::processSkinPrintFeature(const SliceDataStorage& storage, La
gcode_layer.addPolygonsByOptimizer(skin_polygons, config);
}

std::optional<Point> near_start_location;
const EFillMethod pattern = (gcode_layer.getLayerNr() == 0) ?
mesh.settings.get<EFillMethod>("top_bottom_pattern_0") :
mesh.settings.get<EFillMethod>("top_bottom_pattern");
if (pattern == EFillMethod::LINES || pattern == EFillMethod::ZIG_ZAG)
{ // update near_start_location to a location which tries to avoid seams in skin
near_start_location = getSeamAvoidingLocation(area, skin_angle, gcode_layer.getLastPlannedPositionOrStartingPosition());
}

constexpr bool enable_travel_optimization = false;
constexpr float flow = 1.0;
if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES || pattern == EFillMethod::CUBIC || pattern == EFillMethod::TETRAHEDRAL || pattern == EFillMethod::QUARTER_CUBIC || pattern == EFillMethod::CUBICSUBDIV)
if(monotonic)
{
gcode_layer.addLinesByOptimizer(skin_lines, config, SpaceFillType::Lines, enable_travel_optimization, mesh.settings.get<coord_t>("infill_wipe_dist"), flow, near_start_location, fan_speed);
const AngleRadians monotonic_direction = AngleRadians(skin_angle + 90);
constexpr Ratio flow = 1.0_r;
const coord_t max_adjacent_distance = config.getLineWidth() * 1.1; //Lines are considered adjacent if they are 1 line width apart, with 10% extra play. The monotonic order is enforced if they are adjacent.
if(pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES || pattern == EFillMethod::CUBIC || pattern == EFillMethod::TETRAHEDRAL || pattern == EFillMethod::QUARTER_CUBIC || pattern == EFillMethod::CUBICSUBDIV)
{
gcode_layer.addLinesMonotonic(skin_lines, config, SpaceFillType::Lines, monotonic_direction, max_adjacent_distance, mesh.settings.get<coord_t>("infill_wipe_dist"), flow, fan_speed);
}
else
{
const SpaceFillType space_fill_type = (pattern == EFillMethod::ZIG_ZAG) ? SpaceFillType::PolyLines : SpaceFillType::Lines;
constexpr coord_t wipe_dist = 0;
gcode_layer.addLinesMonotonic(skin_lines, config, space_fill_type, monotonic_direction, max_adjacent_distance, wipe_dist, flow, fan_speed);
}
}
else
{
SpaceFillType space_fill_type = (pattern == EFillMethod::ZIG_ZAG) ? SpaceFillType::PolyLines : SpaceFillType::Lines;
constexpr coord_t wipe_dist = 0;
gcode_layer.addLinesByOptimizer(skin_lines, config, space_fill_type, enable_travel_optimization, wipe_dist, flow, near_start_location, fan_speed);
std::optional<Point> near_start_location;
const EFillMethod pattern = (gcode_layer.getLayerNr() == 0) ?
mesh.settings.get<EFillMethod>("top_bottom_pattern_0") :
mesh.settings.get<EFillMethod>("top_bottom_pattern");
if (pattern == EFillMethod::LINES || pattern == EFillMethod::ZIG_ZAG)
{ // update near_start_location to a location which tries to avoid seams in skin
near_start_location = getSeamAvoidingLocation(area, skin_angle, gcode_layer.getLastPlannedPositionOrStartingPosition());
}

constexpr bool enable_travel_optimization = false;
constexpr float flow = 1.0;
if(pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES || pattern == EFillMethod::CUBIC || pattern == EFillMethod::TETRAHEDRAL || pattern == EFillMethod::QUARTER_CUBIC || pattern == EFillMethod::CUBICSUBDIV)
{
gcode_layer.addLinesByOptimizer(skin_lines, config, SpaceFillType::Lines, enable_travel_optimization, mesh.settings.get<coord_t>("infill_wipe_dist"), flow, near_start_location, fan_speed);
}
else
{
SpaceFillType space_fill_type = (pattern == EFillMethod::ZIG_ZAG) ? SpaceFillType::PolyLines : SpaceFillType::Lines;
constexpr coord_t wipe_dist = 0;
gcode_layer.addLinesByOptimizer(skin_lines, config, space_fill_type, enable_travel_optimization, wipe_dist, flow, near_start_location, fan_speed);
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/FffGcodeWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,11 +581,13 @@ class FffGcodeWriter : public NoCopy
* \param skin_angle the angle to use for linear infill types
* \param skin_overlap The amount by which to expand the \p area
* \param skin density Sets the density of the the skin lines by adjusting the distance between them (normal skin is 1.0)
* \param monotonic Whether to order lines monotonically (``true``) or to
* minimise travel moves (``false``).
* \param[out] perimeter_gaps_output Optional output to store the gaps which occur if the pattern is concentric
* \param[out] added_something Whether this function added anything to the layer plan
* \param fan_speed fan speed override for this skin area
*/
void processSkinPrintFeature(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const Polygons& area, const GCodePathConfig& config, EFillMethod pattern, const AngleDegrees skin_angle, const coord_t skin_overlap, const Ratio skin_density, Polygons* perimeter_gaps_output, bool& added_something, double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT) const;
void processSkinPrintFeature(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const Polygons& area, const GCodePathConfig& config, EFillMethod pattern, const AngleDegrees skin_angle, const coord_t skin_overlap, const Ratio skin_density, const bool monotonic, Polygons* perimeter_gaps_output, bool& added_something, double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT) const;

/*!
* Add perimeter gaps of a mesh with the given extruder.
Expand Down
2 changes: 1 addition & 1 deletion src/FffPolygonGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#include "progress/ProgressEstimatorLinear.h"
#include "progress/ProgressStageEstimator.h"
#include "settings/AdaptiveLayerHeights.h"
#include "settings/types/AngleRadians.h"
#include "settings/types/Angle.h"
#include "settings/types/LayerIndex.h"
#include "utils/algorithm.h"
#include "utils/gettime.h"
Expand Down
62 changes: 61 additions & 1 deletion src/LayerPlan.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//Copyright (c) 2020 Ultimaker B.V.
//Copyright (c) 2021 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include <cstring>
Expand All @@ -7,6 +7,7 @@
#include "ExtruderTrain.h"
#include "LayerPlan.h"
#include "MergeInfillLines.h"
#include "PathOrderMonotonic.h" //Monotonic ordering of skin lines.
#include "raft.h" // getTotalExtraLayers
#include "Slice.h"
#include "sliceDataStorage.h"
Expand Down Expand Up @@ -1124,6 +1125,65 @@ void LayerPlan::addLinesByOptimizer(const Polygons& polygons, const GCodePathCon
}
}

void LayerPlan::addLinesMonotonic(const Polygons& polygons, const GCodePathConfig& config, const SpaceFillType space_fill_type, const AngleRadians monotonic_direction, const coord_t max_adjacent_distance, const coord_t wipe_dist, const Ratio flow_ratio, const double fan_speed)
{
const Point last_position = getLastPlannedPositionOrStartingPosition();
PathOrderMonotonic<ConstPolygonRef> order(monotonic_direction, max_adjacent_distance, last_position);
for(size_t line_idx = 0; line_idx < polygons.size(); ++line_idx)
{
order.addPolyline(polygons[line_idx]);
}
order.optimize();

for (unsigned int order_idx = 0; order_idx < order.paths.size(); order_idx++)
{
const PathOrder<ConstPolygonRef>::Path& path = order.paths[order_idx];
ConstPolygonRef polygon = *path.vertices;
const size_t start = path.start_vertex;
const size_t end = 1 - start;
const Point& p0 = polygon[start];
const Point& p1 = polygon[end];
// ignore line segments that are less than 5uM long
if(vSize2(p1 - p0) < MINIMUM_SQUARED_LINE_LENGTH)
{
continue;
}
addTravel(p0);
addExtrusionMove(p1, config, space_fill_type, flow_ratio, false, 1.0, fan_speed);

// Wipe
if (wipe_dist != 0)
{
bool wipe = true;
int line_width = config.getLineWidth();

// Don't wipe is current extrusion is too small
if (vSize2(p1 - p0) <= line_width * line_width * 4)
{
wipe = false;
}

// Don't wipe if next starting point is very near
if (wipe && (order_idx < order.paths.size() - 1))
{
const PathOrder<ConstPolygonRef>::Path& next_path = order.paths[order_idx + 1];
ConstPolygonRef next_polygon = *next_path.vertices;
const size_t next_start = next_path.start_vertex;
const Point& next_p0 = next_polygon[next_start];
if (vSize2(next_p0 - p1) <= line_width * line_width * 4)
{
wipe = false;
}
}

if (wipe)
{
addExtrusionMove(p1 + normal(p1-p0, wipe_dist), config, space_fill_type, 0.0, false, 1.0, fan_speed);
}
}
}
}

void LayerPlan::spiralizeWallSlice(const GCodePathConfig& config, ConstPolygonRef wall, ConstPolygonRef last_wall, const int seam_vertex_idx, const int last_seam_vertex_idx, const bool is_top_layer, const bool is_bottom_layer)
{
const bool smooth_contours = Application::getInstance().current_slice->scene.current_mesh_group->settings.get<bool>("smooth_spiralized_contours");
Expand Down
21 changes: 20 additions & 1 deletion src/LayerPlan.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//Copyright (c) 2020 Ultimaker B.V.
//Copyright (c) 2021 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#ifndef LAYER_PLAN_H
Expand Down Expand Up @@ -607,6 +607,25 @@ class LayerPlan : public NoCopy
*/
void addLinesByOptimizer(const Polygons& polygons, const GCodePathConfig& config, SpaceFillType space_fill_type, bool enable_travel_optimization = false, int wipe_dist = 0, float flow_ratio = 1.0, std::optional<Point> near_start_location = std::optional<Point>(), double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT);

/*!
* Add polygons to the g-code with monotonic order.
* \param polygons The lines to add.
* \param config The settings to print those lines with.
* \param space_fill_type The type of space filling used to generate the
* line segments (should be either Lines or PolyLines!)
* \param monotonic_direction The directions in which to sort the lines
* monotonically.
* \param max_adjacent_distance With a monotonic order, adjacent lines must
* be printed in a certain direction. Lines that are not adjacent may be
* printed in any order. This limit is the longest distance at which two
* lines are still considered to be adjacent.
* \param wipe_dist The distance wiped without extruding after laying down a
* line.
* \param flow_ratio The ratio with which to multiply the extrusion amount.
* \param fan_speed Fan speed override for this path.
*/
void addLinesMonotonic(const Polygons& polygons, const GCodePathConfig& config, const SpaceFillType space_fill_type, const AngleRadians monotonic_direction, const coord_t max_adjacent_distance, const coord_t wipe_dist = 0, const Ratio flow_ratio = 1.0_r, const double fan_speed = 100.0);

/*!
* Add a spiralized slice of wall that is interpolated in X/Y between \p last_wall and \p wall.
*
Expand Down
43 changes: 43 additions & 0 deletions src/PathOrder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//Copyright (c) 2021 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "PathOrder.h" //The definitions we're implementing here.
#include "sliceDataStorage.h" //For SliceLayerPart and related parts to reorder.

//Since the PathOrder is a template class, we will only implement the template specializations in this file.
//The templated segments need to go into the header.

namespace cura
{

template<>
ConstPolygonRef PathOrder<ConstPolygonRef>::getVertexData(ConstPolygonRef path)
{
return path;
}

template<>
ConstPolygonRef PathOrder<PolygonRef>::getVertexData(PolygonRef path)
{
return path;
}

template<>
ConstPolygonRef PathOrder<const SkinPart*>::getVertexData(const SkinPart* path)
{
return path->outline.outerPolygon();
}

template<>
ConstPolygonRef PathOrder<const SliceLayerPart*>::getVertexData(const SliceLayerPart* path)
{
return path->outline.outerPolygon();
}

template<>
ConstPolygonRef PathOrder<const SupportInfillPart*>::getVertexData(const SupportInfillPart* path)
{
return path->outline.outerPolygon();
}

}
Loading

0 comments on commit 9527c1c

Please sign in to comment.