Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_gcode_viewer

This commit is contained in:
Enrico Turri
2020-03-03 08:34:51 +01:00
108 changed files with 29542 additions and 21922 deletions
+48 -6
View File
@@ -855,7 +855,12 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons)
}
// Outer offset shall not split the input contour into multiples. It is expected, that the solution will be non empty and it will contain just a single polygon.
ClipperLib::Paths fix_after_outer_offset(const ClipperLib::Path &input, ClipperLib::PolyFillType filltype, bool reverse_result)
ClipperLib::Paths fix_after_outer_offset(
const ClipperLib::Path &input,
// combination of default prameters to correspond to void ClipperOffset::Execute(Paths& solution, double delta)
// to produce a CCW output contour from CCW input contour for a positive offset.
ClipperLib::PolyFillType filltype, // = ClipperLib::pftPositive
bool reverse_result) // = false
{
ClipperLib::Paths solution;
if (! input.empty()) {
@@ -867,8 +872,13 @@ ClipperLib::Paths fix_after_outer_offset(const ClipperLib::Path &input, ClipperL
return solution;
}
// Inner offset may split the source contour into multiple contours, but one shall not be inside the other.
ClipperLib::Paths fix_after_inner_offset(const ClipperLib::Path &input, ClipperLib::PolyFillType filltype, bool reverse_result)
// Inner offset may split the source contour into multiple contours, but one resulting contour shall not lie inside the other.
ClipperLib::Paths fix_after_inner_offset(
const ClipperLib::Path &input,
// combination of default prameters to correspond to void ClipperOffset::Execute(Paths& solution, double delta)
// to produce a CCW output contour from CCW input contour for a negative offset.
ClipperLib::PolyFillType filltype, // = ClipperLib::pftNegative
bool reverse_result) // = true
{
ClipperLib::Paths solution;
if (! input.empty()) {
@@ -1041,12 +1051,20 @@ Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::v
// 1) Offset the outer contour.
ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, true);
#ifndef NDEBUG
for (auto &c : contours)
assert(ClipperLib::Area(c) > 0.);
#endif /* NDEBUG */
// 2) Offset the holes one by one, collect the results.
ClipperLib::Paths holes;
holes.reserve(expoly.holes.size());
for (const Polygon& hole : expoly.holes)
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, false));
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, false));
#ifndef NDEBUG
for (auto &c : holes)
assert(ClipperLib::Area(c) > 0.);
#endif /* NDEBUG */
// 3) Subtract holes from the contours.
ClipperLib::Paths output;
@@ -1077,12 +1095,20 @@ for (const std::vector<float>& ds : deltas)
// 1) Offset the outer contour.
ClipperLib::Paths contours = fix_after_outer_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftPositive, false);
#ifndef NDEBUG
for (auto &c : contours)
assert(ClipperLib::Area(c) > 0.);
#endif /* NDEBUG */
// 2) Offset the holes one by one, collect the results.
ClipperLib::Paths holes;
holes.reserve(expoly.holes.size());
for (const Polygon& hole : expoly.holes)
append(holes, fix_after_inner_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, true));
#ifndef NDEBUG
for (auto &c : holes)
assert(ClipperLib::Area(c) > 0.);
#endif /* NDEBUG */
// 3) Subtract holes from the contours.
ClipperLib::Paths output;
@@ -1113,12 +1139,20 @@ for (const std::vector<float>& ds : deltas)
// 1) Offset the outer contour.
ClipperLib::Paths contours = fix_after_outer_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftPositive, false);
#ifndef NDEBUG
for (auto &c : contours)
assert(ClipperLib::Area(c) > 0.);
#endif /* NDEBUG */
// 2) Offset the holes one by one, collect the results.
ClipperLib::Paths holes;
holes.reserve(expoly.holes.size());
for (const Polygon& hole : expoly.holes)
append(holes, fix_after_inner_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, true));
#ifndef NDEBUG
for (auto &c : holes)
assert(ClipperLib::Area(c) > 0.);
#endif /* NDEBUG */
// 3) Subtract holes from the contours.
unscaleClipperPolygons(contours);
@@ -1152,13 +1186,21 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s
#endif /* NDEBUG */
// 1) Offset the outer contour.
ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, false);
ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, true);
#ifndef NDEBUG
for (auto &c : contours)
assert(ClipperLib::Area(c) > 0.);
#endif /* NDEBUG */
// 2) Offset the holes one by one, collect the results.
ClipperLib::Paths holes;
holes.reserve(expoly.holes.size());
for (const Polygon& hole : expoly.holes)
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, true));
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, false));
#ifndef NDEBUG
for (auto &c : holes)
assert(ClipperLib::Area(c) > 0.);
#endif /* NDEBUG */
// 3) Subtract holes from the contours.
unscaleClipperPolygons(contours);
+1
View File
@@ -686,6 +686,7 @@ public:
ConfigOption* clone() const override { return new ConfigOptionString(*this); }
ConfigOptionString& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionString &rhs) const { return this->value == rhs.value; }
bool empty() const { return this->value.empty(); }
std::string serialize() const override
{
+6
View File
@@ -13,6 +13,12 @@ static constexpr char ColorChangeCode[] = "M600";
static constexpr char PausePrintCode[] = "M601";
static constexpr char ToolChangeCode[] = "tool_change";
enum CustomGcodeType
{
cgtColorChange,
cgtPausePrint,
};
namespace CustomGCode {
struct Item
+34 -4
View File
@@ -524,11 +524,22 @@ static inline void smooth_compensation_banded(const Points &contour, float band,
}
}
ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &external_perimeter_flow, const double compensation)
#ifndef NDEBUG
static bool validate_expoly_orientation(const ExPolygon &expoly)
{
bool valid = expoly.contour.is_counter_clockwise();
for (auto &h : expoly.holes)
valid &= h.is_clockwise();
return valid;
}
#endif /* NDEBUG */
ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, double min_contour_width, const double compensation)
{
// The contour shall be wide enough to apply the external perimeter plus compensation on both sides.
double min_contour_width = double(external_perimeter_flow.scaled_width() + external_perimeter_flow.scaled_spacing());
assert(validate_expoly_orientation(input_expoly));
double scaled_compensation = scale_(compensation);
min_contour_width = scale_(min_contour_width);
double min_contour_width_compensated = min_contour_width + 2. * scaled_compensation;
// Make the search radius a bit larger for the averaging in contour_distance over a fan of rays to work.
double search_radius = min_contour_width_compensated + min_contour_width * 0.5;
@@ -547,6 +558,7 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &
{
EdgeGrid::Grid grid;
ExPolygon simplified = input_expoly.simplify(SCALED_EPSILON).front();
assert(validate_expoly_orientation(simplified));
BoundingBox bbox = get_extents(simplified.contour);
bbox.offset(SCALED_EPSILON);
grid.set_bbox(bbox);
@@ -559,6 +571,7 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &
Polygon &poly = (idx_contour == 0) ? resampled.contour : resampled.holes[idx_contour - 1];
std::vector<ResampledPoint> resampled_point_parameters;
poly.points = resample_polygon(poly.points, resample_interval, resampled_point_parameters);
assert(poly.is_counter_clockwise() == (idx_contour == 0));
std::vector<float> dists = contour_distance2(grid, idx_contour, poly.points, resampled_point_parameters, scaled_compensation, search_radius);
for (float &d : dists) {
// printf("Point %d, Distance: %lf\n", int(&d - dists.data()), unscale<double>(d));
@@ -593,10 +606,18 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &
assert(out_vec.size() == 1);
}
}
assert(validate_expoly_orientation(out));
return out;
}
ExPolygon elephant_foot_compensation(const ExPolygon &input, const Flow &external_perimeter_flow, const double compensation)
{
// The contour shall be wide enough to apply the external perimeter plus compensation on both sides.
double min_contour_width = double(external_perimeter_flow.width + external_perimeter_flow.spacing());
return elephant_foot_compensation(input, min_contour_width, compensation);
}
ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &external_perimeter_flow, const double compensation)
{
ExPolygons out;
@@ -606,4 +627,13 @@ ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &exter
return out;
}
ExPolygons elephant_foot_compensation(const ExPolygons &input, double min_contour_width, const double compensation)
{
ExPolygons out;
out.reserve(input.size());
for (const ExPolygon &expoly : input)
out.emplace_back(elephant_foot_compensation(expoly, min_contour_width, compensation));
return out;
}
} // namespace Slic3r
@@ -8,6 +8,8 @@ namespace Slic3r {
class Flow;
ExPolygon elephant_foot_compensation(const ExPolygon &input, double min_countour_width, const double compensation);
ExPolygons elephant_foot_compensation(const ExPolygons &input, double min_countour_width, const double compensation);
ExPolygon elephant_foot_compensation(const ExPolygon &input, const Flow &external_perimeter_flow, const double compensation);
ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &external_perimeter_flow, const double compensation);
+4 -12
View File
@@ -11,18 +11,10 @@ void filter_by_extrusion_role_in_place(ExtrusionEntitiesPtr &extrusion_entities,
if (role != erMixed) {
auto first = extrusion_entities.begin();
auto last = extrusion_entities.end();
auto result = first;
while (first != last) {
// The caller wants only paths with a specific extrusion role.
auto role2 = (*first)->role();
if (role != role2) {
// This extrusion entity does not match the role asked.
assert(role2 != erMixed);
*result = *first;
++ result;
}
++ first;
}
extrusion_entities.erase(
std::remove_if(first, last, [&role](const ExtrusionEntity* ee) {
return ee->role() != role; }),
last);
}
}
+10 -4
View File
@@ -11,6 +11,12 @@
namespace Slic3r {
FlowErrorNegativeSpacing::FlowErrorNegativeSpacing() :
FlowError("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?") {}
FlowErrorNegativeFlow::FlowErrorNegativeFlow() :
FlowError("Flow::mm3_per_mm() produced negative flow. Did you set some extrusion width too small?") {}
// This static method returns a sane extrusion width default.
float Flow::auto_extrusion_width(FlowRole role, float nozzle_diameter)
{
@@ -52,7 +58,7 @@ static inline FlowRole opt_key_to_flow_role(const std::string &opt_key)
static inline void throw_on_missing_variable(const std::string &opt_key, const char *dependent_opt_key)
{
throw std::runtime_error((boost::format(L("Cannot calculate extrusion width for %1%: Variable \"%2%\" not accessible.")) % opt_key % dependent_opt_key).str());
throw FlowErrorMissingVariable((boost::format(L("Cannot calculate extrusion width for %1%: Variable \"%2%\" not accessible.")) % opt_key % dependent_opt_key).str());
}
// Used to provide hints to the user on default extrusion width values, and to provide reasonable values to the PlaceholderParser.
@@ -174,7 +180,7 @@ float Flow::spacing() const
#endif
// assert(res > 0.f);
if (res <= 0.f)
throw std::runtime_error("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?");
throw FlowErrorNegativeSpacing();
return res;
}
@@ -190,7 +196,7 @@ float Flow::spacing(const Flow &other) const
0.5 * this->spacing() + 0.5 * other.spacing());
// assert(res > 0.f);
if (res <= 0.f)
throw std::runtime_error("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?");
throw FlowErrorNegativeSpacing();
return res;
}
@@ -204,7 +210,7 @@ double Flow::mm3_per_mm() const
float(this->height * (this->width - this->height * (1. - 0.25 * PI)));
//assert(res > 0.);
if (res <= 0.)
throw std::runtime_error("Flow::mm3_per_mm() produced negative flow. Did you set some extrusion width too small?");
throw FlowErrorNegativeFlow();
return res;
}
+25
View File
@@ -27,6 +27,31 @@ enum FlowRole {
frSupportMaterialInterface,
};
class FlowError : public std::invalid_argument
{
public:
FlowError(const std::string& what_arg) : invalid_argument(what_arg) {}
FlowError(const char* what_arg) : invalid_argument(what_arg) {}
};
class FlowErrorNegativeSpacing : public FlowError
{
public:
FlowErrorNegativeSpacing();
};
class FlowErrorNegativeFlow : public FlowError
{
public:
FlowErrorNegativeFlow();
};
class FlowErrorMissingVariable : public FlowError
{
public:
FlowErrorMissingVariable(const std::string& what_arg) : FlowError(what_arg) {}
};
class Flow
{
public:
+8 -7
View File
@@ -1060,9 +1060,9 @@ namespace DoExport {
print_statistics.clear();
print_statistics.estimated_normal_print_time = normal_time_estimator.get_time_dhm/*s*/();
print_statistics.estimated_silent_print_time = silent_time_estimator_enabled ? silent_time_estimator.get_time_dhm/*s*/() : "N/A";
print_statistics.estimated_normal_color_print_times = normal_time_estimator.get_color_times_dhms(true);
print_statistics.estimated_normal_custom_gcode_print_times = normal_time_estimator.get_custom_gcode_times_dhm(true);
if (silent_time_estimator_enabled)
print_statistics.estimated_silent_color_print_times = silent_time_estimator.get_color_times_dhms(true);
print_statistics.estimated_silent_custom_gcode_print_times = silent_time_estimator.get_custom_gcode_times_dhm(true);
print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges);
if (! extruders.empty()) {
std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
@@ -1104,11 +1104,11 @@ namespace DoExport {
print_statistics.total_wipe_tower_cost += has_wipe_tower ? (extruded_volume - extruder.extruded_volume())* extruder.filament_density() * 0.001 * extruder.filament_cost() * 0.001 : 0.;
}
filament_stats_string_out += out_filament_used_mm.first;
filament_stats_string_out += out_filament_used_cm3.first;
filament_stats_string_out += "\n" + out_filament_used_cm3.first;
if (out_filament_used_g.second)
filament_stats_string_out += out_filament_used_g.first;
filament_stats_string_out += "\n" + out_filament_used_g.first;
if (out_filament_cost.second)
filament_stats_string_out += out_filament_cost.first;
filament_stats_string_out += "\n" + out_filament_cost.first;
}
return filament_stats_string_out;
}
@@ -1550,6 +1550,7 @@ void GCode::_do_export(Print& print, FILE* file)
m_writer.extruders(),
// Modifies
print.m_print_statistics));
_write(file, "\n");
_write_format(file, "; total filament used [g] = %.1lf\n", print.m_print_statistics.total_weight);
_write_format(file, "; total filament cost = %.1lf\n", print.m_print_statistics.total_cost);
if (print.m_print_statistics.total_toolchanges > 0)
@@ -1852,7 +1853,7 @@ namespace ProcessLayer
if (!pause_print_msg.empty())
gcode += "M117 " + pause_print_msg + "\n";
// add tag for time estimator
//gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n";
gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n";
}
else // custom Gcode
{
@@ -3436,7 +3437,7 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
if (this_override == nullptr || (*this_override)[copy] == -int(extruder)-1)
target_eec.emplace_back(entities[i]);
}
for (; i < overrides.size(); ++ i)
for (; i < entities.size(); ++ i)
target_eec.emplace_back(entities[i]);
}
}
+62 -30
View File
@@ -174,6 +174,7 @@ namespace Slic3r {
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; _TE_SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
const std::string GCodeTimeEstimator::Color_Change_Tag = "PRINT_COLOR_CHANGE";
const std::string GCodeTimeEstimator::Pause_Print_Tag = "PRINT_PAUSE";
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
: m_mode(mode)
@@ -212,8 +213,8 @@ namespace Slic3r {
}
_calculate_time();
if (m_needs_color_times && (m_color_time_cache != 0.0f))
m_color_times.push_back(m_color_time_cache);
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
#if ENABLE_MOVE_STATS
_log_moves_stats();
@@ -230,8 +231,8 @@ namespace Slic3r {
_calculate_time();
if (m_needs_color_times && (m_color_time_cache != 0.0f))
m_color_times.push_back(m_color_time_cache);
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
#if ENABLE_MOVE_STATS
_log_moves_stats();
@@ -245,8 +246,8 @@ namespace Slic3r {
m_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
_calculate_time();
if (m_needs_color_times && (m_color_time_cache != 0.0f))
m_color_times.push_back(m_color_time_cache);
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
#if ENABLE_MOVE_STATS
_log_moves_stats();
@@ -263,8 +264,8 @@ namespace Slic3r {
m_parser.parse_line(line, action);
_calculate_time();
if (m_needs_color_times && (m_color_time_cache != 0.0f))
m_color_times.push_back(m_color_time_cache);
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache});
#if ENABLE_MOVE_STATS
_log_moves_stats();
@@ -351,8 +352,8 @@ namespace Slic3r {
}
// check tags
// remove color change tag
if (gcode_line == "; " + Color_Change_Tag)
// remove Color_Change_Tag and Pause_Print_Tag
if (gcode_line == "; " + Color_Change_Tag || gcode_line == "; " + Pause_Print_Tag)
continue;
// replaces placeholders for initial line M73 with the real lines
@@ -717,25 +718,26 @@ namespace Slic3r {
return _get_time_minutes(get_time());
}
std::vector<float> GCodeTimeEstimator::get_color_times() const
std::vector<std::pair<CustomGcodeType, float>> GCodeTimeEstimator::get_custom_gcode_times() const
{
return m_color_times;
return m_custom_gcode_times;
}
std::vector<std::string> GCodeTimeEstimator::get_color_times_dhms(bool include_remaining) const
{
std::vector<std::string> ret;
float total_time = 0.0f;
for (float t : m_color_times)
// for (float t : m_color_times)
for (auto t : m_custom_gcode_times)
{
std::string time = _get_time_dhms(t);
std::string time = _get_time_dhms(t.second);
if (include_remaining)
{
time += " (";
time += _get_time_dhms(m_time - total_time);
time += ")";
}
total_time += t;
total_time += t.second;
ret.push_back(time);
}
return ret;
@@ -745,20 +747,42 @@ namespace Slic3r {
{
std::vector<std::string> ret;
float total_time = 0.0f;
for (float t : m_color_times)
// for (float t : m_color_times)
for (auto t : m_custom_gcode_times)
{
std::string time = _get_time_minutes(t);
std::string time = _get_time_minutes(t.second);
if (include_remaining)
{
time += " (";
time += _get_time_minutes(m_time - total_time);
time += ")";
}
total_time += t;
total_time += t.second;
}
return ret;
}
std::vector<std::pair<CustomGcodeType, std::string>> GCodeTimeEstimator::get_custom_gcode_times_dhm(bool include_remaining) const
{
std::vector<std::pair<CustomGcodeType, std::string>> ret;
float total_time = 0.0f;
for (auto t : m_custom_gcode_times)
{
std::string time = _get_time_dhm(t.second);
if (include_remaining)
{
time += " (";
time += _get_time_dhm(m_time - total_time);
time += ")";
}
total_time += t.second;
ret.push_back({t.first, time});
}
return ret;
}
// Return an estimate of the memory consumed by the time estimator.
size_t GCodeTimeEstimator::memory_used() const
{
@@ -791,9 +815,9 @@ namespace Slic3r {
m_last_st_synchronized_block_id = -1;
m_needs_color_times = false;
m_color_times.clear();
m_color_time_cache = 0.0f;
m_needs_custom_gcode_times = false;
m_custom_gcode_times.clear();
m_custom_gcode_time_cache = 0.0f;
}
void GCodeTimeEstimator::_reset_time()
@@ -814,7 +838,7 @@ namespace Slic3r {
_recalculate_trapezoids();
m_time += get_additional_time();
m_color_time_cache += get_additional_time();
m_custom_gcode_time_cache += get_additional_time();
for (int i = m_last_st_synchronized_block_id + 1; i < (int)m_blocks.size(); ++i)
{
@@ -835,7 +859,7 @@ namespace Slic3r {
it->second.time += block_time;
#endif // ENABLE_MOVE_STATS
m_color_time_cache += block_time;
m_custom_gcode_time_cache += block_time;
}
m_last_st_synchronized_block_id = (int)m_blocks.size() - 1;
@@ -1466,26 +1490,34 @@ namespace Slic3r {
{
std::string comment = line.comment();
// color change tag
// Color_Change_Tag
size_t pos = comment.find(Color_Change_Tag);
if (pos != comment.npos)
{
_process_color_change_tag();
_process_custom_gcode_tag(cgtColorChange);
return true;
}
// Pause_Print_Tag
pos = comment.find(Pause_Print_Tag);
if (pos != comment.npos)
{
_process_custom_gcode_tag(cgtPausePrint);
return true;
}
return false;
}
void GCodeTimeEstimator::_process_color_change_tag()
void GCodeTimeEstimator::_process_custom_gcode_tag(CustomGcodeType code)
{
PROFILE_FUNC();
m_needs_color_times = true;
m_needs_custom_gcode_times = true;
_calculate_time();
if (m_color_time_cache != 0.0f)
if (m_custom_gcode_time_cache != 0.0f)
{
m_color_times.push_back(m_color_time_cache);
m_color_time_cache = 0.0f;
m_custom_gcode_times.push_back({code, m_custom_gcode_time_cache});
m_custom_gcode_time_cache = 0.0f;
}
}
+14 -8
View File
@@ -4,6 +4,7 @@
#include "libslic3r.h"
#include "PrintConfig.hpp"
#include "GCodeReader.hpp"
#include "CustomGCode.hpp"
#define ENABLE_MOVE_STATS 0
@@ -23,6 +24,7 @@ namespace Slic3r {
static const std::string Silent_Last_M73_Output_Placeholder_Tag;
static const std::string Color_Change_Tag;
static const std::string Pause_Print_Tag;
enum EMode : unsigned char
{
@@ -240,10 +242,10 @@ namespace Slic3r {
int m_last_st_synchronized_block_id;
float m_time; // s
// data to calculate color print times
bool m_needs_color_times;
std::vector<float> m_color_times;
float m_color_time_cache;
// data to calculate custom code times
bool m_needs_custom_gcode_times;
std::vector<std::pair<CustomGcodeType, float>> m_custom_gcode_times;
float m_custom_gcode_time_cache;
#if ENABLE_MOVE_STATS
MovesStatsMap _moves_stats;
@@ -369,8 +371,8 @@ namespace Slic3r {
// Returns the estimated time, in minutes (integer)
std::string get_time_minutes() const;
// Returns the estimated time, in seconds, for each color
std::vector<float> get_color_times() const;
// Returns the estimated time, in seconds, for each custom gcode
std::vector<std::pair<CustomGcodeType, float>> get_custom_gcode_times() const;
// Returns the estimated time, in format DDd HHh MMm SSs, for each color
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
@@ -380,6 +382,10 @@ namespace Slic3r {
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
std::vector<std::string> get_color_times_minutes(bool include_remaining) const;
// Returns the estimated time, in format DDd HHh MMm, for each custom_gcode
// If include_remaining==true the strings will be formatted as: "time for custom_gcode (remaining time at color start)"
std::vector<std::pair<CustomGcodeType, std::string>> get_custom_gcode_times_dhm(bool include_remaining) const;
// Return an estimate of the memory consumed by the time estimator.
size_t memory_used() const;
@@ -460,8 +466,8 @@ namespace Slic3r {
// Returns true if any tag has been processed
bool _process_tags(const GCodeReader::GCodeLine& line);
// Processes color change tag
void _process_color_change_tag();
// Processes ColorChangeTag and PausePrintTag
void _process_custom_gcode_tag(CustomGcodeType code);
// Simulates firmware st_synchronize() call
void _simulate_st_synchronize();
+5 -1
View File
@@ -613,8 +613,12 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone());
m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
// We want the filament overrides to be applied over their respective extruder parameters by the PlaceholderParser.
// see "Placeholders do not respect filament overrides." GH issue #3649
m_placeholder_parser.apply_config(filament_overrides);
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
m_config.apply_only(new_full_config, print_diff, true);
//FIXME use move semantics once ConfigBase supports it.
m_config.apply(filament_overrides);
// Handle changes to object config defaults
m_default_object_config.apply_only(new_full_config, object_diff, true);
@@ -1935,7 +1939,7 @@ void Print::_make_brim()
for (size_t i = 0; i < loops_trimmed_order.size();) {
// Find all pieces that the initial loop was split into.
size_t j = i + 1;
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].first == loops_trimmed_order[j].first; ++ j) ;
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].second == loops_trimmed_order[j].second; ++ j) ;
const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first;
if (i + 1 == j && first_path.size() > 3 && first_path.front().X == first_path.back().X && first_path.front().Y == first_path.back().Y) {
auto *loop = new ExtrusionLoop();
+8 -8
View File
@@ -153,15 +153,15 @@ public:
Layer* get_layer(int idx) { return m_layers[idx]; }
// Get a layer exactly at print_z.
const Layer* get_layer_at_printz(coordf_t print_z) const {
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [print_z](const Layer *layer) { return layer->print_z < print_z; });
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [print_z](const Layer *layer) { return layer->print_z < print_z; });
return (it == m_layers.end() || (*it)->print_z != print_z) ? nullptr : *it;
}
Layer* get_layer_at_printz(coordf_t print_z) { return const_cast<Layer*>(std::as_const(*this).get_layer_at_printz(print_z)); }
// Get a layer approximately at print_z.
const Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon) const {
coordf_t limit = print_z + epsilon;
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [limit](const Layer *layer) { return layer->print_z < limit; });
return (it == m_layers.end() || (*it)->print_z < print_z - epsilon) ? nullptr : *it;
coordf_t limit = print_z - epsilon;
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [limit](const Layer *layer) { return layer->print_z < limit; });
return (it == m_layers.end() || (*it)->print_z > print_z + epsilon) ? nullptr : *it;
}
Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon) { return const_cast<Layer*>(std::as_const(*this).get_layer_at_printz(print_z, epsilon)); }
@@ -305,8 +305,8 @@ struct PrintStatistics
PrintStatistics() { clear(); }
std::string estimated_normal_print_time;
std::string estimated_silent_print_time;
std::vector<std::string> estimated_normal_color_print_times;
std::vector<std::string> estimated_silent_color_print_times;
std::vector<std::pair<CustomGcodeType, std::string>> estimated_normal_custom_gcode_print_times;
std::vector<std::pair<CustomGcodeType, std::string>> estimated_silent_custom_gcode_print_times;
double total_used_filament;
double total_extruded_volume;
double total_cost;
@@ -326,8 +326,8 @@ struct PrintStatistics
void clear() {
estimated_normal_print_time.clear();
estimated_silent_print_time.clear();
estimated_normal_color_print_times.clear();
estimated_silent_color_print_times.clear();
estimated_normal_custom_gcode_print_times.clear();
estimated_silent_custom_gcode_print_times.clear();
total_used_filament = 0.;
total_extruded_volume = 0.;
total_cost = 0.;
+30 -11
View File
@@ -113,6 +113,16 @@ void PrintConfigDef::init_common_params()
"If left blank, the default OS CA certificate repository is used.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString(""));
def = this->add("elefant_foot_compensation", coFloat);
def->label = L("Elephant foot compensation");
def->category = L("Advanced");
def->tooltip = L("The first layer will be shrunk in the XY plane by the configured value "
"to compensate for the 1st layer squish aka an Elephant Foot effect.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.2));
}
void PrintConfigDef::init_fff_params()
@@ -371,16 +381,6 @@ void PrintConfigDef::init_fff_params()
def->min = 0;
def->set_default_value(new ConfigOptionFloat(6));
def = this->add("elefant_foot_compensation", coFloat);
def->label = L("Elephant foot compensation");
def->category = L("Advanced");
def->tooltip = L("The first layer will be shrunk in the XY plane by the configured value "
"to compensate for the 1st layer squish aka an Elephant Foot effect.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0));
def = this->add("end_gcode", coString);
def->label = L("End G-code");
def->tooltip = L("This end procedure is inserted at the end of the output file. "
@@ -2442,6 +2442,15 @@ void PrintConfigDef::init_sla_params()
"to the sign of the correction.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0.0));
def = this->add("elefant_foot_min_width", coFloat);
def->label = L("Elephant foot minimum width");
def->category = L("Advanced");
def->tooltip = L("Minimum width of features to maintain when doing elephant foot compensation.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.2));
def = this->add("gamma_correction", coFloat);
def->label = L("Printer gamma correction");
@@ -2644,6 +2653,16 @@ void PrintConfigDef::init_sla_params()
def->max = 15;
def->mode = comSimple;
def->set_default_value(new ConfigOptionFloat(1.0));
def = this->add("support_max_bridges_on_pillar", coInt);
def->label = L("Max bridges on a pillar");
def->tooltip = L(
"Maximum number of bridges that can be placed on a pillar. Bridges "
"hold support point pinheads and connect to pillars as small branches.");
def->min = 0;
def->max = 50;
def->mode = comExpert;
def->set_default_value(new ConfigOptionInt(3));
def = this->add("support_pillar_connection_mode", coEnum);
def->label = L("Support pillar connection mode");
@@ -2840,7 +2859,7 @@ void PrintConfigDef::init_sla_params()
def->min = 45;
def->max = 90;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(45.0));
def->set_default_value(new ConfigOptionFloat(90.0));
def = this->add("pad_around_object", coBool);
def->label = L("Pad around object");
+8
View File
@@ -980,6 +980,9 @@ public:
// Radius in mm of the support pillars.
ConfigOptionFloat support_pillar_diameter /*= 0.8*/;
// How much bridge (supporting another pinhead) can be placed on a pillar.
ConfigOptionInt support_max_bridges_on_pillar;
// How the pillars are bridged together
ConfigOptionEnum<SLAPillarConnectionMode> support_pillar_connection_mode;
@@ -1101,6 +1104,7 @@ protected:
OPT_PTR(support_head_penetration);
OPT_PTR(support_head_width);
OPT_PTR(support_pillar_diameter);
OPT_PTR(support_max_bridges_on_pillar);
OPT_PTR(support_pillar_connection_mode);
OPT_PTR(support_buildplate_only);
OPT_PTR(support_pillar_widening_factor);
@@ -1175,6 +1179,8 @@ public:
ConfigOptionBool display_mirror_y;
ConfigOptionFloats relative_correction;
ConfigOptionFloat absolute_correction;
ConfigOptionFloat elefant_foot_compensation;
ConfigOptionFloat elefant_foot_min_width;
ConfigOptionFloat gamma_correction;
ConfigOptionFloat fast_tilt_time;
ConfigOptionFloat slow_tilt_time;
@@ -1198,6 +1204,8 @@ protected:
OPT_PTR(display_orientation);
OPT_PTR(relative_correction);
OPT_PTR(absolute_correction);
OPT_PTR(elefant_foot_compensation);
OPT_PTR(elefant_foot_min_width);
OPT_PTR(gamma_correction);
OPT_PTR(fast_tilt_time);
OPT_PTR(slow_tilt_time);
+9 -8
View File
@@ -1139,10 +1139,9 @@ void PrintObject::discover_vertical_shells()
}
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
polygons_append(holes, cache_top_botom_regions[idx_layer].holes);
{
if (int n_top_layers = region_config.top_solid_layers.value; n_top_layers > 0) {
// Gather top regions projected to this layer.
coordf_t print_z = layer->print_z;
int n_top_layers = region_config.top_solid_layers.value;
coordf_t print_z = layer->print_z;
for (int i = int(idx_layer) + 1;
i < int(cache_top_botom_regions.size()) &&
(i < int(idx_layer) + n_top_layers ||
@@ -1159,10 +1158,9 @@ void PrintObject::discover_vertical_shells()
}
}
}
{
if (int n_bottom_layers = region_config.bottom_solid_layers.value; n_bottom_layers > 0) {
// Gather bottom regions projected to this layer.
coordf_t bottom_z = layer->bottom_z();
int n_bottom_layers = region_config.bottom_solid_layers.value;
coordf_t bottom_z = layer->bottom_z();
for (int i = int(idx_layer) - 1;
i >= 0 &&
(i > int(idx_layer) - n_bottom_layers ||
@@ -2356,6 +2354,9 @@ void PrintObject::discover_horizontal_shells()
for (size_t idx_surface_type = 0; idx_surface_type < 3; ++ idx_surface_type) {
m_print->throw_if_canceled();
SurfaceType type = (idx_surface_type == 0) ? stTop : (idx_surface_type == 1) ? stBottom : stBottomBridge;
int num_solid_layers = (type == stTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
if (num_solid_layers == 0)
continue;
// Find slices of current type for current layer.
// Use slices instead of fill_surfaces, because they also include the perimeter area,
// which needs to be propagated in shells; we need to grow slices like we did for
@@ -2384,9 +2385,9 @@ void PrintObject::discover_horizontal_shells()
// Scatter top / bottom regions to other layers. Scattering process is inherently serial, it is difficult to parallelize without locking.
for (int n = (type == stTop) ? int(i) - 1 : int(i) + 1;
(type == stTop) ?
(n >= 0 && (int(i) - n < region_config.top_solid_layers.value ||
(n >= 0 && (int(i) - n < num_solid_layers ||
print_z - m_layers[n]->print_z < region_config.top_solid_min_thickness.value - EPSILON)) :
(n < int(m_layers.size()) && (n - int(i) < region_config.bottom_solid_layers.value ||
(n < int(m_layers.size()) && (n - int(i) < num_solid_layers ||
m_layers[n]->bottom_z() - bottom_z < region_config.bottom_solid_min_thickness.value - EPSILON));
(type == stTop) ? -- n : ++ n)
{
-1
View File
@@ -41,7 +41,6 @@ const double SupportConfig::max_dual_pillar_height_mm = 35.0;
const double SupportConfig::optimizer_rel_score_diff = 1e-6;
const unsigned SupportConfig::optimizer_max_iterations = 1000;
const unsigned SupportConfig::pillar_cascade_neighbors = 3;
const unsigned SupportConfig::max_bridges_on_pillar = 3;
void SupportTree::retrieve_full_mesh(TriangleMesh &outmesh) const {
outmesh.merge(retrieve_mesh(MeshType::Support));
+3 -1
View File
@@ -83,6 +83,8 @@ struct SupportConfig
// body. This is only useful when elevation is set to zero.
double pillar_base_safety_distance_mm = 0.5;
unsigned max_bridges_on_pillar = 3;
double head_fullwidth() const {
return 2 * head_front_radius_mm + head_width_mm +
2 * head_back_radius_mm - head_penetration_mm;
@@ -103,7 +105,7 @@ struct SupportConfig
static const double optimizer_rel_score_diff;
static const unsigned optimizer_max_iterations;
static const unsigned pillar_cascade_neighbors;
static const unsigned max_bridges_on_pillar;
};
enum class MeshType { Support, Pad };
+6 -2
View File
@@ -65,6 +65,8 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c)
c.support_base_safety_distance.getFloat() < EPSILON ?
scfg.safety_distance_mm : c.support_base_safety_distance.getFloat();
scfg.max_bridges_on_pillar = unsigned(c.support_max_bridges_on_pillar.getInt());
return scfg;
}
@@ -785,6 +787,8 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
"material_correction",
"relative_correction",
"absolute_correction",
"elefant_foot_compensation",
"elefant_foot_min_width",
"gamma_correction"
};
@@ -944,6 +948,7 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|| opt_key == "support_head_penetration"
|| opt_key == "support_head_width"
|| opt_key == "support_pillar_diameter"
|| opt_key == "support_max_bridges_on_pillar"
|| opt_key == "support_pillar_connection_mode"
|| opt_key == "support_buildplate_only"
|| opt_key == "support_base_diameter"
@@ -1087,8 +1092,7 @@ const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
const ExPolygons &SliceRecord::get_slice(SliceOrigin o) const
{
size_t idx = o == soModel ? m_model_slices_idx :
m_support_slices_idx;
size_t idx = o == soModel ? m_model_slices_idx : m_support_slices_idx;
if(m_po == nullptr) return EMPTY_SLICE;
+4
View File
@@ -152,6 +152,10 @@ public:
}
const ExPolygons& get_slice(SliceOrigin o) const;
size_t get_slice_idx(SliceOrigin o) const
{
return o == soModel ? m_model_slices_idx : m_support_slices_idx;
}
};
private:
+46 -21
View File
@@ -8,6 +8,8 @@
#include <libslic3r/SLA/Pad.hpp>
#include <libslic3r/SLA/SupportPointGenerator.hpp>
#include <libslic3r/ElephantFootCompensation.hpp>
#include <libslic3r/ClipperUtils.hpp>
// For geometry algorithms with native Clipper types (no copies and conversions)
@@ -78,6 +80,40 @@ SLAPrint::Steps::Steps(SLAPrint *print)
, objectstep_scale{(max_objstatus - min_objstatus) / (objcount * 100.0)}
{}
void SLAPrint::Steps::apply_printer_corrections(SLAPrintObject &po, SliceOrigin o)
{
if (o == soSupport && !po.m_supportdata) return;
auto faded_lyrs = size_t(po.m_config.faded_layers.getInt());
double min_w = m_print->m_printer_config.elefant_foot_min_width.getFloat() / 2.;
double start_efc = m_print->m_printer_config.elefant_foot_compensation.getFloat();
double doffs = m_print->m_printer_config.absolute_correction.getFloat();
coord_t clpr_offs = scaled(doffs);
faded_lyrs = std::min(po.m_slice_index.size(), faded_lyrs);
auto efc = [start_efc, faded_lyrs](size_t pos) {
return (faded_lyrs - 1 - pos) * start_efc / (faded_lyrs - 1);
};
std::vector<ExPolygons> &slices = o == soModel ?
po.m_model_slices :
po.m_supportdata->support_slices;
if (clpr_offs != 0) for (size_t i = 0; i < po.m_slice_index.size(); ++i) {
size_t idx = po.m_slice_index[i].get_slice_idx(o);
if (idx < slices.size())
slices[idx] = offset_ex(slices[idx], float(clpr_offs));
}
if (start_efc > 0.) for (size_t i = 0; i < faded_lyrs; ++i) {
size_t idx = po.m_slice_index[i].get_slice_idx(o);
if (idx < slices.size())
slices[idx] = elephant_foot_compensation(slices[idx], min_w, efc(i));
}
}
void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
{
po.m_hollowing_data.reset();
@@ -236,20 +272,15 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
}
auto mit = slindex_it;
double doffs = m_print->m_printer_config.absolute_correction.getFloat();
coord_t clpr_offs = scaled(doffs);
for(size_t id = 0;
for (size_t id = 0;
id < po.m_model_slices.size() && mit != po.m_slice_index.end();
id++)
{
// We apply the printer correction offset here.
if(clpr_offs != 0)
po.m_model_slices[id] =
offset_ex(po.m_model_slices[id], float(clpr_offs));
id++) {
mit->set_model_slice_idx(po, id); ++mit;
}
// We apply the printer correction offset here.
apply_printer_corrections(po, soModel);
if(po.m_config.supports_enable.getBool() || po.m_config.pad_enable.getBool())
{
po.m_supportdata.reset(new SLAPrintObject::SupportData(mesh));
@@ -446,21 +477,15 @@ void SLAPrint::Steps::slice_supports(SLAPrintObject &po) {
auto heights = reserve_vector<float>(po.m_slice_index.size());
for(auto& rec : po.m_slice_index) heights.emplace_back(rec.slice_level());
sd->support_slices = sd->support_tree_ptr->slice(
heights, float(po.config().slice_closing_radius.value));
heights, float(po.config().slice_closing_radius.value));
}
double doffs = m_print->m_printer_config.absolute_correction.getFloat();
coord_t clpr_offs = scaled(doffs);
for (size_t i = 0; i < sd->support_slices.size() && i < po.m_slice_index.size(); ++i) {
// We apply the printer correction offset here.
if (clpr_offs != 0)
sd->support_slices[i] = offset_ex(sd->support_slices[i], float(clpr_offs));
for (size_t i = 0; i < sd->support_slices.size() && i < po.m_slice_index.size(); ++i)
po.m_slice_index[i].set_support_slice_idx(po, i);
}
apply_printer_corrections(po, soSupport);
// Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update
// status to the 3D preview to load the SLA slices.
+2
View File
@@ -43,6 +43,8 @@ private:
bool canceled() const { return m_print->canceled(); }
void initialize_printer_input();
void apply_printer_corrections(SLAPrintObject &po, SliceOrigin o);
public:
Steps(SLAPrint *print);
+4 -2
View File
@@ -43,10 +43,12 @@
//==================
// 2.2.0.beta1 techs
// 2.2.0.rc1 techs
//==================
#define ENABLE_2_2_0_BETA1 1
#define ENABLE_2_2_0_RC1 1
// Enable hack to remove crash when closing on OSX 10.9.5
#define ENABLE_HACK_CLOSING_ON_OSX_10_9_5 (1 && ENABLE_2_2_0_RC1)
//==================
// 2.3.0.alpha1 techs
+12 -4
View File
@@ -64,15 +64,23 @@ extern std::string normalize_utf8_nfc(const char *src);
// for a short while, so the file may not be movable. Retry while we see recoverable errors.
extern std::error_code rename_file(const std::string &from, const std::string &to);
enum CopyFileResult {
SUCCESS = 0,
FAIL_COPY_FILE,
FAIL_FILES_DIFFERENT,
FAIL_RENAMING,
FAIL_CHECK_ORIGIN_NOT_OPENED,
FAIL_CHECK_TARGET_NOT_OPENED
};
// Copy a file, adjust the access attributes, so that the target is writable.
int copy_file_inner(const std::string &from, const std::string &to);
CopyFileResult copy_file_inner(const std::string &from, const std::string &to);
// Copy file to a temp file first, then rename it to the final file name.
// If with_check is true, then the content of the copied file is compared to the content
// of the source file before renaming.
extern int copy_file(const std::string &from, const std::string &to, const bool with_check = false);
extern CopyFileResult copy_file(const std::string &from, const std::string &to, const bool with_check = false);
// Compares two files, returns 0 if identical, -1 if different.
extern int check_copy(const std::string& origin, const std::string& copy);
// Compares two files if identical.
extern CopyFileResult check_copy(const std::string& origin, const std::string& copy);
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
// https://github.com/prusa3d/PrusaSlicer/issues/1298
+17 -15
View File
@@ -417,7 +417,7 @@ std::error_code rename_file(const std::string &from, const std::string &to)
#endif
}
int copy_file_inner(const std::string& from, const std::string& to)
CopyFileResult copy_file_inner(const std::string& from, const std::string& to)
{
const boost::filesystem::path source(from);
const boost::filesystem::path target(to);
@@ -433,38 +433,40 @@ int copy_file_inner(const std::string& from, const std::string& to)
boost::filesystem::permissions(target, perms, ec);
boost::filesystem::copy_file(source, target, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec) {
return -1;
return FAIL_COPY_FILE;
}
boost::filesystem::permissions(target, perms, ec);
return 0;
return SUCCESS;
}
int copy_file(const std::string &from, const std::string &to, const bool with_check)
CopyFileResult copy_file(const std::string &from, const std::string &to, const bool with_check)
{
std::string to_temp = to + ".tmp";
int ret_val = copy_file_inner(from,to_temp);
if(ret_val == 0)
CopyFileResult ret_val = copy_file_inner(from,to_temp);
if(ret_val == SUCCESS)
{
if (with_check)
ret_val = check_copy(from, to_temp);
if (ret_val == 0 && rename_file(to_temp, to))
ret_val = -3;
ret_val = FAIL_RENAMING;
}
return ret_val;
}
int check_copy(const std::string &origin, const std::string &copy)
CopyFileResult check_copy(const std::string &origin, const std::string &copy)
{
std::ifstream f1(origin, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
std::ifstream f2(copy, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
boost::nowide::ifstream f1(origin, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
boost::nowide::ifstream f2(copy, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
if (f1.fail() || f2.fail())
return -2;
if (f1.fail())
return FAIL_CHECK_ORIGIN_NOT_OPENED;
if (f2.fail())
return FAIL_CHECK_TARGET_NOT_OPENED;
std::streampos fsize = f1.tellg();
if (fsize != f2.tellg())
return -2;
return FAIL_FILES_DIFFERENT;
f1.seekg(0, std::ifstream::beg);
f2.seekg(0, std::ifstream::beg);
@@ -481,12 +483,12 @@ int check_copy(const std::string &origin, const std::string &copy)
if (origin_cnt != copy_cnt ||
(origin_cnt > 0 && std::memcmp(buffer_origin.data(), buffer_copy.data(), origin_cnt) != 0))
// Files are different.
return -2;
return FAIL_FILES_DIFFERENT;
fsize -= origin_cnt;
} while (f1.good() && f2.good());
// All data has been read and compared equal.
return (f1.eof() && f2.eof() && fsize == 0) ? 0 : -2;
return (f1.eof() && f2.eof() && fsize == 0) ? SUCCESS : FAIL_FILES_DIFFERENT;
}
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.