mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 16:05:54 +08:00
Merge branch 'master' into fs_svg_SPE-1517
This commit is contained in:
commit
4ecc22638b
@ -1,4 +1,5 @@
|
||||
min_slic3r_version = 2.6.0-beta1
|
||||
0.2.8 Fixed compatible printer condition.
|
||||
0.2.7 Fixed compatible condition for MONO X.
|
||||
0.2.6 Added MONO X 6K.
|
||||
0.2.5 Fixed output file format for MONO SE.
|
||||
|
@ -5,7 +5,7 @@
|
||||
name = Anycubic
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 0.2.7
|
||||
config_version = 0.2.8
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anycubic/
|
||||
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
@ -2452,7 +2452,7 @@ initial_exposure_time = 30
|
||||
material_type = Plant-Based
|
||||
material_vendor = Anycubic
|
||||
material_colour = #808080
|
||||
compatible_printers_condition = printer_model=="PHOTON MONO SE" and
|
||||
compatible_printers_condition = printer_model=="PHOTON MONO SE"
|
||||
material_notes = LIFT_SPEED=2
|
||||
|
||||
## Printers
|
||||
|
@ -1,4 +1,5 @@
|
||||
min_slic3r_version = 2.6.2-alpha0
|
||||
1.11.0-alpha6 Increased MBL temperature for PET. Enabled FW-specific object labels for XL/MK3.9/MK4/MINI. PETG V0 marked as UL certified for MK4.
|
||||
1.11.0-alpha5 Added new profiles (additional nozzle diameters) for Prusa MINI Input Shaper (Alpha). Arc fitting changed to I J.
|
||||
1.11.0-alpha4 Updated compatible printer conditions for specific filament profiles.
|
||||
1.11.0-alpha3 Added new print profiles for Prusa MINI Input Shaper (Alpha). Updated MK4 IS profiles.
|
||||
|
File diff suppressed because one or more lines are too long
@ -97,7 +97,8 @@ inline IType Round(double val)
|
||||
{
|
||||
double v = FRound(val);
|
||||
#if defined(CLIPPERLIB_INT32) && ! defined(NDEBUG)
|
||||
static constexpr const double hi = 65536 * 16383;
|
||||
static_assert(sizeof(IType) == 4 || sizeof(IType) == 8, "IType must be int32 or int64");
|
||||
static constexpr const double hi = 65536. * 16383. * (sizeof(IType) == 4 ? 1 : 65536. * 65536.);
|
||||
if (v > hi || -v > hi)
|
||||
throw clipperException("Coordinate outside allowed range");
|
||||
#endif
|
||||
|
@ -1,9 +1,8 @@
|
||||
///|/ Copyright (c) Prusa Research 2020 - 2023 Enrico Turri @enricoturri1966, Vojtěch Bubník @bubnikv, Pavel Mikuš @Godrak, Lukáš Matěna @lukasmatena, Filip Sykala @Jony01, Oleksandra Iushchenko @YuSanka
|
||||
///|/ Copyright (c) SuperSlicer 2023 Remi Durand @supermerill
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#include "libslic3r/libslic3r.h"
|
||||
///|/ Copyright (c) Prusa Research 2020 - 2023 Enrico Turri @enricoturri1966, Vojtěch Bubník @bubnikv, Pavel Mikuš @Godrak, Lukáš Matěna @lukasmatena, Filip Sykala @Jony01, Oleksandra Iushchenko @YuSanka
|
||||
///|/ Copyright (c) SuperSlicer 2023 Remi Durand @supermerill
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/LocalesUtils.hpp"
|
||||
@ -2888,7 +2887,17 @@ void GCodeProcessor::process_G1(const std::array<std::optional<double>, 4>& axes
|
||||
void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise)
|
||||
{
|
||||
enum class EFitting { None, IJ, R };
|
||||
const EFitting fitting = line.has('R') ? EFitting::R : (line.has('I') && line.has('J')) ? EFitting::IJ : EFitting::None;
|
||||
std::string_view axis_pos_I;
|
||||
std::string_view axis_pos_J;
|
||||
EFitting fitting = EFitting::None;
|
||||
if (line.has('R')) {
|
||||
fitting = EFitting::R;
|
||||
} else {
|
||||
axis_pos_I = line.axis_pos('I');
|
||||
axis_pos_J = line.axis_pos('J');
|
||||
if (! axis_pos_I.empty() || ! axis_pos_J.empty())
|
||||
fitting = EFitting::IJ;
|
||||
}
|
||||
|
||||
if (fitting == EFitting::None)
|
||||
return;
|
||||
@ -2921,7 +2930,10 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
|
||||
rel_center.y() = c.y() - m_start_position[Y];
|
||||
}
|
||||
else {
|
||||
if (!line.has_value('I', rel_center.x()) || !line.has_value('J', rel_center.y()))
|
||||
assert(fitting == EFitting::IJ);
|
||||
if (! axis_pos_I.empty() && ! line.has_value(axis_pos_I, rel_center.x()))
|
||||
return;
|
||||
if (! axis_pos_J.empty() && ! line.has_value(axis_pos_J, rel_center.y()))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -237,42 +237,56 @@ const char* GCodeReader::axis_pos(const char *raw_str, char axis)
|
||||
|
||||
bool GCodeReader::GCodeLine::has(char axis) const
|
||||
{
|
||||
const char *c = axis_pos(m_raw.c_str(), axis);
|
||||
return c != nullptr;
|
||||
return GCodeReader::axis_pos(this->raw().c_str(), axis);
|
||||
}
|
||||
|
||||
std::string_view GCodeReader::GCodeLine::axis_pos(char axis) const
|
||||
{
|
||||
const std::string &s = this->raw();
|
||||
const char *c = GCodeReader::axis_pos(this->raw().c_str(), axis);
|
||||
return c ? std::string_view{ c, s.size() - (c - s.data()) } : std::string_view();
|
||||
}
|
||||
|
||||
bool GCodeReader::GCodeLine::has_value(std::string_view axis_pos, float &value)
|
||||
{
|
||||
if (const char *c = axis_pos.data(); c) {
|
||||
// Try to parse the numeric value.
|
||||
double v = 0.;
|
||||
const char *end = axis_pos.data() + axis_pos.size();
|
||||
auto [pend, ec] = fast_float::from_chars(++ c, end, v);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
value = float(v);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GCodeReader::GCodeLine::has_value(char axis, float &value) const
|
||||
{
|
||||
assert(is_decimal_separator_point());
|
||||
const char *c = axis_pos(m_raw.c_str(), axis);
|
||||
if (c == nullptr)
|
||||
return false;
|
||||
// Try to parse the numeric value.
|
||||
double v = 0.;
|
||||
const char* end = m_raw.c_str() + m_raw.size();
|
||||
auto [pend, ec] = fast_float::from_chars(++c, end, v);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
value = float(v);
|
||||
return true;
|
||||
return this->has_value(this->axis_pos(axis), value);
|
||||
}
|
||||
|
||||
bool GCodeReader::GCodeLine::has_value(std::string_view axis_pos, int &value)
|
||||
{
|
||||
if (const char *c = axis_pos.data(); c) {
|
||||
// Try to parse the numeric value.
|
||||
char *pend = nullptr;
|
||||
long v = strtol(++ c, &pend, 10);
|
||||
if (pend != nullptr && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
value = int(v);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GCodeReader::GCodeLine::has_value(char axis, int &value) const
|
||||
{
|
||||
const char *c = axis_pos(m_raw.c_str(), axis);
|
||||
if (c == nullptr)
|
||||
return false;
|
||||
// Try to parse the numeric value.
|
||||
char *pend = nullptr;
|
||||
long v = strtol(++ c, &pend, 10);
|
||||
if (pend != nullptr && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
value = int(v);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return this->has_value(this->axis_pos(axis), value);
|
||||
}
|
||||
|
||||
void GCodeReader::GCodeLine::set(const GCodeReader &reader, const Axis axis, const float new_value, const int decimal_digits)
|
||||
|
@ -30,11 +30,16 @@ public:
|
||||
const std::string_view comment() const
|
||||
{ size_t pos = m_raw.find(';'); return (pos == std::string::npos) ? std::string_view() : std::string_view(m_raw).substr(pos + 1); }
|
||||
|
||||
// Return position in this->raw() string starting with the "axis" character.
|
||||
std::string_view axis_pos(char axis) const;
|
||||
bool has(Axis axis) const { return (m_mask & (1 << int(axis))) != 0; }
|
||||
float value(Axis axis) const { return m_axis[axis]; }
|
||||
bool has(char axis) const;
|
||||
bool has_value(char axis, float &value) const;
|
||||
bool has_value(char axis, int &value) const;
|
||||
// Parse value of an axis from raw string starting at axis_pos.
|
||||
static bool has_value(std::string_view axis_pos, float &value);
|
||||
static bool has_value(std::string_view axis_pos, int &value);
|
||||
float new_X(const GCodeReader &reader) const { return this->has(X) ? this->x() : reader.x(); }
|
||||
float new_Y(const GCodeReader &reader) const { return this->has(Y) ? this->y() : reader.y(); }
|
||||
float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); }
|
||||
|
@ -264,44 +264,47 @@ static std::optional<Circle> try_create_circle(const Points::const_iterator begi
|
||||
// of all points on the polyline to be fitted.
|
||||
Vec2i64 first_point = begin->cast<int64_t>();
|
||||
Vec2i64 last_point = std::prev(end)->cast<int64_t>();
|
||||
Vec2i64 c = (first_point.cast<int64_t>() + last_point.cast<int64_t>()) / 2;
|
||||
Vec2i64 v = last_point - first_point;
|
||||
Vec2i64 prev_point = first_point;
|
||||
int prev_side = sign(v.dot(prev_point - c));
|
||||
assert(prev_side != 0);
|
||||
Point point_on_bisector;
|
||||
#ifndef NDEBUG
|
||||
point_on_bisector = { std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max() };
|
||||
#endif // NDEBUG
|
||||
for (auto it = std::next(begin); it != end; ++ it) {
|
||||
Vec2i64 this_point = it->cast<int64_t>();
|
||||
int64_t d = v.dot(this_point - c);
|
||||
int this_side = sign(d);
|
||||
int sideness = this_side * prev_side;
|
||||
if (sideness < 0) {
|
||||
// Calculate the intersection point.
|
||||
Vec2d vd = v.cast<double>();
|
||||
Vec2d p = c.cast<double>() + vd * double(d) / vd.squaredNorm();
|
||||
point_on_bisector = p.cast<coord_t>();
|
||||
break;
|
||||
}
|
||||
if (sideness == 0) {
|
||||
// this_point is on the bisector.
|
||||
assert(prev_side != 0);
|
||||
assert(this_side == 0);
|
||||
point_on_bisector = this_point.cast<coord_t>();
|
||||
break;
|
||||
Vec2d vd = v.cast<double>();
|
||||
double ld = v.squaredNorm();
|
||||
if (ld > sqr(scaled<double>(0.0015))) {
|
||||
Vec2i64 c = (first_point.cast<int64_t>() + last_point.cast<int64_t>()) / 2;
|
||||
Vec2i64 prev_point = first_point;
|
||||
int prev_side = sign(v.dot(prev_point - c));
|
||||
assert(prev_side != 0);
|
||||
Point point_on_bisector;
|
||||
#ifndef NDEBUG
|
||||
point_on_bisector = { std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max() };
|
||||
#endif // NDEBUG
|
||||
for (auto it = std::next(begin); it != end; ++ it) {
|
||||
Vec2i64 this_point = it->cast<int64_t>();
|
||||
int64_t d = v.dot(this_point - c);
|
||||
int this_side = sign(d);
|
||||
int sideness = this_side * prev_side;
|
||||
if (sideness < 0) {
|
||||
// Calculate the intersection point.
|
||||
Vec2d p = c.cast<double>() + vd * double(d) / ld;
|
||||
point_on_bisector = p.cast<coord_t>();
|
||||
break;
|
||||
}
|
||||
if (sideness == 0) {
|
||||
// this_point is on the bisector.
|
||||
assert(prev_side != 0);
|
||||
assert(this_side == 0);
|
||||
point_on_bisector = this_point.cast<coord_t>();
|
||||
break;
|
||||
}
|
||||
prev_point = this_point;
|
||||
prev_side = this_side;
|
||||
}
|
||||
prev_point = this_point;
|
||||
prev_side = this_side;
|
||||
// point_on_bisector must be set
|
||||
assert(point_on_bisector.x() != std::numeric_limits<coord_t>::max() && point_on_bisector.y() != std::numeric_limits<coord_t>::max());
|
||||
circle = try_create_circle(*begin, point_on_bisector, *std::prev(end), max_radius);
|
||||
if (// Use twice the tolerance for fitting the initial circle.
|
||||
// Early exit if such approximation is grossly inaccurate, thus the tolerance could not be achieved.
|
||||
circle && ! circle_approximation_sufficient(*circle, begin, end, tolerance * 2))
|
||||
circle.reset();
|
||||
}
|
||||
// point_on_bisector must be set
|
||||
assert(point_on_bisector.x() != std::numeric_limits<coord_t>::max() && point_on_bisector.y() != std::numeric_limits<coord_t>::max());
|
||||
circle = try_create_circle(*begin, point_on_bisector, *std::prev(end), max_radius);
|
||||
if (// Use twice the tolerance for fitting the initial circle.
|
||||
// Early exit if such approximation is grossly inaccurate, thus the tolerance could not be achieved.
|
||||
circle && ! circle_approximation_sufficient(*circle, begin, end, tolerance * 2))
|
||||
circle.reset();
|
||||
}
|
||||
if (circle) {
|
||||
// Fit the arc between the end points by least squares.
|
||||
@ -320,13 +323,16 @@ static std::optional<Circle> try_create_circle(const Points::const_iterator begi
|
||||
std::optional<Vec2d> opt_center = ArcWelder::arc_fit_center_gauss_newton_ls(first_point, last_point,
|
||||
circle->center.cast<double>(), fpts.begin(), fpts.end(), 5);
|
||||
if (opt_center) {
|
||||
circle->center = opt_center->cast<coord_t>();
|
||||
circle->radius = (circle->radius > 0 ? 1.f : -1.f) * (*opt_center - first_point).norm();
|
||||
if (circle_approximation_sufficient(*circle, begin, end, tolerance)) {
|
||||
out = circle;
|
||||
} else {
|
||||
//FIXME One may consider adjusting the arc to fit the worst offender as a last effort,
|
||||
// however Vojtech is not sure whether it is worth it.
|
||||
// Fitted radius must not be excessively large. If so, it is better to fit with a line segment.
|
||||
if (const double r2 = (*opt_center - first_point).squaredNorm(); r2 < max_radius * max_radius) {
|
||||
circle->center = opt_center->cast<coord_t>();
|
||||
circle->radius = (circle->radius > 0 ? 1.f : -1.f) * sqrt(r2);
|
||||
if (circle_approximation_sufficient(*circle, begin, end, tolerance)) {
|
||||
out = circle;
|
||||
} else {
|
||||
//FIXME One may consider adjusting the arc to fit the worst offender as a last effort,
|
||||
// however Vojtech is not sure whether it is worth it.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -657,10 +657,11 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
|
||||
auto printer_technology = printers.get_selected_preset().printer_technology();
|
||||
if (printer_technology == ptFFF && ! preferred_selection.filament.empty()) {
|
||||
const std::string& preferred_preset_name = get_preset_name_by_alias(Preset::Type::TYPE_FILAMENT, preferred_selection.filament, 0);
|
||||
if (auto it = filaments.find_preset_internal(preferred_preset_name);
|
||||
it != filaments.end() && it->is_visible && it->is_compatible) {
|
||||
filaments.select_preset_by_name_strict(preferred_preset_name);
|
||||
this->extruders_filaments.front().select_filament(filaments.get_selected_preset_name());
|
||||
ExtruderFilaments& extruder_frst = this->extruders_filaments.front();
|
||||
if (auto it = extruder_frst.find_filament_internal(preferred_preset_name);
|
||||
it != extruder_frst.end() && it->preset->is_visible && it->is_compatible) {
|
||||
if (extruder_frst.select_filament(preferred_preset_name))
|
||||
filaments.select_preset_by_name_strict(preferred_preset_name);
|
||||
}
|
||||
} else if (printer_technology == ptSLA && ! preferred_selection.sla_material.empty()) {
|
||||
const std::string& preferred_preset_name = get_preset_name_by_alias(Preset::Type::TYPE_SLA_MATERIAL, preferred_selection.sla_material);
|
||||
|
Loading…
x
Reference in New Issue
Block a user