mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 10:19:02 +08:00
SPE-1784: New compressed (binary) gcode format integration
Added GCode Block save/load with no encoding Changed blocks order to: File metadata|Printer metadata|Thumbnails[]|Print metadata|Slicer metadata|GCode[]
This commit is contained in:
parent
989cf7a27d
commit
3f5de75bae
@ -997,94 +997,107 @@ namespace DoExport {
|
||||
{
|
||||
std::string filament_stats_string_out;
|
||||
|
||||
print_statistics.clear();
|
||||
print_statistics.clear();
|
||||
print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges);
|
||||
print_statistics.initial_extruder_id = initial_extruder_id;
|
||||
std::vector<std::string> filament_types;
|
||||
if (! extruders.empty()) {
|
||||
std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_cm3("; filament used [cm3] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_g ("; filament used [g] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_cost ("; filament cost = ", 0);
|
||||
for (const Extruder &extruder : extruders) {
|
||||
print_statistics.printing_extruders.emplace_back(extruder.id());
|
||||
filament_types.emplace_back(config.filament_type.get_at(extruder.id()));
|
||||
if (! extruders.empty()) {
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
std::pair<std::string, unsigned int> out_filament_used_mm(PrintStatistics::FilamentUsedMmMask + " ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_cm3(PrintStatistics::FilamentUsedCm3Mask + " ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_g(PrintStatistics::FilamentUsedGMask + " ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_cost(PrintStatistics::FilamentCostMask + " ", 0);
|
||||
#else
|
||||
std::pair<std::string, unsigned int> out_filament_used_mm("; filament used [mm] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_cm3("; filament used [cm3] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_g ("; filament used [g] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_cost("; filament cost = ", 0);
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
for (const Extruder &extruder : extruders) {
|
||||
print_statistics.printing_extruders.emplace_back(extruder.id());
|
||||
filament_types.emplace_back(config.filament_type.get_at(extruder.id()));
|
||||
|
||||
double used_filament = extruder.used_filament() + (has_wipe_tower ? wipe_tower_data.used_filament[extruder.id()] : 0.f);
|
||||
double extruded_volume = extruder.extruded_volume() + (has_wipe_tower ? wipe_tower_data.used_filament[extruder.id()] * 2.4052f : 0.f); // assumes 1.75mm filament diameter
|
||||
double filament_weight = extruded_volume * extruder.filament_density() * 0.001;
|
||||
double filament_cost = filament_weight * extruder.filament_cost() * 0.001;
|
||||
auto append = [&extruder](std::pair<std::string, unsigned int> &dst, const char *tmpl, double value) {
|
||||
assert(is_decimal_separator_point());
|
||||
while (dst.second < extruder.id()) {
|
||||
// Fill in the non-printing extruders with zeros.
|
||||
dst.first += (dst.second > 0) ? ", 0" : "0";
|
||||
++ dst.second;
|
||||
}
|
||||
if (dst.second > 0)
|
||||
dst.first += ", ";
|
||||
char buf[64];
|
||||
sprintf(buf, tmpl, value);
|
||||
dst.first += buf;
|
||||
++ dst.second;
|
||||
};
|
||||
double used_filament = extruder.used_filament() + (has_wipe_tower ? wipe_tower_data.used_filament[extruder.id()] : 0.f);
|
||||
double extruded_volume = extruder.extruded_volume() + (has_wipe_tower ? wipe_tower_data.used_filament[extruder.id()] * 2.4052f : 0.f); // assumes 1.75mm filament diameter
|
||||
double filament_weight = extruded_volume * extruder.filament_density() * 0.001;
|
||||
double filament_cost = filament_weight * extruder.filament_cost() * 0.001;
|
||||
auto append = [&extruder](std::pair<std::string, unsigned int> &dst, const char *tmpl, double value) {
|
||||
assert(is_decimal_separator_point());
|
||||
while (dst.second < extruder.id()) {
|
||||
// Fill in the non-printing extruders with zeros.
|
||||
dst.first += (dst.second > 0) ? ", 0" : "0";
|
||||
++ dst.second;
|
||||
}
|
||||
if (dst.second > 0)
|
||||
dst.first += ", ";
|
||||
char buf[64];
|
||||
sprintf(buf, tmpl, value);
|
||||
dst.first += buf;
|
||||
++ dst.second;
|
||||
};
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
if (export_binary_data) {
|
||||
char buf[128];
|
||||
sprintf(buf, "%.2lf", used_filament);
|
||||
binary_data.print_metadata.raw_data.push_back({ "filament used [mm]", std::string(buf) });
|
||||
sprintf(buf, "%.2lf", extruded_volume * 0.001);
|
||||
binary_data.print_metadata.raw_data.push_back({ "filament used [cm3]", std::string(buf) });
|
||||
}
|
||||
else {
|
||||
if (export_binary_data) {
|
||||
char buf[128];
|
||||
sprintf(buf, "%.2lf", used_filament);
|
||||
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::FilamentUsedMm, std::string(buf) });
|
||||
sprintf(buf, "%.2lf", extruded_volume * 0.001);
|
||||
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::FilamentUsedCm3, std::string(buf) });
|
||||
}
|
||||
else {
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
append(out_filament_used_mm, "%.2lf", used_filament);
|
||||
append(out_filament_used_cm3, "%.2lf", extruded_volume * 0.001);
|
||||
append(out_filament_used_mm, "%.2lf", used_filament);
|
||||
append(out_filament_used_cm3, "%.2lf", extruded_volume * 0.001);
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
if (filament_weight > 0.) {
|
||||
print_statistics.total_weight = print_statistics.total_weight + filament_weight;
|
||||
if (filament_weight > 0.) {
|
||||
print_statistics.total_weight = print_statistics.total_weight + filament_weight;
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
if (export_binary_data) {
|
||||
char buf[128];
|
||||
sprintf(buf, "%.2lf", filament_weight);
|
||||
binary_data.print_metadata.raw_data.push_back({ "filament used [g]", std::string(buf) });
|
||||
}
|
||||
else
|
||||
if (export_binary_data) {
|
||||
char buf[128];
|
||||
sprintf(buf, "%.2lf", filament_weight);
|
||||
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::FilamentUsedG, std::string(buf) });
|
||||
}
|
||||
else
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
append(out_filament_used_g, "%.2lf", filament_weight);
|
||||
if (filament_cost > 0.) {
|
||||
print_statistics.total_cost = print_statistics.total_cost + filament_cost;
|
||||
append(out_filament_used_g, "%.2lf", filament_weight);
|
||||
if (filament_cost > 0.) {
|
||||
print_statistics.total_cost = print_statistics.total_cost + filament_cost;
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
if (export_binary_data) {
|
||||
char buf[128];
|
||||
sprintf(buf, "%.2lf", filament_cost);
|
||||
binary_data.print_metadata.raw_data.push_back({ "filament cost", std::string(buf) });
|
||||
}
|
||||
else
|
||||
if (export_binary_data) {
|
||||
char buf[128];
|
||||
sprintf(buf, "%.2lf", filament_cost);
|
||||
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::FilamentCost, std::string(buf) });
|
||||
}
|
||||
else
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
append(out_filament_cost, "%.2lf", filament_cost);
|
||||
}
|
||||
}
|
||||
print_statistics.total_used_filament += used_filament;
|
||||
print_statistics.total_extruded_volume += extruded_volume;
|
||||
print_statistics.total_wipe_tower_filament += has_wipe_tower ? used_filament - extruder.used_filament() : 0.;
|
||||
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 += "\n" + out_filament_used_cm3.first;
|
||||
if (out_filament_used_g.second)
|
||||
filament_stats_string_out += "\n" + out_filament_used_g.first;
|
||||
if (out_filament_cost.second)
|
||||
filament_stats_string_out += "\n" + out_filament_cost.first;
|
||||
print_statistics.initial_filament_type = config.filament_type.get_at(initial_extruder_id);
|
||||
std::sort(filament_types.begin(), filament_types.end());
|
||||
print_statistics.printing_filament_types = filament_types.front();
|
||||
for (size_t i = 1; i < filament_types.size(); ++ i) {
|
||||
print_statistics.printing_filament_types += ",";
|
||||
print_statistics.printing_filament_types += filament_types[i];
|
||||
}
|
||||
append(out_filament_cost, "%.2lf", filament_cost);
|
||||
}
|
||||
}
|
||||
print_statistics.total_used_filament += used_filament;
|
||||
print_statistics.total_extruded_volume += extruded_volume;
|
||||
print_statistics.total_wipe_tower_filament += has_wipe_tower ? used_filament - extruder.used_filament() : 0.;
|
||||
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.;
|
||||
}
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
if (!export_binary_data) {
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
filament_stats_string_out += out_filament_used_mm.first;
|
||||
filament_stats_string_out += "\n" + out_filament_used_cm3.first;
|
||||
if (out_filament_used_g.second)
|
||||
filament_stats_string_out += "\n" + out_filament_used_g.first;
|
||||
if (out_filament_cost.second)
|
||||
filament_stats_string_out += "\n" + out_filament_cost.first;
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
print_statistics.initial_filament_type = config.filament_type.get_at(initial_extruder_id);
|
||||
std::sort(filament_types.begin(), filament_types.end());
|
||||
print_statistics.printing_filament_types = filament_types.front();
|
||||
for (size_t i = 1; i < filament_types.size(); ++ i) {
|
||||
print_statistics.printing_filament_types += ",";
|
||||
print_statistics.printing_filament_types += filament_types[i];
|
||||
}
|
||||
}
|
||||
return filament_stats_string_out;
|
||||
}
|
||||
@ -1216,8 +1229,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
this->m_avoid_crossing_curled_overhangs.init_bed_shape(get_bed_shape(print.config()));
|
||||
}
|
||||
|
||||
// Write information on the generator.
|
||||
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
if (!export_to_binary_gcode)
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
// Write information on the generator.
|
||||
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
// if exporting gcode in ascii format, generate the thumbnails here
|
||||
@ -1582,7 +1598,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
|
||||
// Get filament stats.
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
file.write(DoExport::update_print_stats_and_format_filament_stats(
|
||||
const std::string filament_stats_string_out = DoExport::update_print_stats_and_format_filament_stats(
|
||||
// Const inputs
|
||||
has_wipe_tower, print.wipe_tower_data(),
|
||||
this->config(),
|
||||
@ -1592,15 +1608,18 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
print.m_print_statistics,
|
||||
export_to_binary_gcode,
|
||||
m_processor.get_binary_data()
|
||||
));
|
||||
);
|
||||
|
||||
if (!export_to_binary_gcode)
|
||||
file.write(filament_stats_string_out);
|
||||
|
||||
if (export_to_binary_gcode) {
|
||||
BinaryGCode::BinaryData& binary_data = m_processor.get_binary_data();
|
||||
char buf[128];
|
||||
sprintf(buf, "%.2lf", print.m_print_statistics.total_weight);
|
||||
binary_data.print_metadata.raw_data.push_back({ "total filament used [g]", std::string(buf) });
|
||||
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::TotalFilamentUsedG, std::string(buf) });
|
||||
sprintf(buf, "%.2lf", print.m_print_statistics.total_cost);
|
||||
binary_data.print_metadata.raw_data.push_back({ "total filament cost", std::string(buf) });
|
||||
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::TotalFilamentCost, std::string(buf) });
|
||||
if (print.m_print_statistics.total_toolchanges > 0)
|
||||
binary_data.print_metadata.raw_data.push_back({ "total toolchanges", std::to_string(print.m_print_statistics.total_toolchanges) });
|
||||
}
|
||||
@ -1619,8 +1638,13 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
// if exporting gcode in ascii format, statistics export is done here
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
file.write("\n");
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
file.write_format(PrintStatistics::TotalFilamentUsedGValueMask.c_str(), print.m_print_statistics.total_weight);
|
||||
file.write_format(PrintStatistics::TotalFilamentCostValueMask.c_str(), print.m_print_statistics.total_cost);
|
||||
#else
|
||||
file.write_format("; total filament used [g] = %.2lf\n", print.m_print_statistics.total_weight);
|
||||
file.write_format("; total filament cost = %.2lf\n", print.m_print_statistics.total_cost);
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
if (print.m_print_statistics.total_toolchanges > 0)
|
||||
file.write_format("; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges);
|
||||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str());
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace BinaryGCode {
|
||||
|
||||
static size_t g_checksum_max_cache_size = 65536;
|
||||
static const size_t MAX_GCODE_CACHE_SIZE = 65536;
|
||||
|
||||
std::string translate_result(BinaryGCode::EResult result)
|
||||
{
|
||||
@ -26,10 +27,13 @@ std::string translate_result(BinaryGCode::EResult result)
|
||||
case BinaryGCode::EResult::InvalidBlockType: { return "Invalid block type"; }
|
||||
case BinaryGCode::EResult::InvalidCompressionType: { return "Invalid compression type"; }
|
||||
case BinaryGCode::EResult::InvalidMetadataEncodingType: { return "Invalid metadata encoding type"; }
|
||||
case BinaryGCode::EResult::InvalidGCodeEncodingType: { return "Invalid gcode encoding type"; }
|
||||
case BinaryGCode::EResult::DataCompressionError: { return "Data compression error"; }
|
||||
case BinaryGCode::EResult::DataUncompressionError: { return "Data uncompression error"; }
|
||||
case BinaryGCode::EResult::MetadataEncodingError: { return "Data encoding error"; }
|
||||
case BinaryGCode::EResult::MetadataDecodingError: { return "Data decoding error"; }
|
||||
case BinaryGCode::EResult::GCodeEncodingError: { return "GCode encoding error"; }
|
||||
case BinaryGCode::EResult::GCodeDecodingError: { return "GCode decoding error"; }
|
||||
case BinaryGCode::EResult::BlockNotFound: { return "Block not found"; }
|
||||
case BinaryGCode::EResult::InvalidChecksum: { return "Invalid checksum"; }
|
||||
case BinaryGCode::EResult::InvalidThumbnailFormat: { return "Invalid thumbnail format"; }
|
||||
@ -48,6 +52,7 @@ static uint16_t block_types_count() { return 1 + (uint16_t)EBlockTyp
|
||||
static uint16_t compression_types_count() { return 1 + (uint16_t)ECompressionType::None; }
|
||||
static uint16_t thumbnail_formats_count() { return 1 + (uint16_t)EThumbnailFormat::QOI; }
|
||||
static uint16_t metadata_encoding_types_count() { return 1 + (uint16_t)EMetadataEncodingType::INI; }
|
||||
static uint16_t gcode_encoding_types_count() { return 1 + (uint16_t)EGCodeEncodingType::MeatPack; }
|
||||
|
||||
static bool write_to_file(FILE& file, const void* data, size_t data_size)
|
||||
{
|
||||
@ -61,43 +66,60 @@ static bool read_from_file(FILE& file, void* data, size_t data_size)
|
||||
return !ferror(&file);
|
||||
}
|
||||
|
||||
static bool encode_metadata(const std::vector<std::pair<std::string, std::string>>& data_in, std::vector<uint8_t>& data_out,
|
||||
static bool encode_metadata(const std::vector<std::pair<std::string, std::string>>& src, std::vector<uint8_t>& dst,
|
||||
EMetadataEncodingType encoding_type)
|
||||
{
|
||||
for (const auto& [key, value] : data_in) {
|
||||
for (const auto& [key, value] : src) {
|
||||
switch (encoding_type)
|
||||
{
|
||||
case EMetadataEncodingType::INI:
|
||||
{
|
||||
data_out.insert(data_out.end(), key.begin(), key.end());
|
||||
data_out.emplace_back('=');
|
||||
data_out.insert(data_out.end(), value.begin(), value.end());
|
||||
data_out.emplace_back('\n');
|
||||
dst.insert(dst.end(), key.begin(), key.end());
|
||||
dst.emplace_back('=');
|
||||
dst.insert(dst.end(), value.begin(), value.end());
|
||||
dst.emplace_back('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decode_metadata(const std::vector<uint8_t>& data_in, std::vector<std::pair<std::string, std::string>>& data_out,
|
||||
static bool encode_gcode(const std::string& src, std::vector<uint8_t>& dst, EGCodeEncodingType encoding_type)
|
||||
{
|
||||
switch (encoding_type)
|
||||
{
|
||||
case EGCodeEncodingType::None:
|
||||
{
|
||||
dst.insert(dst.end(), src.begin(), src.end());
|
||||
break;
|
||||
}
|
||||
case EGCodeEncodingType::MeatPack:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decode_metadata(const std::vector<uint8_t>& src, std::vector<std::pair<std::string, std::string>>& dst,
|
||||
EMetadataEncodingType encoding_type)
|
||||
{
|
||||
switch (encoding_type)
|
||||
{
|
||||
case EMetadataEncodingType::INI:
|
||||
{
|
||||
auto start_it = data_in.begin();
|
||||
auto end_it = data_in.begin();
|
||||
while (end_it != data_in.end()) {
|
||||
while (end_it != data_in.end() && *end_it != '\n') {
|
||||
auto start_it = src.begin();
|
||||
auto end_it = src.begin();
|
||||
while (end_it != src.end()) {
|
||||
while (end_it != src.end() && *end_it != '\n') {
|
||||
++end_it;
|
||||
}
|
||||
const std::string item(start_it, end_it);
|
||||
const size_t pos = item.find_first_of('=');
|
||||
if (pos != std::string::npos) {
|
||||
data_out.emplace_back(std::make_pair(item.substr(0, pos), item.substr(pos + 1)));
|
||||
dst.emplace_back(std::make_pair(item.substr(0, pos), item.substr(pos + 1)));
|
||||
start_it = ++end_it;
|
||||
}
|
||||
}
|
||||
@ -108,12 +130,30 @@ static bool decode_metadata(const std::vector<uint8_t>& data_in, std::vector<std
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool compress(const std::vector<uint8_t>& data_in, std::vector<uint8_t>& data_out, ECompressionType compression_type)
|
||||
static bool decode_gcode(const std::vector<uint8_t>& src, std::string& dst, EGCodeEncodingType encoding_type)
|
||||
{
|
||||
switch (encoding_type)
|
||||
{
|
||||
case EGCodeEncodingType::None:
|
||||
{
|
||||
dst.insert(dst.end(), src.begin(), src.end());
|
||||
break;
|
||||
}
|
||||
case EGCodeEncodingType::MeatPack:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool compress(const std::vector<uint8_t>& src, std::vector<uint8_t>& data_out, ECompressionType compression_type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool uncompress(const std::vector<uint8_t>& data_in, std::vector<uint8_t>& data_out, ECompressionType compression_type)
|
||||
static bool uncompress(const std::vector<uint8_t>& src, std::vector<uint8_t>& data_out, ECompressionType compression_type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -357,7 +397,6 @@ EResult BaseMetadataBlock::read_data(FILE& file, const BlockHeader& block_header
|
||||
if (!read_from_file(file, (void*)&encoding_type, sizeof(encoding_type)))
|
||||
return EResult::ReadError;
|
||||
if (encoding_type > metadata_encoding_types_count())
|
||||
// Found invalid metadata encoding type
|
||||
return EResult::InvalidMetadataEncodingType;
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
@ -620,11 +659,99 @@ EResult SlicerMetadataBlock::read_data(FILE& file, const FileHeader& file_header
|
||||
|
||||
EResult GCodeBlock::write(FILE& file, ECompressionType compression_type, EChecksumType checksum_type) const
|
||||
{
|
||||
if (encoding_type > gcode_encoding_types_count())
|
||||
return EResult::InvalidGCodeEncodingType;
|
||||
|
||||
BlockHeader block_header = { (uint16_t)EBlockType::GCode, (uint16_t)compression_type, (uint32_t)0 };
|
||||
std::vector<uint8_t> out_data;
|
||||
if (!raw_data.empty()) {
|
||||
// process payload encoding
|
||||
std::vector<uint8_t> uncompressed_data;
|
||||
if (!encode_gcode(raw_data, uncompressed_data, (EGCodeEncodingType)encoding_type))
|
||||
return EResult::GCodeEncodingError;
|
||||
// process payload compression
|
||||
block_header.uncompressed_size = (uint32_t)uncompressed_data.size();
|
||||
std::vector<uint8_t> compressed_data;
|
||||
if (compression_type != ECompressionType::None) {
|
||||
if (!compress(uncompressed_data, compressed_data, compression_type))
|
||||
return EResult::DataCompressionError;
|
||||
block_header.compressed_size = (uint32_t)compressed_data.size();
|
||||
}
|
||||
out_data.swap((compression_type == ECompressionType::None) ? uncompressed_data : compressed_data);
|
||||
}
|
||||
|
||||
// write block header
|
||||
EResult res = block_header.write(file);
|
||||
if (res != EResult::Success)
|
||||
// propagate error
|
||||
return res;
|
||||
|
||||
// write block payload
|
||||
if (!write_to_file(file, (const void*)&encoding_type, sizeof(encoding_type)))
|
||||
return EResult::WriteError;
|
||||
if (!out_data.empty()) {
|
||||
#if ENABLE_BINARIZED_GCODE_DEBUG
|
||||
const std::string out = "GCodeBlock data size:" + std::to_string(out_data.size()) + "\n";
|
||||
OutputDebugStringA(out.c_str());
|
||||
#endif // ENABLE_BINARIZED_GCODE_DEBUG
|
||||
if (!write_to_file(file, (const void*)out_data.data(), out_data.size()))
|
||||
return EResult::WriteError;
|
||||
}
|
||||
|
||||
// write checksum
|
||||
if (checksum_type != EChecksumType::None) {
|
||||
Checksum cs(checksum_type);
|
||||
// update checksum with block header
|
||||
block_header.update_checksum(cs);
|
||||
// update checksum with block payload
|
||||
cs.append(encode((const void*)&encoding_type, sizeof(encoding_type)));
|
||||
if (!out_data.empty())
|
||||
cs.append(out_data);
|
||||
res = cs.write(file);
|
||||
if (res != EResult::Success)
|
||||
// propagate error
|
||||
return res;
|
||||
}
|
||||
|
||||
return EResult::Success;
|
||||
}
|
||||
|
||||
EResult GCodeBlock::read_data(FILE& file, const FileHeader& file_header, const BlockHeader& block_header)
|
||||
{
|
||||
const ECompressionType compression_type = (ECompressionType)block_header.compression;
|
||||
|
||||
if (!read_from_file(file, (void*)&encoding_type, sizeof(encoding_type)))
|
||||
return EResult::ReadError;
|
||||
if (encoding_type > gcode_encoding_types_count())
|
||||
return EResult::InvalidGCodeEncodingType;
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
const size_t data_size = (compression_type == ECompressionType::None) ? block_header.uncompressed_size : block_header.compressed_size;
|
||||
if (data_size > 0) {
|
||||
data.resize(data_size);
|
||||
if (!read_from_file(file, (void*)data.data(), data_size))
|
||||
return EResult::ReadError;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> uncompressed_data;
|
||||
if (compression_type != ECompressionType::None) {
|
||||
if (!uncompress(data, uncompressed_data, compression_type))
|
||||
return EResult::DataUncompressionError;
|
||||
}
|
||||
|
||||
if (!decode_gcode((compression_type == ECompressionType::None) ? data : uncompressed_data, raw_data, (EGCodeEncodingType)encoding_type))
|
||||
return EResult::GCodeDecodingError;
|
||||
|
||||
const EChecksumType checksum_type = (EChecksumType)file_header.checksum_type;
|
||||
if (checksum_type != EChecksumType::None) {
|
||||
// read block checksum
|
||||
Checksum cs(checksum_type);
|
||||
const EResult res = cs.read(file);
|
||||
if (res != EResult::Success)
|
||||
// propagate error
|
||||
return res;
|
||||
}
|
||||
|
||||
return EResult::Success;
|
||||
}
|
||||
|
||||
@ -660,60 +787,116 @@ EResult ChecksumBlock::read_data(FILE& file, const BlockHeader& block_header)
|
||||
}
|
||||
#endif // ENABLE_CHECKSUM_BLOCK
|
||||
|
||||
EResult Binarizer::initialize(FILE& file, EChecksumType checksum_type)
|
||||
EResult Binarizer::initialize(FILE& file, EGCodeEncodingType gcode_encoding_type, EChecksumType checksum_type)
|
||||
{
|
||||
if (!m_enabled)
|
||||
return EResult::Success;
|
||||
|
||||
// initialize checksum
|
||||
m_file = &file;
|
||||
|
||||
m_gcode_encoding_type = gcode_encoding_type;
|
||||
m_checksum_type = checksum_type;
|
||||
#if ENABLE_CHECKSUM_BLOCK
|
||||
// initialize checksum
|
||||
m_checksum = ChecksumBlock();
|
||||
#endif // ENABLE_CHECKSUM_BLOCK
|
||||
|
||||
// save header
|
||||
FileHeader file_header;
|
||||
file_header.checksum_type = (uint16_t)m_checksum_type;
|
||||
EResult res = file_header.write(file);
|
||||
EResult res = file_header.write(*m_file);
|
||||
if (res != EResult::Success)
|
||||
return res;
|
||||
|
||||
// save file metadata block
|
||||
res = m_binary_data.file_metadata.write(file, ECompressionType::None, m_checksum_type);
|
||||
res = m_binary_data.file_metadata.write(*m_file, m_compression_type, m_checksum_type);
|
||||
if (res != EResult::Success)
|
||||
return res;
|
||||
|
||||
// save printer metadata block
|
||||
res = m_binary_data.printer_metadata.write(file, ECompressionType::None, m_checksum_type);
|
||||
res = m_binary_data.printer_metadata.write(*m_file, m_compression_type, m_checksum_type);
|
||||
if (res != EResult::Success)
|
||||
return res;
|
||||
|
||||
// save thumbnail blocks
|
||||
for (const ThumbnailBlock& block : m_binary_data.thumbnails) {
|
||||
res = block.write(file, m_checksum_type);
|
||||
res = block.write(*m_file, m_checksum_type);
|
||||
if (res != EResult::Success)
|
||||
return res;
|
||||
}
|
||||
|
||||
// save slicer metadata block
|
||||
res = m_binary_data.slicer_metadata.write(file, ECompressionType::None, m_checksum_type);
|
||||
// save print metadata block
|
||||
res = m_binary_data.print_metadata.write(*m_file, m_compression_type, m_checksum_type);
|
||||
if (res != EResult::Success)
|
||||
return res;
|
||||
|
||||
// save gcode block
|
||||
// save slicer metadata block
|
||||
res = m_binary_data.slicer_metadata.write(*m_file, m_compression_type, m_checksum_type);
|
||||
if (res != EResult::Success)
|
||||
return res;
|
||||
|
||||
return EResult::Success;
|
||||
}
|
||||
|
||||
EResult Binarizer::finalize(FILE& file)
|
||||
static EResult write_gcode_block(FILE& file, const std::string& raw_data, EGCodeEncodingType encoding_type, ECompressionType compression_type,
|
||||
EChecksumType checksum_type)
|
||||
{
|
||||
GCodeBlock block;
|
||||
block.encoding_type = (uint16_t)encoding_type;
|
||||
block.raw_data = raw_data;
|
||||
return block.write(file, compression_type, checksum_type);
|
||||
}
|
||||
|
||||
EResult Binarizer::append_gcode(const std::string& gcode)
|
||||
{
|
||||
if (gcode.empty())
|
||||
return EResult::Success;
|
||||
|
||||
assert(m_file != nullptr);
|
||||
if (m_file == nullptr)
|
||||
return EResult::WriteError;
|
||||
|
||||
auto it_begin = gcode.begin();
|
||||
do {
|
||||
const size_t begin_pos = std::distance(gcode.begin(), it_begin);
|
||||
const size_t end_line_pos = gcode.find_first_of('\n', begin_pos);
|
||||
if (end_line_pos == std::string::npos)
|
||||
return EResult::WriteError;
|
||||
|
||||
const size_t line_size = 1 + end_line_pos - begin_pos;
|
||||
if (line_size + m_gcode_cache.length() > MAX_GCODE_CACHE_SIZE) {
|
||||
if (!m_gcode_cache.empty()) {
|
||||
const EResult res = write_gcode_block(*m_file, m_gcode_cache, m_gcode_encoding_type, m_compression_type, m_checksum_type);
|
||||
if (res != EResult::Success)
|
||||
// propagate error
|
||||
return res;
|
||||
m_gcode_cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (line_size > MAX_GCODE_CACHE_SIZE)
|
||||
return EResult::WriteError;
|
||||
|
||||
m_gcode_cache.insert(m_gcode_cache.end(), it_begin, it_begin + line_size);
|
||||
it_begin += line_size;
|
||||
}
|
||||
while (it_begin != gcode.end());
|
||||
|
||||
return EResult::Success;
|
||||
}
|
||||
|
||||
EResult Binarizer::finalize()
|
||||
{
|
||||
if (!m_enabled)
|
||||
return EResult::Success;
|
||||
|
||||
// save print metadata block
|
||||
EResult res = m_binary_data.print_metadata.write(file, ECompressionType::None, m_checksum_type);
|
||||
if (res != EResult::Success)
|
||||
return res;
|
||||
// save gcode cache, if not empty
|
||||
if (!m_gcode_cache.empty()) {
|
||||
const EResult res = write_gcode_block(*m_file, m_gcode_cache, m_gcode_encoding_type, m_compression_type, m_checksum_type);
|
||||
if (res != EResult::Success)
|
||||
// propagate error
|
||||
return res;
|
||||
}
|
||||
|
||||
#if ENABLE_CHECKSUM_BLOCK
|
||||
if (m_checksum_type != EChecksumType::None) {
|
||||
|
@ -29,10 +29,13 @@ enum class EResult : uint16_t
|
||||
InvalidBlockType,
|
||||
InvalidCompressionType,
|
||||
InvalidMetadataEncodingType,
|
||||
InvalidGCodeEncodingType,
|
||||
DataCompressionError,
|
||||
DataUncompressionError,
|
||||
MetadataEncodingError,
|
||||
MetadataDecodingError,
|
||||
GCodeEncodingError,
|
||||
GCodeDecodingError,
|
||||
BlockNotFound,
|
||||
InvalidChecksum,
|
||||
InvalidThumbnailFormat,
|
||||
@ -195,12 +198,23 @@ struct SlicerMetadataBlock : public BaseMetadataBlock
|
||||
EResult read_data(FILE& file, const FileHeader& file_header, const BlockHeader& block_header);
|
||||
};
|
||||
|
||||
struct GCodeBlock : public BaseMetadataBlock
|
||||
enum class EGCodeEncodingType : uint16_t
|
||||
{
|
||||
None,
|
||||
MeatPack,
|
||||
};
|
||||
|
||||
struct GCodeBlock
|
||||
{
|
||||
uint16_t encoding_type{ 0 };
|
||||
std::string raw_data;
|
||||
|
||||
// write block header and data
|
||||
EResult write(FILE& file, ECompressionType compression_type, EChecksumType checksum_type) const;
|
||||
// read block data
|
||||
EResult read_data(FILE& file, const FileHeader& file_header, const BlockHeader& block_header);
|
||||
|
||||
static size_t get_parameters_size() { return sizeof(encoding_type); }
|
||||
};
|
||||
|
||||
#if ENABLE_CHECKSUM_BLOCK
|
||||
@ -248,16 +262,20 @@ public:
|
||||
BinaryData& get_binary_data() { return m_binary_data; }
|
||||
const BinaryData& get_binary_data() const { return m_binary_data; }
|
||||
|
||||
EResult initialize(FILE& file, EChecksumType checksum_type);
|
||||
EResult finalize(FILE& file);
|
||||
EResult initialize(FILE& file, EGCodeEncodingType gcode_encoding_type, EChecksumType checksum_type);
|
||||
EResult append_gcode(const std::string& gcode);
|
||||
EResult finalize();
|
||||
|
||||
private:
|
||||
bool m_enabled{ false };
|
||||
|
||||
EChecksumType m_checksum_type{ EChecksumType::None };
|
||||
ECompressionType m_compression_type{ ECompressionType::None };
|
||||
EGCodeEncodingType m_gcode_encoding_type{ EGCodeEncodingType::None };
|
||||
|
||||
FILE* m_file{ nullptr };
|
||||
BinaryData m_binary_data;
|
||||
std::string m_gcode_cache;
|
||||
#if ENABLE_CHECKSUM_BLOCK
|
||||
ChecksumBlock m_checksum;
|
||||
#endif // ENABLE_CHECKSUM_BLOCK
|
||||
|
@ -1127,10 +1127,18 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
FILE* m_file{ nullptr };
|
||||
};
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
m_start_time = std::chrono::high_resolution_clock::now();
|
||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
||||
FILE* file = boost::nowide::fopen(filename.c_str(), "rb");
|
||||
if (file == nullptr)
|
||||
throw Slic3r::RuntimeError("Unable to open file: " + filename + "\n");
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
const long file_size = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
ScopedFile scoped_file(file);
|
||||
|
||||
BinaryGCode::set_checksum_max_cache_size(1024);
|
||||
@ -1141,7 +1149,6 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError("File: " + filename + "does not contain a valid binary gcode\n Error: " + BinaryGCode::translate_result(res) + "\n");
|
||||
|
||||
const long first_block_header_position = ftell(file);
|
||||
const bool verify_checksum = true;
|
||||
|
||||
// read file metadata block
|
||||
@ -1222,7 +1229,27 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
||||
}
|
||||
|
||||
// read print metadata block
|
||||
if ((BinaryGCode::EBlockType)block_header.type != BinaryGCode::EBlockType::PrintMetadata)
|
||||
throw Slic3r::RuntimeError("Unable to find print metadata block in file: " + filename + "\n");
|
||||
BinaryGCode::PrintMetadataBlock print_metadata_block;
|
||||
res = print_metadata_block.read_data(*file, file_header, block_header);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
||||
#if ENABLE_BINARIZED_GCODE_DEBUG
|
||||
OutputDebugStringA("Print metadata:\n");
|
||||
for (const auto& [key, value] : print_metadata_block.raw_data) {
|
||||
OutputDebugStringA(key.c_str());
|
||||
OutputDebugStringA("->");
|
||||
OutputDebugStringA(value.c_str());
|
||||
OutputDebugStringA("\n");
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE_DEBUG
|
||||
|
||||
// read slicer metadata block
|
||||
res = BinaryGCode::read_next_block_header(*file, file_header, block_header, verify_checksum);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
||||
if ((BinaryGCode::EBlockType)block_header.type != BinaryGCode::EBlockType::SlicerMetadata)
|
||||
throw Slic3r::RuntimeError("Unable to find slicer metadata block in file: " + filename + "\n");
|
||||
BinaryGCode::SlicerMetadataBlock slicer_metadata_block;
|
||||
@ -1250,25 +1277,38 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
config.load_from_ini_string(str, ForwardCompatibilitySubstitutionRule::EnableSilent);
|
||||
apply_config(config);
|
||||
|
||||
// read print metadata block
|
||||
m_result.filename = filename;
|
||||
m_result.id = ++s_result_id;
|
||||
initialize_result_moves();
|
||||
|
||||
// read gcodes block
|
||||
res = BinaryGCode::read_next_block_header(*file, file_header, block_header, verify_checksum);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
||||
if ((BinaryGCode::EBlockType)block_header.type != BinaryGCode::EBlockType::PrintMetadata)
|
||||
throw Slic3r::RuntimeError("Unable to find print metadata block in file: " + filename + "\n");
|
||||
BinaryGCode::PrintMetadataBlock print_metadata_block;
|
||||
res = print_metadata_block.read_data(*file, file_header, block_header);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
||||
#if ENABLE_BINARIZED_GCODE_DEBUG
|
||||
OutputDebugStringA("Print metadata:\n");
|
||||
for (const auto& [key, value] : print_metadata_block.raw_data) {
|
||||
OutputDebugStringA(key.c_str());
|
||||
OutputDebugStringA("->");
|
||||
OutputDebugStringA(value.c_str());
|
||||
OutputDebugStringA("\n");
|
||||
if ((BinaryGCode::EBlockType)block_header.type != BinaryGCode::EBlockType::GCode)
|
||||
throw Slic3r::RuntimeError("Unable to find gcode block in file: " + filename + "\n");
|
||||
while ((BinaryGCode::EBlockType)block_header.type == BinaryGCode::EBlockType::GCode) {
|
||||
BinaryGCode::GCodeBlock block;
|
||||
res = block.read_data(*file, file_header, block_header);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
||||
|
||||
// TODO: Update m_result.lines_ends
|
||||
|
||||
m_parser.parse_buffer(block.raw_data, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) {
|
||||
this->process_gcode_line(line, true);
|
||||
});
|
||||
|
||||
if (ftell(file) == file_size)
|
||||
break;
|
||||
|
||||
res = BinaryGCode::read_next_block_header(*file, file_header, block_header, verify_checksum);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE_DEBUG
|
||||
|
||||
// Don't post-process the G-code to update time stamps.
|
||||
this->finalize(false);
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
|
||||
@ -3622,9 +3662,57 @@ void GCodeProcessor::post_process()
|
||||
}
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
std::vector<double> filament_mm(m_result.extruders_count, 0.0);
|
||||
std::vector<double> filament_cm3(m_result.extruders_count, 0.0);
|
||||
std::vector<double> filament_g(m_result.extruders_count, 0.0);
|
||||
std::vector<double> filament_cost(m_result.extruders_count, 0.0);
|
||||
|
||||
double filament_total_g = 0.0;
|
||||
double filament_total_cost = 0.0;
|
||||
|
||||
for (const auto& [id, volume] : m_result.print_statistics.volumes_per_extruder) {
|
||||
filament_mm[id] = volume / (static_cast<double>(M_PI) * sqr(0.5 * m_result.filament_diameters[id]));
|
||||
filament_cm3[id] = volume * 0.001;
|
||||
filament_g[id] = filament_cm3[id] * double(m_result.filament_densities[id]);
|
||||
filament_cost[id] = filament_g[id] * double(m_result.filament_cost[id]) * 0.001;
|
||||
filament_total_g += filament_g[id];
|
||||
filament_total_cost += filament_cost[id];
|
||||
}
|
||||
|
||||
if (m_binarizer.is_enabled()) {
|
||||
BinaryGCode::set_checksum_max_cache_size(4096);
|
||||
const BinaryGCode::EResult res = m_binarizer.initialize(*out.f, BinaryGCode::EChecksumType::CRC32);
|
||||
// update print metadata
|
||||
auto update_value = [](std::string& value, const std::vector<double>& values) {
|
||||
char buf[1024];
|
||||
value.clear();
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
sprintf(buf, i == values.size() - 1 ? " %.2lf" : " %.2lf,", values[i]);
|
||||
value += buf;
|
||||
}
|
||||
};
|
||||
|
||||
// update binary data
|
||||
BinaryGCode::BinaryData& binary_data = m_binarizer.get_binary_data();
|
||||
for (auto& [key, value] : binary_data.print_metadata.raw_data) {
|
||||
if (key == PrintStatistics::FilamentUsedMm) update_value(value, filament_mm);
|
||||
else if (key == PrintStatistics::FilamentUsedG) update_value(value, filament_g);
|
||||
else if (key == PrintStatistics::TotalFilamentUsedG) update_value(value, { filament_total_g });
|
||||
else if (key == PrintStatistics::FilamentUsedCm3) update_value(value, filament_cm3);
|
||||
else if (key == PrintStatistics::FilamentCost) update_value(value, filament_cost);
|
||||
else if (key == PrintStatistics::TotalFilamentCost) update_value(value, { filament_total_cost });
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
const TimeMachine& machine = m_time_processor.machines[i];
|
||||
PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
|
||||
if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
|
||||
char buf[128];
|
||||
sprintf(buf, "(%s mode)", (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent");
|
||||
binary_data.print_metadata.raw_data.push_back({ "estimated printing time " + std::string(buf), get_time_dhms(machine.time) });
|
||||
binary_data.print_metadata.raw_data.push_back({ "estimated first layer printing time " + std::string(buf), get_time_dhms(machine.layers_time.empty() ? 0.f : machine.layers_time.front()) });
|
||||
}
|
||||
}
|
||||
|
||||
const BinaryGCode::EResult res = m_binarizer.initialize(*out.f, BinaryGCode::EGCodeEncodingType::None, BinaryGCode::EChecksumType::CRC32);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError(std::string("Unable to initialize the gcode binarizer.\n"));
|
||||
}
|
||||
@ -3876,9 +3964,30 @@ void GCodeProcessor::post_process()
|
||||
}
|
||||
}
|
||||
|
||||
write_to_file(out, out_string, result, out_path);
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
if (m_binarizer.is_enabled()) {
|
||||
BinaryGCode::EResult res = m_binarizer.append_gcode(out_string);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError(std::string("Error while sending gcode to the binarizer.\n"));
|
||||
}
|
||||
else
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
write_to_file(out, out_string, result, out_path);
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
update_out_file_pos(out, out_string, result);
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
}
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
void update_out_file_pos(FilePtr& out, const std::string& out_string, GCodeProcessorResult& result) {
|
||||
for (size_t i = 0; i < out_string.size(); ++i) {
|
||||
if (out_string[i] == '\n')
|
||||
result.lines_ends.emplace_back(m_out_file_pos + i + 1);
|
||||
}
|
||||
m_out_file_pos += out_string.size();
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
|
||||
// flush the current content of the cache to file
|
||||
void flush(FilePtr& out, GCodeProcessorResult& result, const std::string& out_path) {
|
||||
// collect lines to flush into a single string
|
||||
@ -3892,7 +4001,18 @@ void GCodeProcessor::post_process()
|
||||
m_statistics.remove_all_lines();
|
||||
#endif // NDEBUG
|
||||
|
||||
write_to_file(out, out_string, result, out_path);
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
if (m_binarizer.is_enabled()) {
|
||||
BinaryGCode::EResult res = m_binarizer.append_gcode(out_string);
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError(std::string("Error while sending gcode to the binarizer.\n"));
|
||||
}
|
||||
else
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
write_to_file(out, out_string, result, out_path);
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
update_out_file_pos(out, out_string, result);
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
}
|
||||
|
||||
void synchronize_moves(GCodeProcessorResult& result) const {
|
||||
@ -3922,12 +4042,13 @@ void GCodeProcessor::post_process()
|
||||
}
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
#else
|
||||
for (size_t i = 0; i < out_string.size(); ++i) {
|
||||
if (out_string[i] == '\n')
|
||||
result.lines_ends.emplace_back(m_out_file_pos + i + 1);
|
||||
}
|
||||
m_out_file_pos += out_string.size();
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -3999,6 +4120,7 @@ void GCodeProcessor::post_process()
|
||||
return processed;
|
||||
};
|
||||
|
||||
#if !ENABLE_BINARIZED_GCODE
|
||||
std::vector<double> filament_mm(m_result.extruders_count, 0.0);
|
||||
std::vector<double> filament_cm3(m_result.extruders_count, 0.0);
|
||||
std::vector<double> filament_g(m_result.extruders_count, 0.0);
|
||||
@ -4015,6 +4137,7 @@ void GCodeProcessor::post_process()
|
||||
filament_total_g += filament_g[id];
|
||||
filament_total_cost += filament_cost[id];
|
||||
}
|
||||
#endif // !ENABLE_BINARIZED_GCODE
|
||||
|
||||
auto process_used_filament = [&](std::string& gcode_line) {
|
||||
// Prefilter for parsing speed.
|
||||
@ -4036,12 +4159,21 @@ void GCodeProcessor::post_process()
|
||||
};
|
||||
|
||||
bool ret = false;
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
ret |= process_tag(gcode_line, PrintStatistics::FilamentUsedMmMask, filament_mm);
|
||||
ret |= process_tag(gcode_line, PrintStatistics::FilamentUsedGMask, filament_g);
|
||||
ret |= process_tag(gcode_line, PrintStatistics::TotalFilamentUsedGMask, { filament_total_g });
|
||||
ret |= process_tag(gcode_line, PrintStatistics::FilamentUsedCm3Mask, filament_cm3);
|
||||
ret |= process_tag(gcode_line, PrintStatistics::FilamentCostMask, filament_cost);
|
||||
ret |= process_tag(gcode_line, PrintStatistics::TotalFilamentCostMask, { filament_total_cost });
|
||||
#else
|
||||
ret |= process_tag(gcode_line, "; filament used [mm] =", filament_mm);
|
||||
ret |= process_tag(gcode_line, "; filament used [g] =", filament_g);
|
||||
ret |= process_tag(gcode_line, "; total filament used [g] =", { filament_total_g });
|
||||
ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_cm3);
|
||||
ret |= process_tag(gcode_line, "; filament cost =", filament_cost);
|
||||
ret |= process_tag(gcode_line, "; total filament cost =", { filament_total_cost });
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
return ret;
|
||||
};
|
||||
|
||||
@ -4251,39 +4383,7 @@ void GCodeProcessor::post_process()
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
if (m_binarizer.is_enabled()) {
|
||||
// update print metadata
|
||||
auto update_value = [](std::string& value, const std::vector<double>& values) {
|
||||
char buf[1024];
|
||||
value.clear();
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
sprintf(buf, i == values.size() - 1 ? " %.2lf" : " %.2lf,", values[i]);
|
||||
value += buf;
|
||||
}
|
||||
};
|
||||
|
||||
// update binary data
|
||||
BinaryGCode::BinaryData& binary_data = m_binarizer.get_binary_data();
|
||||
for (auto& [key, value] : binary_data.print_metadata.raw_data) {
|
||||
if (key == "filament used [mm]") update_value(value, filament_mm);
|
||||
else if (key == "filament used [g]") update_value(value, filament_g);
|
||||
else if (key == "total filament used [g]") update_value(value, { filament_total_g });
|
||||
else if (key == "filament used [cm3]") update_value(value, filament_cm3);
|
||||
else if (key == "filament cost") update_value(value, filament_cost);
|
||||
else if (key == "total filament cost") update_value(value, { filament_total_cost });
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
const TimeMachine& machine = m_time_processor.machines[i];
|
||||
PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
|
||||
if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
|
||||
char buf[128];
|
||||
sprintf(buf, "(%s mode)", (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent");
|
||||
binary_data.print_metadata.raw_data.push_back({ "estimated printing time " + std::string(buf), get_time_dhms(machine.time) });
|
||||
binary_data.print_metadata.raw_data.push_back({ "estimated first layer printing time " + std::string(buf), get_time_dhms(machine.layers_time.empty() ? 0.f : machine.layers_time.front()) });
|
||||
}
|
||||
}
|
||||
|
||||
const BinaryGCode::EResult res = m_binarizer.finalize(*out.f);
|
||||
const BinaryGCode::EResult res = m_binarizer.finalize();
|
||||
if (res != BinaryGCode::EResult::Success)
|
||||
throw Slic3r::RuntimeError(std::string("Error while finalizing the gcode binarizer.\n"));
|
||||
}
|
||||
|
@ -1548,6 +1548,28 @@ std::string Print::output_filename(const std::string &filename_base) const
|
||||
return this->PrintBase::output_filename(m_config.output_filename_format.value, ".gcode", filename_base, &config);
|
||||
}
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
const std::string PrintStatistics::FilamentUsedG = "filament used [g]";
|
||||
const std::string PrintStatistics::FilamentUsedGMask = "; " + PrintStatistics::FilamentUsedG + " =";
|
||||
|
||||
const std::string PrintStatistics::TotalFilamentUsedG = "total " + PrintStatistics::FilamentUsedG;
|
||||
const std::string PrintStatistics::TotalFilamentUsedGMask = "; " + PrintStatistics::TotalFilamentUsedG + " =";
|
||||
const std::string PrintStatistics::TotalFilamentUsedGValueMask = TotalFilamentUsedGMask + " %.2lf\n";
|
||||
|
||||
const std::string PrintStatistics::FilamentUsedCm3 = "filament used [cm3]";
|
||||
const std::string PrintStatistics::FilamentUsedCm3Mask = "; " + PrintStatistics::FilamentUsedCm3 + " =";
|
||||
|
||||
const std::string PrintStatistics::FilamentUsedMm = "filament used [mm]";
|
||||
const std::string PrintStatistics::FilamentUsedMmMask = "; " + PrintStatistics::FilamentUsedMm + " =";
|
||||
|
||||
const std::string PrintStatistics::FilamentCost = "filament cost";
|
||||
const std::string PrintStatistics::FilamentCostMask = "; " + PrintStatistics::FilamentCost + " =";
|
||||
|
||||
const std::string PrintStatistics::TotalFilamentCost = "total " + PrintStatistics::FilamentCost;
|
||||
const std::string PrintStatistics::TotalFilamentCostMask = "; " + PrintStatistics::TotalFilamentCost + " =";
|
||||
const std::string PrintStatistics::TotalFilamentCostValueMask = PrintStatistics::TotalFilamentCostMask + " %.2lf\n";
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
|
||||
DynamicConfig PrintStatistics::config() const
|
||||
{
|
||||
DynamicConfig config;
|
||||
|
@ -528,6 +528,23 @@ struct PrintStatistics
|
||||
filament_stats.clear();
|
||||
printing_extruders.clear();
|
||||
}
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
static const std::string FilamentUsedG;
|
||||
static const std::string FilamentUsedGMask;
|
||||
static const std::string TotalFilamentUsedG;
|
||||
static const std::string TotalFilamentUsedGMask;
|
||||
static const std::string TotalFilamentUsedGValueMask;
|
||||
static const std::string FilamentUsedCm3;
|
||||
static const std::string FilamentUsedCm3Mask;
|
||||
static const std::string FilamentUsedMm;
|
||||
static const std::string FilamentUsedMmMask;
|
||||
static const std::string FilamentCost;
|
||||
static const std::string FilamentCostMask;
|
||||
static const std::string TotalFilamentCost;
|
||||
static const std::string TotalFilamentCostMask;
|
||||
static const std::string TotalFilamentCostValueMask;
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
};
|
||||
|
||||
using PrintObjectPtrs = std::vector<PrintObject*>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user