mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 18:55:59 +08:00
Merge branch 'master' into fs_svg
This commit is contained in:
commit
92115754c4
@ -1,3 +1,5 @@
|
|||||||
|
min_slic3r_version = 2.6.0-alpha6
|
||||||
|
1.0.2 Updated g-code flavor and travel accelerations.
|
||||||
min_slic3r_version = 2.4.2
|
min_slic3r_version = 2.4.2
|
||||||
1.0.1 Added 350mm Voron v1 variant. Updated max print heights. Removed redundant v1 volcano nozzle variants.
|
1.0.1 Added 350mm Voron v1 variant. Updated max print heights. Removed redundant v1 volcano nozzle variants.
|
||||||
min_slic3r_version = 2.4.0-beta0
|
min_slic3r_version = 2.4.0-beta0
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
name = Voron
|
name = Voron
|
||||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
# 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.
|
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||||
config_version = 1.0.1
|
config_version = 1.0.2
|
||||||
# Where to get the updates from?
|
# Where to get the updates from?
|
||||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Voron/
|
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Voron/
|
||||||
|
|
||||||
@ -183,7 +183,8 @@ deretract_speed = 25
|
|||||||
end_gcode = print_end ;end script from macro
|
end_gcode = print_end ;end script from macro
|
||||||
extruder_colour = #FFE3CA
|
extruder_colour = #FFE3CA
|
||||||
extruder_offset = 0x0
|
extruder_offset = 0x0
|
||||||
gcode_flavor = marlin
|
gcode_flavor = klipper
|
||||||
|
autoemit_temperature_commands = 1
|
||||||
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
|
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
|
||||||
machine_max_acceleration_e = 10000
|
machine_max_acceleration_e = 10000
|
||||||
machine_max_acceleration_extruding = 1500
|
machine_max_acceleration_extruding = 1500
|
||||||
@ -672,7 +673,8 @@ brim_width = 0
|
|||||||
clip_multipart_objects = 1
|
clip_multipart_objects = 1
|
||||||
compatible_printers =
|
compatible_printers =
|
||||||
complete_objects = 0
|
complete_objects = 0
|
||||||
default_acceleration = 3000
|
default_acceleration = 2000
|
||||||
|
travel_acceleration = 3000
|
||||||
dont_support_bridges = 1
|
dont_support_bridges = 1
|
||||||
ensure_vertical_shell_thickness = 1
|
ensure_vertical_shell_thickness = 1
|
||||||
external_perimeters_first = 0
|
external_perimeters_first = 0
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "PlaceholderParser.hpp"
|
#include "PlaceholderParser.hpp"
|
||||||
#include "Exception.hpp"
|
#include "Exception.hpp"
|
||||||
#include "Flow.hpp"
|
#include "Flow.hpp"
|
||||||
|
#include "Utils.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@ -204,6 +205,7 @@ namespace client
|
|||||||
explicit expr(double d, const Iterator &it_begin, const Iterator &it_end) : m_type(TYPE_DOUBLE), it_range(it_begin, it_end) { m_data.d = d; }
|
explicit expr(double d, const Iterator &it_begin, const Iterator &it_end) : m_type(TYPE_DOUBLE), it_range(it_begin, it_end) { m_data.d = d; }
|
||||||
explicit expr(const char *s) : m_type(TYPE_STRING) { m_data.s = new std::string(s); }
|
explicit expr(const char *s) : m_type(TYPE_STRING) { m_data.s = new std::string(s); }
|
||||||
explicit expr(const std::string &s) : m_type(TYPE_STRING) { m_data.s = new std::string(s); }
|
explicit expr(const std::string &s) : m_type(TYPE_STRING) { m_data.s = new std::string(s); }
|
||||||
|
explicit expr(std::string &&s) : m_type(TYPE_STRING) { m_data.s = new std::string(std::move(s)); }
|
||||||
explicit expr(const std::string &s, const Iterator &it_begin, const Iterator &it_end) :
|
explicit expr(const std::string &s, const Iterator &it_begin, const Iterator &it_end) :
|
||||||
m_type(TYPE_STRING), it_range(it_begin, it_end) { m_data.s = new std::string(s); }
|
m_type(TYPE_STRING), it_range(it_begin, it_end) { m_data.s = new std::string(s); }
|
||||||
explicit expr(expr &&rhs, const Iterator &it_begin, const Iterator &it_end) : m_type(rhs.type()), it_range{ it_begin, it_end }
|
explicit expr(expr &&rhs, const Iterator &it_begin, const Iterator &it_end) : m_type(rhs.type()), it_range{ it_begin, it_end }
|
||||||
@ -904,9 +906,12 @@ namespace client
|
|||||||
const ConfigOption *opt = ctx->resolve_symbol(opt_key_str);
|
const ConfigOption *opt = ctx->resolve_symbol(opt_key_str);
|
||||||
if (opt == nullptr) {
|
if (opt == nullptr) {
|
||||||
// Check whether the opt_key ends with '_'.
|
// Check whether the opt_key ends with '_'.
|
||||||
if (opt_key_str.back() == '_')
|
if (opt_key_str.back() == '_') {
|
||||||
opt_key_str.resize(opt_key_str.size() - 1);
|
opt_key_str.resize(opt_key_str.size() - 1);
|
||||||
opt = ctx->resolve_symbol(opt_key_str);
|
opt = ctx->resolve_symbol(opt_key_str);
|
||||||
|
}
|
||||||
|
if (opt == nullptr)
|
||||||
|
ctx->throw_exception("Variable does not exist", opt_key);
|
||||||
}
|
}
|
||||||
if (! opt->is_vector())
|
if (! opt->is_vector())
|
||||||
ctx->throw_exception("Trying to index a scalar variable", opt_key);
|
ctx->throw_exception("Trying to index a scalar variable", opt_key);
|
||||||
@ -1701,7 +1706,7 @@ namespace client
|
|||||||
|
|
||||||
// This parser is to be used inside a raw[] directive to accept a single valid UTF-8 character.
|
// This parser is to be used inside a raw[] directive to accept a single valid UTF-8 character.
|
||||||
// If an invalid UTF-8 sequence is encountered, a qi::expectation_failure is thrown.
|
// If an invalid UTF-8 sequence is encountered, a qi::expectation_failure is thrown.
|
||||||
struct utf8_char_skipper_parser : qi::primitive_parser<utf8_char_skipper_parser>
|
struct utf8_char_parser : qi::primitive_parser<utf8_char_parser>
|
||||||
{
|
{
|
||||||
// Define the attribute type exposed by this parser component
|
// Define the attribute type exposed by this parser component
|
||||||
template <typename Context, typename Iterator>
|
template <typename Context, typename Iterator>
|
||||||
@ -1710,9 +1715,10 @@ namespace client
|
|||||||
typedef wchar_t type;
|
typedef wchar_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function is called during the actual parsing process
|
// This function is called during the actual parsing process to skip whitespaces.
|
||||||
|
// Also it throws if it encounters valid or invalid UTF-8 sequence.
|
||||||
template <typename Iterator, typename Context , typename Skipper, typename Attribute>
|
template <typename Iterator, typename Context , typename Skipper, typename Attribute>
|
||||||
bool parse(Iterator& first, Iterator const& last, Context& context, Skipper const& skipper, Attribute& attr) const
|
bool parse(Iterator &first, Iterator const &last, Context &context, Skipper const &skipper, Attribute& attr) const
|
||||||
{
|
{
|
||||||
// The skipper shall always be empty, any white space will be accepted.
|
// The skipper shall always be empty, any white space will be accepted.
|
||||||
// skip_over(first, last, skipper);
|
// skip_over(first, last, skipper);
|
||||||
@ -1762,6 +1768,38 @@ namespace client
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This parser is to be used inside a raw[] directive to accept a single valid UTF-8 character.
|
||||||
|
// If an invalid UTF-8 sequence is encountered, a qi::expectation_failure is thrown.
|
||||||
|
struct ascii_char_skipper_parser : public utf8_char_parser
|
||||||
|
{
|
||||||
|
// This function is called during the actual parsing process
|
||||||
|
template <typename Iterator, typename Context, typename Skipper, typename Attribute>
|
||||||
|
bool parse(Iterator &first, Iterator const &last, Context &context, Skipper const &skipper, Attribute &attr) const
|
||||||
|
{
|
||||||
|
Iterator it = first;
|
||||||
|
// Let the UTF-8 parser throw if it encounters an invalid UTF-8 sequence.
|
||||||
|
if (! utf8_char_parser::parse(it, last, context, skipper, attr))
|
||||||
|
return false;
|
||||||
|
char c = *first;
|
||||||
|
if (it - first > 1 || c < 0)
|
||||||
|
MyContext::throw_exception("Non-ASCII7 characters are only allowed inside text blocks and string literals, not inside code blocks.", IteratorRange(first, it));
|
||||||
|
if (c == '\r' || c == '\n' || c == '\t' || c == ' ') {
|
||||||
|
// Skip the whitespaces
|
||||||
|
++ first;
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
// Stop skipping, let this 7bit ASCII character be processed.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called during error handling to create a human readable string for the error context.
|
||||||
|
template <typename Context>
|
||||||
|
spirit::info what(Context&) const
|
||||||
|
{
|
||||||
|
return spirit::info("ASCII7_char");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct FactorActions {
|
struct FactorActions {
|
||||||
static void set_start_pos(Iterator &start_pos, expr &out)
|
static void set_start_pos(Iterator &start_pos, expr &out)
|
||||||
{ out.it_range = IteratorRange(start_pos, start_pos); }
|
{ out.it_range = IteratorRange(start_pos, start_pos); }
|
||||||
@ -1790,8 +1828,49 @@ namespace client
|
|||||||
if (ctx->skipping()) {
|
if (ctx->skipping()) {
|
||||||
out.reset();
|
out.reset();
|
||||||
out.it_range = it_range;
|
out.it_range = it_range;
|
||||||
} else
|
} else {
|
||||||
out = expr(std::string(it_range.begin() + 1, it_range.end() - 1), it_range.begin(), it_range.end());
|
// Unescape the string, UTF-8 safe.
|
||||||
|
std::string s;
|
||||||
|
auto begin = std::next(it_range.begin());
|
||||||
|
auto end = std::prev(it_range.end());
|
||||||
|
assert(begin <= end);
|
||||||
|
{
|
||||||
|
// 1) Get the size of the string after unescaping.
|
||||||
|
size_t len = 0;
|
||||||
|
for (auto it = begin; it != end;) {
|
||||||
|
if (*it == '\\') {
|
||||||
|
if (++ it == end ||
|
||||||
|
(*it != 'r' && *it != 'n' && *it != '"' && *it != '\\'))
|
||||||
|
ctx->throw_exception("Invalid escape sequence", {std::prev(it), std::next(it) });
|
||||||
|
++ len;
|
||||||
|
++ it;
|
||||||
|
} else {
|
||||||
|
size_t n = get_utf8_sequence_length(&*it, end - it);
|
||||||
|
len += n;
|
||||||
|
it += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// and reserve the string.
|
||||||
|
s.reserve(len);
|
||||||
|
}
|
||||||
|
// 2) Copy & unescape the string.
|
||||||
|
for (auto it = begin; it != end;) {
|
||||||
|
if (*it == '\\') {
|
||||||
|
char c = *(++ it);
|
||||||
|
if (c == 'r')
|
||||||
|
c = '\r';
|
||||||
|
else if (c == 'n')
|
||||||
|
c = '\n';
|
||||||
|
s += c;
|
||||||
|
++ it;
|
||||||
|
} else {
|
||||||
|
size_t n = get_utf8_sequence_length(&*it, end - it);
|
||||||
|
s.append(&*it, n);
|
||||||
|
it += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out = expr(std::move(s), it_range.begin(), it_range.end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static void expr_(expr &value, Iterator &end_pos, expr &out)
|
static void expr_(expr &value, Iterator &end_pos, expr &out)
|
||||||
{ auto begin_pos = out.it_range.begin(); out = expr(std::move(value), begin_pos, end_pos); }
|
{ auto begin_pos = out.it_range.begin(); out = expr(std::move(value), begin_pos, end_pos); }
|
||||||
@ -1807,11 +1886,13 @@ namespace client
|
|||||||
static void noexpr(expr &out) { out.reset(); }
|
static void noexpr(expr &out) { out.reset(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using skipper = ascii_char_skipper_parser;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Our macro_processor grammar
|
// Our macro_processor grammar
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Inspired by the C grammar rules https://www.lysator.liu.se/c/ANSI-C-grammar-y.html
|
// Inspired by the C grammar rules https://www.lysator.liu.se/c/ANSI-C-grammar-y.html
|
||||||
struct macro_processor : qi::grammar<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit_encoding::space_type>
|
struct macro_processor : qi::grammar<Iterator, std::string(const MyContext*), qi::locals<bool>, skipper>
|
||||||
{
|
{
|
||||||
macro_processor() : macro_processor::base_type(start)
|
macro_processor() : macro_processor::base_type(start)
|
||||||
{
|
{
|
||||||
@ -1825,7 +1906,7 @@ namespace client
|
|||||||
qi::no_skip_type no_skip;
|
qi::no_skip_type no_skip;
|
||||||
qi::real_parser<double, strict_real_policies_without_nan_inf> strict_double;
|
qi::real_parser<double, strict_real_policies_without_nan_inf> strict_double;
|
||||||
spirit_encoding::char_type char_;
|
spirit_encoding::char_type char_;
|
||||||
utf8_char_skipper_parser utf8char;
|
utf8_char_parser utf8char;
|
||||||
spirit::bool_type bool_;
|
spirit::bool_type bool_;
|
||||||
spirit::int_type int_;
|
spirit::int_type int_;
|
||||||
spirit::double_type double_;
|
spirit::double_type double_;
|
||||||
@ -2165,22 +2246,22 @@ namespace client
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generic expression over expr.
|
// Generic expression over expr.
|
||||||
typedef qi::rule<Iterator, expr(const MyContext*), spirit_encoding::space_type> RuleExpression;
|
typedef qi::rule<Iterator, expr(const MyContext*), skipper> RuleExpression;
|
||||||
|
|
||||||
// The start of the grammar.
|
// The start of the grammar.
|
||||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit_encoding::space_type> start;
|
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool>, skipper> start;
|
||||||
// A free-form text.
|
// A free-form text.
|
||||||
qi::rule<Iterator, std::string(), spirit_encoding::space_type> text;
|
qi::rule<Iterator, std::string(), skipper> text;
|
||||||
// A free-form text, possibly empty, possibly containing macro expansions.
|
// A free-form text, possibly empty, possibly containing macro expansions.
|
||||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> text_block;
|
qi::rule<Iterator, std::string(const MyContext*), skipper> text_block;
|
||||||
// Statements enclosed in curely braces {}
|
// Statements enclosed in curely braces {}
|
||||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> block, statement, macros, if_text_block, if_macros, else_macros;
|
qi::rule<Iterator, std::string(const MyContext*), skipper> block, statement, macros, if_text_block, if_macros, else_macros;
|
||||||
// Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index].
|
// Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index].
|
||||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> legacy_variable_expansion;
|
qi::rule<Iterator, std::string(const MyContext*), skipper> legacy_variable_expansion;
|
||||||
// Parsed identifier name.
|
// Parsed identifier name.
|
||||||
qi::rule<Iterator, IteratorRange(), spirit_encoding::space_type> identifier;
|
qi::rule<Iterator, IteratorRange(), skipper> identifier;
|
||||||
// Ternary operator (?:) over logical_or_expression.
|
// Ternary operator (?:) over logical_or_expression.
|
||||||
qi::rule<Iterator, expr(const MyContext*), qi::locals<bool>, spirit_encoding::space_type> conditional_expression;
|
qi::rule<Iterator, expr(const MyContext*), qi::locals<bool>, skipper> conditional_expression;
|
||||||
// Logical or over logical_and_expressions.
|
// Logical or over logical_and_expressions.
|
||||||
RuleExpression logical_or_expression;
|
RuleExpression logical_or_expression;
|
||||||
// Logical and over relational_expressions.
|
// Logical and over relational_expressions.
|
||||||
@ -2198,27 +2279,27 @@ namespace client
|
|||||||
// Accepting an optional parameter.
|
// Accepting an optional parameter.
|
||||||
RuleExpression optional_parameter;
|
RuleExpression optional_parameter;
|
||||||
// Rule to capture a regular expression enclosed in //.
|
// Rule to capture a regular expression enclosed in //.
|
||||||
qi::rule<Iterator, IteratorRange(), spirit_encoding::space_type> regular_expression;
|
qi::rule<Iterator, IteratorRange(), skipper> regular_expression;
|
||||||
// Evaluate boolean expression into bool.
|
// Evaluate boolean expression into bool.
|
||||||
qi::rule<Iterator, bool(const MyContext*), spirit_encoding::space_type> bool_expr_eval;
|
qi::rule<Iterator, bool(const MyContext*), skipper> bool_expr_eval;
|
||||||
// Reference of a scalar variable, or reference to a field of a vector variable.
|
// Reference of a scalar variable, or reference to a field of a vector variable.
|
||||||
qi::rule<Iterator, OptWithPos(const MyContext*), qi::locals<OptWithPos, int>, spirit_encoding::space_type> variable_reference;
|
qi::rule<Iterator, OptWithPos(const MyContext*), qi::locals<OptWithPos, int>, skipper> variable_reference;
|
||||||
// Rule to translate an identifier to a ConfigOption, or to fail.
|
// Rule to translate an identifier to a ConfigOption, or to fail.
|
||||||
qi::rule<Iterator, OptWithPos(const MyContext*), spirit_encoding::space_type> variable;
|
qi::rule<Iterator, OptWithPos(const MyContext*), skipper> variable;
|
||||||
// Evaluating whether a nullable variable is nil.
|
// Evaluating whether a nullable variable is nil.
|
||||||
qi::rule<Iterator, expr(const MyContext*), spirit_encoding::space_type> is_nil_test;
|
qi::rule<Iterator, expr(const MyContext*), skipper> is_nil_test;
|
||||||
// Evaluating "one of" list of patterns.
|
// Evaluating "one of" list of patterns.
|
||||||
qi::rule<Iterator, expr(const MyContext*), qi::locals<expr>, spirit_encoding::space_type> one_of;
|
qi::rule<Iterator, expr(const MyContext*), qi::locals<expr>, skipper> one_of;
|
||||||
qi::rule<Iterator, expr(const MyContext*, const expr ¶m), spirit_encoding::space_type> one_of_list;
|
qi::rule<Iterator, expr(const MyContext*, const expr ¶m), skipper> one_of_list;
|
||||||
// Evaluating the "interpolate_table" expression.
|
// Evaluating the "interpolate_table" expression.
|
||||||
qi::rule<Iterator, expr(const MyContext*), qi::locals<expr>, spirit_encoding::space_type> interpolate_table;
|
qi::rule<Iterator, expr(const MyContext*), qi::locals<expr>, skipper> interpolate_table;
|
||||||
qi::rule<Iterator, InterpolateTableContext(const MyContext*, const expr ¶m), spirit_encoding::space_type> interpolate_table_list;
|
qi::rule<Iterator, InterpolateTableContext(const MyContext*, const expr ¶m), skipper> interpolate_table_list;
|
||||||
|
|
||||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit_encoding::space_type> if_else_output;
|
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool>, skipper> if_else_output;
|
||||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<OptWithPos>, spirit_encoding::space_type> assignment_statement;
|
qi::rule<Iterator, std::string(const MyContext*), qi::locals<OptWithPos>, skipper> assignment_statement;
|
||||||
// Allocating new local or global variables.
|
// Allocating new local or global variables.
|
||||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool, MyContext::NewOldVariable>, spirit_encoding::space_type> new_variable_statement;
|
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool, MyContext::NewOldVariable>, skipper> new_variable_statement;
|
||||||
qi::rule<Iterator, std::vector<expr>(const MyContext*), spirit_encoding::space_type> initializer_list;
|
qi::rule<Iterator, std::vector<expr>(const MyContext*), skipper> initializer_list;
|
||||||
|
|
||||||
qi::symbols<char> keywords;
|
qi::symbols<char> keywords;
|
||||||
};
|
};
|
||||||
@ -2229,7 +2310,7 @@ static const client::macro_processor g_macro_processor_instance;
|
|||||||
static std::string process_macro(const std::string &templ, client::MyContext &context)
|
static std::string process_macro(const std::string &templ, client::MyContext &context)
|
||||||
{
|
{
|
||||||
std::string output;
|
std::string output;
|
||||||
phrase_parse(templ.begin(), templ.end(), g_macro_processor_instance(&context), spirit_encoding::space_type{}, output);
|
phrase_parse(templ.begin(), templ.end(), g_macro_processor_instance(&context), client::skipper{}, output);
|
||||||
if (! context.error_message.empty()) {
|
if (! context.error_message.empty()) {
|
||||||
if (context.error_message.back() != '\n' && context.error_message.back() != '\r')
|
if (context.error_message.back() != '\n' && context.error_message.back() != '\r')
|
||||||
context.error_message += '\n';
|
context.error_message += '\n';
|
||||||
|
@ -1509,7 +1509,9 @@ void PrintObject::discover_vertical_shells()
|
|||||||
Polygons internal_volume;
|
Polygons internal_volume;
|
||||||
{
|
{
|
||||||
Polygons shrinked_bottom_slice = idx_layer > 0 ? to_polygons(m_layers[idx_layer - 1]->lslices) : Polygons{};
|
Polygons shrinked_bottom_slice = idx_layer > 0 ? to_polygons(m_layers[idx_layer - 1]->lslices) : Polygons{};
|
||||||
Polygons shrinked_upper_slice = idx_layer > 0 ? to_polygons(m_layers[idx_layer + 1]->lslices) : Polygons{};
|
Polygons shrinked_upper_slice = (idx_layer + 1) < m_layers.size() ?
|
||||||
|
to_polygons(m_layers[idx_layer + 1]->lslices) :
|
||||||
|
Polygons{};
|
||||||
internal_volume = intersection(shrinked_bottom_slice, shrinked_upper_slice);
|
internal_volume = intersection(shrinked_bottom_slice, shrinked_upper_slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1739,7 +1741,7 @@ void PrintObject::bridge_over_infill()
|
|||||||
|
|
||||||
// cluster layers by depth needed for thick bridges. Each cluster is to be processed by single thread sequentially, so that bridges cannot appear one on another
|
// cluster layers by depth needed for thick bridges. Each cluster is to be processed by single thread sequentially, so that bridges cannot appear one on another
|
||||||
std::vector<std::vector<size_t>> clustered_layers_for_threads;
|
std::vector<std::vector<size_t>> clustered_layers_for_threads;
|
||||||
float target_flow_height_factor = 0.75;
|
float target_flow_height_factor = 0.9;
|
||||||
{
|
{
|
||||||
std::vector<size_t> layers_with_candidates;
|
std::vector<size_t> layers_with_candidates;
|
||||||
std::map<size_t, Polygons> layer_area_covered_by_candidates;
|
std::map<size_t, Polygons> layer_area_covered_by_candidates;
|
||||||
@ -1768,7 +1770,7 @@ void PrintObject::bridge_over_infill()
|
|||||||
if (clustered_layers_for_threads.empty() ||
|
if (clustered_layers_for_threads.empty() ||
|
||||||
this->get_layer(clustered_layers_for_threads.back().back())->print_z <
|
this->get_layer(clustered_layers_for_threads.back().back())->print_z <
|
||||||
this->get_layer(pair.first)->print_z -
|
this->get_layer(pair.first)->print_z -
|
||||||
this->get_layer(pair.first)->regions()[0]->flow(frSolidInfill, true).height() * target_flow_height_factor -
|
this->get_layer(pair.first)->regions()[0]->bridging_flow(frSolidInfill, true).height() * target_flow_height_factor -
|
||||||
EPSILON ||
|
EPSILON ||
|
||||||
intersection(layer_area_covered_by_candidates[clustered_layers_for_threads.back().back()],
|
intersection(layer_area_covered_by_candidates[clustered_layers_for_threads.back().back()],
|
||||||
layer_area_covered_by_candidates[pair.first])
|
layer_area_covered_by_candidates[pair.first])
|
||||||
@ -1798,9 +1800,9 @@ void PrintObject::bridge_over_infill()
|
|||||||
ExPolygons not_sparse_infill{};
|
ExPolygons not_sparse_infill{};
|
||||||
double bottom_z = po->get_layer(lidx)->print_z - target_flow_height * target_flow_height_factor - EPSILON;
|
double bottom_z = po->get_layer(lidx)->print_z - target_flow_height * target_flow_height_factor - EPSILON;
|
||||||
for (int i = int(lidx) - 1; i >= 0; --i) {
|
for (int i = int(lidx) - 1; i >= 0; --i) {
|
||||||
// Stop iterating if layer is lower than bottom_z.
|
// Stop iterating if layer is lower than bottom_z and at least one iteration was made
|
||||||
const Layer *layer = po->get_layer(i);
|
const Layer *layer = po->get_layer(i);
|
||||||
if (layer->print_z < bottom_z)
|
if (layer->print_z < bottom_z && i < int(lidx) - 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (const LayerRegion *region : layer->regions()) {
|
for (const LayerRegion *region : layer->regions()) {
|
||||||
@ -2103,9 +2105,10 @@ void PrintObject::bridge_over_infill()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gather deep infill areas, where thick bridges fit
|
// Gather deep infill areas, where thick bridges fit
|
||||||
coordf_t spacing = surfaces_by_layer[lidx].front().region->flow(frSolidInfill, true).scaled_spacing();
|
coordf_t spacing = surfaces_by_layer[lidx].front().region->bridging_flow(frSolidInfill, true).scaled_spacing();
|
||||||
coordf_t target_flow_height = surfaces_by_layer[lidx].front().region->flow(frSolidInfill, true).height() * target_flow_height_factor;
|
coordf_t target_flow_height = surfaces_by_layer[lidx].front().region->bridging_flow(frSolidInfill, true).height() *
|
||||||
Polygons deep_infill_area = gather_areas_w_depth(po, lidx, target_flow_height);
|
target_flow_height_factor;
|
||||||
|
Polygons deep_infill_area = gather_areas_w_depth(po, lidx, target_flow_height);
|
||||||
|
|
||||||
{
|
{
|
||||||
// Now also remove area that has been already filled on lower layers by bridging expansion - For this
|
// Now also remove area that has been already filled on lower layers by bridging expansion - For this
|
||||||
@ -2144,20 +2147,27 @@ void PrintObject::bridge_over_infill()
|
|||||||
expansion_area = closing(expansion_area, SCALED_EPSILON);
|
expansion_area = closing(expansion_area, SCALED_EPSILON);
|
||||||
expansion_area = intersection(expansion_area, deep_infill_area);
|
expansion_area = intersection(expansion_area, deep_infill_area);
|
||||||
Polylines anchors = intersection_pl(infill_lines[lidx - 1], shrink(expansion_area, spacing));
|
Polylines anchors = intersection_pl(infill_lines[lidx - 1], shrink(expansion_area, spacing));
|
||||||
|
Polygons internal_unsupported_area = shrink(deep_infill_area, spacing * 4.5);
|
||||||
|
|
||||||
#ifdef DEBUG_BRIDGE_OVER_INFILL
|
#ifdef DEBUG_BRIDGE_OVER_INFILL
|
||||||
debug_draw(std::to_string(lidx) + "_" + std::to_string(cluster_idx) + "_" + std::to_string(job_idx) + "_" + "_total_area",
|
debug_draw(std::to_string(lidx) + "_" + std::to_string(cluster_idx) + "_" + std::to_string(job_idx) + "_" + "_total_area",
|
||||||
to_lines(total_fill_area), to_lines(expansion_area), to_lines(deep_infill_area), to_lines(anchors));
|
to_lines(total_fill_area), to_lines(expansion_area), to_lines(deep_infill_area), to_lines(anchors));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
std::vector<CandidateSurface> expanded_surfaces;
|
std::vector<CandidateSurface> expanded_surfaces;
|
||||||
expanded_surfaces.reserve(surfaces_by_layer[lidx].size());
|
expanded_surfaces.reserve(surfaces_by_layer[lidx].size());
|
||||||
for (const CandidateSurface &candidate : surfaces_by_layer[lidx]) {
|
for (const CandidateSurface &candidate : surfaces_by_layer[lidx]) {
|
||||||
const Flow &flow = candidate.region->bridging_flow(frSolidInfill, true);
|
const Flow &flow = candidate.region->bridging_flow(frSolidInfill, true);
|
||||||
Polygons area_to_be_bridge = expand(candidate.new_polys, flow.scaled_spacing());
|
Polygons area_to_be_bridge = expand(candidate.new_polys, flow.scaled_spacing());
|
||||||
area_to_be_bridge = intersection(area_to_be_bridge, deep_infill_area);
|
area_to_be_bridge = intersection(area_to_be_bridge, deep_infill_area);
|
||||||
Polygons limiting_area = union_(area_to_be_bridge, expansion_area);
|
|
||||||
|
area_to_be_bridge.erase(std::remove_if(area_to_be_bridge.begin(), area_to_be_bridge.end(),
|
||||||
|
[internal_unsupported_area](const Polygon &p) {
|
||||||
|
return intersection({p}, internal_unsupported_area).empty();
|
||||||
|
}),
|
||||||
|
area_to_be_bridge.end());
|
||||||
|
|
||||||
|
Polygons limiting_area = union_(area_to_be_bridge, expansion_area);
|
||||||
|
|
||||||
if (area_to_be_bridge.empty())
|
if (area_to_be_bridge.empty())
|
||||||
continue;
|
continue;
|
||||||
|
@ -529,7 +529,7 @@ SCENARIO("Perimeters3", "[Perimeters]")
|
|||||||
auto config = Slic3r::DynamicPrintConfig::full_print_config_with({
|
auto config = Slic3r::DynamicPrintConfig::full_print_config_with({
|
||||||
{ "skirts", 0 },
|
{ "skirts", 0 },
|
||||||
{ "perimeters", 3 },
|
{ "perimeters", 3 },
|
||||||
{ "layer_height", 0.4 },
|
{ "layer_height", 0.15 },
|
||||||
{ "bridge_speed", 99 },
|
{ "bridge_speed", 99 },
|
||||||
{ "enable_dynamic_overhang_speeds", false },
|
{ "enable_dynamic_overhang_speeds", false },
|
||||||
// to prevent bridging over sparse infill
|
// to prevent bridging over sparse infill
|
||||||
|
@ -44,6 +44,27 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") {
|
|||||||
SECTION("multiple expressions with semicolons 2") { REQUIRE(parser.process("{temperature[foo];;temperature[foo];}") == "357357"); }
|
SECTION("multiple expressions with semicolons 2") { REQUIRE(parser.process("{temperature[foo];;temperature[foo];}") == "357357"); }
|
||||||
SECTION("multiple expressions with semicolons 3") { REQUIRE(parser.process("{temperature[foo];;;temperature[foo];;}") == "357357"); }
|
SECTION("multiple expressions with semicolons 3") { REQUIRE(parser.process("{temperature[foo];;;temperature[foo];;}") == "357357"); }
|
||||||
|
|
||||||
|
SECTION("parsing string with escaped characters") { REQUIRE(parser.process("{\"hu\\nha\\\\\\\"ha\\\"\"}") == "hu\nha\\\"ha\""); }
|
||||||
|
|
||||||
|
WHEN("An UTF-8 character is used inside the code block") {
|
||||||
|
THEN("A std::runtime_error exception is thrown.") {
|
||||||
|
// full-width plus sign instead of plain +
|
||||||
|
REQUIRE_THROWS_AS(parser.process("{1\xEF\xBC\x8B 3}"), std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("An UTF-8 character is used inside a string") {
|
||||||
|
THEN("UTF-8 sequence is processed correctly when quoted") {
|
||||||
|
// japanese "cool" or "stylish"
|
||||||
|
REQUIRE(parser.process("{1+\"\xE3\x81\x8B\xE3\x81\xA3\xE3\x81\x93\xE3\x81\x84\xE3\x81\x84\"+\" \"+3}") == "1\xE3\x81\x8B\xE3\x81\xA3\xE3\x81\x93\xE3\x81\x84\xE3\x81\x84 3");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("An UTF-8 character is used inside a string") {
|
||||||
|
THEN("UTF-8 sequence is processed correctly outside of code blocks") {
|
||||||
|
// japanese "cool" or "stylish"
|
||||||
|
REQUIRE(parser.process("{1+3}\xE3\x81\x8B\xE3\x81\xA3\xE3\x81\x93\xE3\x81\x84\xE3\x81\x84") == "4\xE3\x81\x8B\xE3\x81\xA3\xE3\x81\x93\xE3\x81\x84\xE3\x81\x84");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test the math expressions.
|
// Test the math expressions.
|
||||||
SECTION("math: 2*3") { REQUIRE(parser.process("{2*3}") == "6"); }
|
SECTION("math: 2*3") { REQUIRE(parser.process("{2*3}") == "6"); }
|
||||||
SECTION("math: 2*3/6") { REQUIRE(parser.process("{2*3/6}") == "1"); }
|
SECTION("math: 2*3/6") { REQUIRE(parser.process("{2*3/6}") == "1"); }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user