This commit is contained in:
Vojtech Bubnik 2021-05-03 15:23:57 +02:00
commit ef07644bf2
21 changed files with 2018 additions and 62 deletions

View file

@ -318,7 +318,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
case erIroning : return L("Ironing");
case erBridgeInfill : return L("Bridge infill");
case erGapFill : return L("Gap fill");
case erSkirt : return L("Skirt");
case erSkirt : return L("Skirt/Brim");
case erSupportMaterial : return L("Support material");
case erSupportMaterialInterface : return L("Support material interface");
case erWipeTower : return L("Wipe tower");
@ -349,7 +349,7 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
return erBridgeInfill;
else if (role == L("Gap fill"))
return erGapFill;
else if (role == L("Skirt"))
else if (role == L("Skirt") || role == L("Skirt/Brim")) // "Skirt" is for backward compatibility with 2.3.1 and earlier
return erSkirt;
else if (role == L("Support material"))
return erSupportMaterial;

View file

@ -857,6 +857,12 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_time_processor.export_remaining_time_enabled = config.remaining_times.value;
m_use_volumetric_e = config.use_volumetric_e;
#if ENABLE_START_GCODE_VISUALIZATION
const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height");
if (first_layer_height != nullptr)
m_first_layer_height = std::abs(first_layer_height->value);
#endif // ENABLE_START_GCODE_VISUALIZATION
}
void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
@ -1035,6 +1041,12 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
const ConfigOptionBool* use_volumetric_e = config.option<ConfigOptionBool>("use_volumetric_e");
if (use_volumetric_e != nullptr)
m_use_volumetric_e = use_volumetric_e->value;
#if ENABLE_START_GCODE_VISUALIZATION
const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height");
if (first_layer_height != nullptr)
m_first_layer_height = std::abs(first_layer_height->value);
#endif // ENABLE_START_GCODE_VISUALIZATION
}
void GCodeProcessor::enable_stealth_time_estimator(bool enabled)
@ -1060,6 +1072,9 @@ void GCodeProcessor::reset()
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
m_line_id = 0;
#if ENABLE_SEAMS_VISUALIZATION
m_last_line_id = 0;
#endif // ENABLE_SEAMS_VISUALIZATION
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
m_feedrate = 0.0f;
m_width = 0.0f;
@ -1082,6 +1097,10 @@ void GCodeProcessor::reset()
m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f);
m_extruded_last_z = 0.0f;
#if ENABLE_START_GCODE_VISUALIZATION
m_first_layer_height = 0.0f;
m_processing_start_custom_gcode = false;
#endif // ENABLE_START_GCODE_VISUALIZATION
m_g1_line_id = 0;
m_layer_id = 0;
m_cp_color.reset();
@ -1443,6 +1462,13 @@ void GCodeProcessor::process_tags(const std::string_view comment)
// extrusion role tag
if (boost::starts_with(comment, reserved_tag(ETags::Role))) {
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length()));
#if ENABLE_SEAMS_VISUALIZATION
if (m_extrusion_role == erExternalPerimeter)
m_seams_detector.activate(true);
#endif // ENABLE_SEAMS_VISUALIZATION
#if ENABLE_START_GCODE_VISUALIZATION
m_processing_start_custom_gcode = (m_extrusion_role == erCustom && m_g1_line_id == 0);
#endif // ENABLE_START_GCODE_VISUALIZATION
return;
}
@ -2187,7 +2213,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
}
#if ENABLE_START_GCODE_VISUALIZATION
if (type == EMoveType::Extrude && (m_width == 0.0f || m_height == 0.0f))
#else
if (type == EMoveType::Extrude && (m_extrusion_role == erCustom || m_width == 0.0f || m_height == 0.0f))
#endif // ENABLE_START_GCODE_VISUALIZATION
type = EMoveType::Travel;
// time estimate section
@ -2303,13 +2333,13 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
float jerk =
(v_exit > v_entry) ?
(((v_entry > 0.0f) || (v_exit < 0.0f)) ?
((v_entry > 0.0f || v_exit < 0.0f) ?
// coasting
(v_exit - v_entry) :
// axis reversal
std::max(v_exit, -v_entry)) :
// v_exit <= v_entry
(((v_entry < 0.0f) || (v_exit > 0.0f)) ?
((v_entry < 0.0f || v_exit > 0.0f) ?
// coasting
(v_entry - v_exit) :
// axis reversal
@ -2330,7 +2360,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
float vmax_junction_threshold = vmax_junction * 0.99f;
// Not coasting. The machine will stop and start the movements anyway, better to start the segment from start.
if ((prev.safe_feedrate > vmax_junction_threshold) && (curr.safe_feedrate > vmax_junction_threshold))
if (prev.safe_feedrate > vmax_junction_threshold && curr.safe_feedrate > vmax_junction_threshold)
vmax_junction = curr.safe_feedrate;
}
@ -2354,6 +2384,31 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
machine.calculate_time(TimeProcessor::Planner::queue_size);
}
#if ENABLE_SEAMS_VISUALIZATION
// check for seam starting vertex
if (type == EMoveType::Extrude && m_extrusion_role == erExternalPerimeter && m_seams_detector.is_active() && !m_seams_detector.has_first_vertex())
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
// check for seam ending vertex and store the resulting move
else if ((type != EMoveType::Extrude || m_extrusion_role != erExternalPerimeter) && m_seams_detector.is_active()) {
auto set_end_position = [this](const Vec3f& pos) {
m_end_position[X] = pos.x(); m_end_position[Y] = pos.y(); m_end_position[Z] = pos.z();
};
assert(m_seams_detector.has_first_vertex());
const Vec3f curr_pos(m_end_position[X], m_end_position[Y], m_end_position[Z]);
const Vec3f new_pos = m_result.moves.back().position - m_extruder_offsets[m_extruder_id];
const std::optional<Vec3f> first_vertex = m_seams_detector.get_first_vertex();
// the threshold value = 0.25 is arbitrary, we may find some smarter condition later
if ((new_pos - *first_vertex).norm() < 0.25f) {
set_end_position(0.5f * (new_pos + *first_vertex));
store_move_vertex(EMoveType::Seam);
set_end_position(curr_pos);
}
m_seams_detector.activate(false);
}
#endif // ENABLE_SEAMS_VISUALIZATION
// store move
store_move_vertex(type);
}
@ -2807,15 +2862,29 @@ void GCodeProcessor::process_T(const std::string_view command)
void GCodeProcessor::store_move_vertex(EMoveType type)
{
#if ENABLE_SEAMS_VISUALIZATION
m_last_line_id = (type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ?
m_line_id + 1 :
((type == EMoveType::Seam) ? m_last_line_id : m_line_id);
#endif // ENABLE_SEAMS_VISUALIZATION
MoveVertex vertex = {
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
#if ENABLE_SEAMS_VISUALIZATION
m_last_line_id,
#else
(type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ? m_line_id + 1 : m_line_id,
#endif // ENABLE_SEAMS_VISUALIZATION
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
type,
m_extrusion_role,
m_extruder_id,
m_cp_color.current,
#if ENABLE_START_GCODE_VISUALIZATION
Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
#else
Vec3f(m_end_position[X], m_end_position[Y], m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
#endif // ENABLE_START_GCODE_VISUALIZATION
m_end_position[E] - m_start_position[E],
m_feedrate,
m_width,

View file

@ -12,6 +12,9 @@
#include <vector>
#include <string>
#include <string_view>
#if ENABLE_SEAMS_VISUALIZATION
#include <optional>
#endif // ENABLE_SEAMS_VISUALIZATION
namespace Slic3r {
@ -20,6 +23,9 @@ namespace Slic3r {
Noop,
Retract,
Unretract,
#if ENABLE_SEAMS_VISUALIZATION
Seam,
#endif // ENABLE_SEAMS_VISUALIZATION
Tool_change,
Color_change,
Pause_Print,
@ -370,8 +376,7 @@ namespace Slic3r {
#if ENABLE_GCODE_VIEWER_STATISTICS
int64_t time{ 0 };
void reset()
{
void reset() {
time = 0;
moves = std::vector<MoveVertex>();
bed_shape = Pointfs();
@ -380,8 +385,7 @@ namespace Slic3r {
settings_ids.reset();
}
#else
void reset()
{
void reset() {
moves = std::vector<MoveVertex>();
bed_shape = Pointfs();
extruder_colors = std::vector<std::string>();
@ -391,6 +395,29 @@ namespace Slic3r {
#endif // ENABLE_GCODE_VIEWER_STATISTICS
};
#if ENABLE_SEAMS_VISUALIZATION
class SeamsDetector
{
bool m_active{ false };
std::optional<Vec3f> m_first_vertex;
public:
void activate(bool active) {
if (m_active != active) {
m_active = active;
if (m_active)
m_first_vertex.reset();
}
}
std::optional<Vec3f> get_first_vertex() const { return m_first_vertex; }
void set_first_vertex(const Vec3f& vertex) { m_first_vertex = vertex; }
bool is_active() const { return m_active; }
bool has_first_vertex() const { return m_first_vertex.has_value(); }
};
#endif // ENABLE_SEAMS_VISUALIZATION
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
struct DataChecker
{
@ -476,6 +503,9 @@ namespace Slic3r {
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
unsigned int m_line_id;
#if ENABLE_SEAMS_VISUALIZATION
unsigned int m_last_line_id;
#endif // ENABLE_SEAMS_VISUALIZATION
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
float m_feedrate; // mm/s
float m_width; // mm
@ -490,10 +520,17 @@ namespace Slic3r {
ExtruderTemps m_extruder_temps;
std::vector<float> m_filament_diameters;
float m_extruded_last_z;
#if ENABLE_START_GCODE_VISUALIZATION
float m_first_layer_height; // mm
bool m_processing_start_custom_gcode;
#endif // ENABLE_START_GCODE_VISUALIZATION
unsigned int m_g1_line_id;
unsigned int m_layer_id;
CpColor m_cp_color;
bool m_use_volumetric_e;
#if ENABLE_SEAMS_VISUALIZATION
SeamsDetector m_seams_detector;
#endif // ENABLE_SEAMS_VISUALIZATION
enum class EProducer
{

View file

@ -639,9 +639,11 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
float prime_section_width = std::min(0.9f * m_bed_width / tools.size(), 60.f);
box_coordinates cleaning_box(Vec2f(0.02f * m_bed_width, 0.01f + m_perimeter_width/2.f), prime_section_width, 100.f);
// In case of a circular bed, place it so it goes across the diameter and hope it will fit
if (m_bed_shape == CircularBed)
cleaning_box.translate(-m_bed_width/2 + m_bed_width * 0.03f, -m_bed_width * 0.12f);
if (m_bed_shape == CircularBed) {
cleaning_box = box_coordinates(Vec2f(0.f, 0.f), prime_section_width, 100.f);
float total_width_half = tools.size() * prime_section_width / 2.f;
cleaning_box.translate(-total_width_half, -std::sqrt(std::max(0.f, std::pow(m_bed_width/2, 2.f) - std::pow(1.05f * total_width_half, 2.f))));
}
else
cleaning_box.translate(m_bed_bottom_left);

View file

@ -833,18 +833,6 @@ indexed_triangle_set ModelObject::raw_indexed_triangle_set() const
return out;
}
// Non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
TriangleMesh ModelObject::full_raw_mesh() const
{
TriangleMesh mesh;
for (const ModelVolume *v : this->volumes)
{
TriangleMesh vol_mesh(v->mesh());
vol_mesh.transform(v->get_matrix());
mesh.merge(vol_mesh);
}
return mesh;
}
const BoundingBoxf3& ModelObject::raw_mesh_bounding_box() const
{

View file

@ -289,8 +289,6 @@ public:
TriangleMesh raw_mesh() const;
// The same as above, but producing a lightweight indexed_triangle_set.
indexed_triangle_set raw_indexed_triangle_set() const;
// Non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
TriangleMesh full_raw_mesh() const;
// A transformed snug bounding box around the non-modifier object volumes, without the translation applied.
// This bounding box is only used for the actual slicing.
const BoundingBoxf3& raw_bounding_box() const;

View file

@ -8,6 +8,7 @@
#include <functional>
#include <limits>
#include <cassert>
#include <optional>
namespace Slic3r { namespace opt {

View file

@ -2207,6 +2207,7 @@ std::vector<ExPolygons> PrintObject::slice_volumes(
TriangleMesh vol_mesh(model_volume.mesh());
vol_mesh.transform(model_volume.get_matrix(), true);
mesh.merge(vol_mesh);
mesh.repair(false);
}
if (mesh.stl.stats.number_of_facets > 0) {
mesh.transform(m_trafo, true);

View file

@ -59,6 +59,10 @@
#define ENABLE_EXTENDED_M73_LINES (1 && ENABLE_VALIDATE_CUSTOM_GCODE)
// Enable a modified version of automatic downscale on load of objects too big
#define ENABLE_MODIFIED_DOWNSCALE_ON_LOAD_OBJECTS_TOO_BIG (1 && ENABLE_2_4_0_ALPHA0)
// Enable visualization of start gcode as regular toolpaths
#define ENABLE_START_GCODE_VISUALIZATION (1 && ENABLE_2_4_0_ALPHA0)
// Enable visualization of seams in preview
#define ENABLE_SEAMS_VISUALIZATION (1 && ENABLE_2_4_0_ALPHA0)
#endif // _prusaslicer_technologies_h_

View file

@ -357,10 +357,14 @@ void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed)
its_transform(its, t);
if (fix_left_handed && t.matrix().block(0, 0, 3, 3).determinant() < 0.) {
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
this->repair(false);
stl_reverse_all_facets(&stl);
this->its.clear();
this->require_shared_vertices();
// As for the assert: the repair function would fix the normals, reversing would
// break them again. The caller should provide a mesh that does not need repair.
// The repair call is left here so things don't break more than they were.
assert(this->repaired);
this->repair(false);
stl_reverse_all_facets(&stl);
this->its.clear();
this->require_shared_vertices();
}
}
@ -369,11 +373,12 @@ void TriangleMesh::transform(const Matrix3d& m, bool fix_left_handed)
stl_transform(&stl, m);
its_transform(its, m);
if (fix_left_handed && m.determinant() < 0.) {
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
// See comments in function above.
assert(this->repaired);
this->repair(false);
stl_reverse_all_facets(&stl);
this->its.clear();
this->require_shared_vertices();
this->its.clear();
this->require_shared_vertices();
}
}