mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 21:05:56 +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
@ -1002,10 +1002,17 @@ namespace DoExport {
|
|||||||
print_statistics.initial_extruder_id = initial_extruder_id;
|
print_statistics.initial_extruder_id = initial_extruder_id;
|
||||||
std::vector<std::string> filament_types;
|
std::vector<std::string> filament_types;
|
||||||
if (! extruders.empty()) {
|
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_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_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_used_g ("; filament used [g] = ", 0);
|
||||||
std::pair<std::string, unsigned int> out_filament_cost("; filament cost = ", 0);
|
std::pair<std::string, unsigned int> out_filament_cost("; filament cost = ", 0);
|
||||||
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
for (const Extruder &extruder : extruders) {
|
for (const Extruder &extruder : extruders) {
|
||||||
print_statistics.printing_extruders.emplace_back(extruder.id());
|
print_statistics.printing_extruders.emplace_back(extruder.id());
|
||||||
filament_types.emplace_back(config.filament_type.get_at(extruder.id()));
|
filament_types.emplace_back(config.filament_type.get_at(extruder.id()));
|
||||||
@ -1032,9 +1039,9 @@ namespace DoExport {
|
|||||||
if (export_binary_data) {
|
if (export_binary_data) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
sprintf(buf, "%.2lf", used_filament);
|
sprintf(buf, "%.2lf", used_filament);
|
||||||
binary_data.print_metadata.raw_data.push_back({ "filament used [mm]", std::string(buf) });
|
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::FilamentUsedMm, std::string(buf) });
|
||||||
sprintf(buf, "%.2lf", extruded_volume * 0.001);
|
sprintf(buf, "%.2lf", extruded_volume * 0.001);
|
||||||
binary_data.print_metadata.raw_data.push_back({ "filament used [cm3]", std::string(buf) });
|
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::FilamentUsedCm3, std::string(buf) });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#endif // ENABLE_BINARIZED_GCODE
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
@ -1049,7 +1056,7 @@ namespace DoExport {
|
|||||||
if (export_binary_data) {
|
if (export_binary_data) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
sprintf(buf, "%.2lf", filament_weight);
|
sprintf(buf, "%.2lf", filament_weight);
|
||||||
binary_data.print_metadata.raw_data.push_back({ "filament used [g]", std::string(buf) });
|
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::FilamentUsedG, std::string(buf) });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif // ENABLE_BINARIZED_GCODE
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
@ -1060,7 +1067,7 @@ namespace DoExport {
|
|||||||
if (export_binary_data) {
|
if (export_binary_data) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
sprintf(buf, "%.2lf", filament_cost);
|
sprintf(buf, "%.2lf", filament_cost);
|
||||||
binary_data.print_metadata.raw_data.push_back({ "filament cost", std::string(buf) });
|
binary_data.print_metadata.raw_data.push_back({ PrintStatistics::FilamentCost, std::string(buf) });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif // ENABLE_BINARIZED_GCODE
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
@ -1072,12 +1079,18 @@ namespace DoExport {
|
|||||||
print_statistics.total_wipe_tower_filament += has_wipe_tower ? used_filament - extruder.used_filament() : 0.;
|
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.;
|
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 += out_filament_used_mm.first;
|
||||||
filament_stats_string_out += "\n" + out_filament_used_cm3.first;
|
filament_stats_string_out += "\n" + out_filament_used_cm3.first;
|
||||||
if (out_filament_used_g.second)
|
if (out_filament_used_g.second)
|
||||||
filament_stats_string_out += "\n" + out_filament_used_g.first;
|
filament_stats_string_out += "\n" + out_filament_used_g.first;
|
||||||
if (out_filament_cost.second)
|
if (out_filament_cost.second)
|
||||||
filament_stats_string_out += "\n" + out_filament_cost.first;
|
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);
|
print_statistics.initial_filament_type = config.filament_type.get_at(initial_extruder_id);
|
||||||
std::sort(filament_types.begin(), filament_types.end());
|
std::sort(filament_types.begin(), filament_types.end());
|
||||||
print_statistics.printing_filament_types = filament_types.front();
|
print_statistics.printing_filament_types = filament_types.front();
|
||||||
@ -1216,6 +1229,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
this->m_avoid_crossing_curled_overhangs.init_bed_shape(get_bed_shape(print.config()));
|
this->m_avoid_crossing_curled_overhangs.init_bed_shape(get_bed_shape(print.config()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_BINARIZED_GCODE
|
||||||
|
if (!export_to_binary_gcode)
|
||||||
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
// Write information on the generator.
|
// Write information on the generator.
|
||||||
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
||||||
|
|
||||||
@ -1582,7 +1598,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
|
|
||||||
// Get filament stats.
|
// Get filament stats.
|
||||||
#if ENABLE_BINARIZED_GCODE
|
#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
|
// Const inputs
|
||||||
has_wipe_tower, print.wipe_tower_data(),
|
has_wipe_tower, print.wipe_tower_data(),
|
||||||
this->config(),
|
this->config(),
|
||||||
@ -1592,15 +1608,18 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
print.m_print_statistics,
|
print.m_print_statistics,
|
||||||
export_to_binary_gcode,
|
export_to_binary_gcode,
|
||||||
m_processor.get_binary_data()
|
m_processor.get_binary_data()
|
||||||
));
|
);
|
||||||
|
|
||||||
|
if (!export_to_binary_gcode)
|
||||||
|
file.write(filament_stats_string_out);
|
||||||
|
|
||||||
if (export_to_binary_gcode) {
|
if (export_to_binary_gcode) {
|
||||||
BinaryGCode::BinaryData& binary_data = m_processor.get_binary_data();
|
BinaryGCode::BinaryData& binary_data = m_processor.get_binary_data();
|
||||||
char buf[128];
|
char buf[128];
|
||||||
sprintf(buf, "%.2lf", print.m_print_statistics.total_weight);
|
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);
|
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)
|
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) });
|
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
|
// if exporting gcode in ascii format, statistics export is done here
|
||||||
#endif // ENABLE_BINARIZED_GCODE
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
file.write("\n");
|
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 used [g] = %.2lf\n", print.m_print_statistics.total_weight);
|
||||||
file.write_format("; total filament cost = %.2lf\n", print.m_print_statistics.total_cost);
|
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)
|
if (print.m_print_statistics.total_toolchanges > 0)
|
||||||
file.write_format("; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges);
|
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());
|
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str());
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace BinaryGCode {
|
namespace BinaryGCode {
|
||||||
|
|
||||||
static size_t g_checksum_max_cache_size = 65536;
|
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)
|
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::InvalidBlockType: { return "Invalid block type"; }
|
||||||
case BinaryGCode::EResult::InvalidCompressionType: { return "Invalid compression type"; }
|
case BinaryGCode::EResult::InvalidCompressionType: { return "Invalid compression type"; }
|
||||||
case BinaryGCode::EResult::InvalidMetadataEncodingType: { return "Invalid metadata encoding 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::DataCompressionError: { return "Data compression error"; }
|
||||||
case BinaryGCode::EResult::DataUncompressionError: { return "Data uncompression error"; }
|
case BinaryGCode::EResult::DataUncompressionError: { return "Data uncompression error"; }
|
||||||
case BinaryGCode::EResult::MetadataEncodingError: { return "Data encoding error"; }
|
case BinaryGCode::EResult::MetadataEncodingError: { return "Data encoding error"; }
|
||||||
case BinaryGCode::EResult::MetadataDecodingError: { return "Data decoding 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::BlockNotFound: { return "Block not found"; }
|
||||||
case BinaryGCode::EResult::InvalidChecksum: { return "Invalid checksum"; }
|
case BinaryGCode::EResult::InvalidChecksum: { return "Invalid checksum"; }
|
||||||
case BinaryGCode::EResult::InvalidThumbnailFormat: { return "Invalid thumbnail format"; }
|
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 compression_types_count() { return 1 + (uint16_t)ECompressionType::None; }
|
||||||
static uint16_t thumbnail_formats_count() { return 1 + (uint16_t)EThumbnailFormat::QOI; }
|
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 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)
|
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);
|
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)
|
EMetadataEncodingType encoding_type)
|
||||||
{
|
{
|
||||||
for (const auto& [key, value] : data_in) {
|
for (const auto& [key, value] : src) {
|
||||||
switch (encoding_type)
|
switch (encoding_type)
|
||||||
{
|
{
|
||||||
case EMetadataEncodingType::INI:
|
case EMetadataEncodingType::INI:
|
||||||
{
|
{
|
||||||
data_out.insert(data_out.end(), key.begin(), key.end());
|
dst.insert(dst.end(), key.begin(), key.end());
|
||||||
data_out.emplace_back('=');
|
dst.emplace_back('=');
|
||||||
data_out.insert(data_out.end(), value.begin(), value.end());
|
dst.insert(dst.end(), value.begin(), value.end());
|
||||||
data_out.emplace_back('\n');
|
dst.emplace_back('\n');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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)
|
EMetadataEncodingType encoding_type)
|
||||||
{
|
{
|
||||||
switch (encoding_type)
|
switch (encoding_type)
|
||||||
{
|
{
|
||||||
case EMetadataEncodingType::INI:
|
case EMetadataEncodingType::INI:
|
||||||
{
|
{
|
||||||
auto start_it = data_in.begin();
|
auto start_it = src.begin();
|
||||||
auto end_it = data_in.begin();
|
auto end_it = src.begin();
|
||||||
while (end_it != data_in.end()) {
|
while (end_it != src.end()) {
|
||||||
while (end_it != data_in.end() && *end_it != '\n') {
|
while (end_it != src.end() && *end_it != '\n') {
|
||||||
++end_it;
|
++end_it;
|
||||||
}
|
}
|
||||||
const std::string item(start_it, end_it);
|
const std::string item(start_it, end_it);
|
||||||
const size_t pos = item.find_first_of('=');
|
const size_t pos = item.find_first_of('=');
|
||||||
if (pos != std::string::npos) {
|
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;
|
start_it = ++end_it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,12 +130,30 @@ static bool decode_metadata(const std::vector<uint8_t>& data_in, std::vector<std
|
|||||||
return true;
|
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;
|
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;
|
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)))
|
if (!read_from_file(file, (void*)&encoding_type, sizeof(encoding_type)))
|
||||||
return EResult::ReadError;
|
return EResult::ReadError;
|
||||||
if (encoding_type > metadata_encoding_types_count())
|
if (encoding_type > metadata_encoding_types_count())
|
||||||
// Found invalid metadata encoding type
|
|
||||||
return EResult::InvalidMetadataEncodingType;
|
return EResult::InvalidMetadataEncodingType;
|
||||||
|
|
||||||
std::vector<uint8_t> data;
|
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
|
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;
|
return EResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
EResult GCodeBlock::read_data(FILE& file, const FileHeader& file_header, const BlockHeader& block_header)
|
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;
|
return EResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,60 +787,116 @@ EResult ChecksumBlock::read_data(FILE& file, const BlockHeader& block_header)
|
|||||||
}
|
}
|
||||||
#endif // ENABLE_CHECKSUM_BLOCK
|
#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)
|
if (!m_enabled)
|
||||||
return EResult::Success;
|
return EResult::Success;
|
||||||
|
|
||||||
// initialize checksum
|
m_file = &file;
|
||||||
|
|
||||||
|
m_gcode_encoding_type = gcode_encoding_type;
|
||||||
m_checksum_type = checksum_type;
|
m_checksum_type = checksum_type;
|
||||||
#if ENABLE_CHECKSUM_BLOCK
|
#if ENABLE_CHECKSUM_BLOCK
|
||||||
|
// initialize checksum
|
||||||
m_checksum = ChecksumBlock();
|
m_checksum = ChecksumBlock();
|
||||||
#endif // ENABLE_CHECKSUM_BLOCK
|
#endif // ENABLE_CHECKSUM_BLOCK
|
||||||
|
|
||||||
// save header
|
// save header
|
||||||
FileHeader file_header;
|
FileHeader file_header;
|
||||||
file_header.checksum_type = (uint16_t)m_checksum_type;
|
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)
|
if (res != EResult::Success)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
// save file metadata block
|
// 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)
|
if (res != EResult::Success)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
// save printer metadata block
|
// 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)
|
if (res != EResult::Success)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
// save thumbnail blocks
|
// save thumbnail blocks
|
||||||
for (const ThumbnailBlock& block : m_binary_data.thumbnails) {
|
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)
|
if (res != EResult::Success)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// save slicer metadata block
|
// save print metadata block
|
||||||
res = m_binary_data.slicer_metadata.write(file, ECompressionType::None, m_checksum_type);
|
res = m_binary_data.print_metadata.write(*m_file, m_compression_type, m_checksum_type);
|
||||||
if (res != EResult::Success)
|
if (res != EResult::Success)
|
||||||
return res;
|
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;
|
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)
|
if (!m_enabled)
|
||||||
return EResult::Success;
|
return EResult::Success;
|
||||||
|
|
||||||
// save print metadata block
|
// save gcode cache, if not empty
|
||||||
EResult res = m_binary_data.print_metadata.write(file, ECompressionType::None, m_checksum_type);
|
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)
|
if (res != EResult::Success)
|
||||||
|
// propagate error
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
#if ENABLE_CHECKSUM_BLOCK
|
#if ENABLE_CHECKSUM_BLOCK
|
||||||
if (m_checksum_type != EChecksumType::None) {
|
if (m_checksum_type != EChecksumType::None) {
|
||||||
|
@ -29,10 +29,13 @@ enum class EResult : uint16_t
|
|||||||
InvalidBlockType,
|
InvalidBlockType,
|
||||||
InvalidCompressionType,
|
InvalidCompressionType,
|
||||||
InvalidMetadataEncodingType,
|
InvalidMetadataEncodingType,
|
||||||
|
InvalidGCodeEncodingType,
|
||||||
DataCompressionError,
|
DataCompressionError,
|
||||||
DataUncompressionError,
|
DataUncompressionError,
|
||||||
MetadataEncodingError,
|
MetadataEncodingError,
|
||||||
MetadataDecodingError,
|
MetadataDecodingError,
|
||||||
|
GCodeEncodingError,
|
||||||
|
GCodeDecodingError,
|
||||||
BlockNotFound,
|
BlockNotFound,
|
||||||
InvalidChecksum,
|
InvalidChecksum,
|
||||||
InvalidThumbnailFormat,
|
InvalidThumbnailFormat,
|
||||||
@ -195,12 +198,23 @@ struct SlicerMetadataBlock : public BaseMetadataBlock
|
|||||||
EResult read_data(FILE& file, const FileHeader& file_header, const BlockHeader& block_header);
|
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
|
// write block header and data
|
||||||
EResult write(FILE& file, ECompressionType compression_type, EChecksumType checksum_type) const;
|
EResult write(FILE& file, ECompressionType compression_type, EChecksumType checksum_type) const;
|
||||||
// read block data
|
// read block data
|
||||||
EResult read_data(FILE& file, const FileHeader& file_header, const BlockHeader& block_header);
|
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
|
#if ENABLE_CHECKSUM_BLOCK
|
||||||
@ -248,16 +262,20 @@ public:
|
|||||||
BinaryData& get_binary_data() { return m_binary_data; }
|
BinaryData& get_binary_data() { return m_binary_data; }
|
||||||
const BinaryData& get_binary_data() const { return m_binary_data; }
|
const BinaryData& get_binary_data() const { return m_binary_data; }
|
||||||
|
|
||||||
EResult initialize(FILE& file, EChecksumType checksum_type);
|
EResult initialize(FILE& file, EGCodeEncodingType gcode_encoding_type, EChecksumType checksum_type);
|
||||||
EResult finalize(FILE& file);
|
EResult append_gcode(const std::string& gcode);
|
||||||
|
EResult finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_enabled{ false };
|
bool m_enabled{ false };
|
||||||
|
|
||||||
EChecksumType m_checksum_type{ EChecksumType::None };
|
EChecksumType m_checksum_type{ EChecksumType::None };
|
||||||
ECompressionType m_compression_type{ ECompressionType::None };
|
ECompressionType m_compression_type{ ECompressionType::None };
|
||||||
|
EGCodeEncodingType m_gcode_encoding_type{ EGCodeEncodingType::None };
|
||||||
|
|
||||||
|
FILE* m_file{ nullptr };
|
||||||
BinaryData m_binary_data;
|
BinaryData m_binary_data;
|
||||||
|
std::string m_gcode_cache;
|
||||||
#if ENABLE_CHECKSUM_BLOCK
|
#if ENABLE_CHECKSUM_BLOCK
|
||||||
ChecksumBlock m_checksum;
|
ChecksumBlock m_checksum;
|
||||||
#endif // ENABLE_CHECKSUM_BLOCK
|
#endif // ENABLE_CHECKSUM_BLOCK
|
||||||
|
@ -1127,10 +1127,18 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
|||||||
FILE* m_file{ nullptr };
|
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");
|
FILE* file = boost::nowide::fopen(filename.c_str(), "rb");
|
||||||
if (file == nullptr)
|
if (file == nullptr)
|
||||||
throw Slic3r::RuntimeError("Unable to open file: " + filename + "\n");
|
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);
|
ScopedFile scoped_file(file);
|
||||||
|
|
||||||
BinaryGCode::set_checksum_max_cache_size(1024);
|
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)
|
if (res != BinaryGCode::EResult::Success)
|
||||||
throw Slic3r::RuntimeError("File: " + filename + "does not contain a valid binary gcode\n Error: " + BinaryGCode::translate_result(res) + "\n");
|
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;
|
const bool verify_checksum = true;
|
||||||
|
|
||||||
// read file metadata block
|
// 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");
|
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
|
// 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)
|
if ((BinaryGCode::EBlockType)block_header.type != BinaryGCode::EBlockType::SlicerMetadata)
|
||||||
throw Slic3r::RuntimeError("Unable to find slicer metadata block in file: " + filename + "\n");
|
throw Slic3r::RuntimeError("Unable to find slicer metadata block in file: " + filename + "\n");
|
||||||
BinaryGCode::SlicerMetadataBlock slicer_metadata_block;
|
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);
|
config.load_from_ini_string(str, ForwardCompatibilitySubstitutionRule::EnableSilent);
|
||||||
apply_config(config);
|
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);
|
res = BinaryGCode::read_next_block_header(*file, file_header, block_header, verify_checksum);
|
||||||
if (res != BinaryGCode::EResult::Success)
|
if (res != BinaryGCode::EResult::Success)
|
||||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
||||||
if ((BinaryGCode::EBlockType)block_header.type != BinaryGCode::EBlockType::PrintMetadata)
|
if ((BinaryGCode::EBlockType)block_header.type != BinaryGCode::EBlockType::GCode)
|
||||||
throw Slic3r::RuntimeError("Unable to find print metadata block in file: " + filename + "\n");
|
throw Slic3r::RuntimeError("Unable to find gcode block in file: " + filename + "\n");
|
||||||
BinaryGCode::PrintMetadataBlock print_metadata_block;
|
while ((BinaryGCode::EBlockType)block_header.type == BinaryGCode::EBlockType::GCode) {
|
||||||
res = print_metadata_block.read_data(*file, file_header, block_header);
|
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)
|
if (res != BinaryGCode::EResult::Success)
|
||||||
throw Slic3r::RuntimeError("Error while reading file: " + filename + ": " + BinaryGCode::translate_result(res) + "\n");
|
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
|
|
||||||
|
// Don't post-process the G-code to update time stamps.
|
||||||
|
this->finalize(false);
|
||||||
}
|
}
|
||||||
#endif // ENABLE_BINARIZED_GCODE
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
|
|
||||||
@ -3622,9 +3662,57 @@ void GCodeProcessor::post_process()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_BINARIZED_GCODE
|
#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()) {
|
if (m_binarizer.is_enabled()) {
|
||||||
BinaryGCode::set_checksum_max_cache_size(4096);
|
// update print metadata
|
||||||
const BinaryGCode::EResult res = m_binarizer.initialize(*out.f, BinaryGCode::EChecksumType::CRC32);
|
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)
|
if (res != BinaryGCode::EResult::Success)
|
||||||
throw Slic3r::RuntimeError(std::string("Unable to initialize the gcode binarizer.\n"));
|
throw Slic3r::RuntimeError(std::string("Unable to initialize the gcode binarizer.\n"));
|
||||||
}
|
}
|
||||||
@ -3876,8 +3964,29 @@ 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
|
// flush the current content of the cache to file
|
||||||
void flush(FilePtr& out, GCodeProcessorResult& result, const std::string& out_path) {
|
void flush(FilePtr& out, GCodeProcessorResult& result, const std::string& out_path) {
|
||||||
@ -3892,7 +4001,18 @@ void GCodeProcessor::post_process()
|
|||||||
m_statistics.remove_all_lines();
|
m_statistics.remove_all_lines();
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
#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);
|
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 {
|
void synchronize_moves(GCodeProcessorResult& result) const {
|
||||||
@ -3922,12 +4042,13 @@ void GCodeProcessor::post_process()
|
|||||||
}
|
}
|
||||||
#if ENABLE_BINARIZED_GCODE
|
#if ENABLE_BINARIZED_GCODE
|
||||||
}
|
}
|
||||||
#endif // ENABLE_BINARIZED_GCODE
|
#else
|
||||||
for (size_t i = 0; i < out_string.size(); ++i) {
|
for (size_t i = 0; i < out_string.size(); ++i) {
|
||||||
if (out_string[i] == '\n')
|
if (out_string[i] == '\n')
|
||||||
result.lines_ends.emplace_back(m_out_file_pos + i + 1);
|
result.lines_ends.emplace_back(m_out_file_pos + i + 1);
|
||||||
}
|
}
|
||||||
m_out_file_pos += out_string.size();
|
m_out_file_pos += out_string.size();
|
||||||
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3999,6 +4120,7 @@ void GCodeProcessor::post_process()
|
|||||||
return processed;
|
return processed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if !ENABLE_BINARIZED_GCODE
|
||||||
std::vector<double> filament_mm(m_result.extruders_count, 0.0);
|
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_cm3(m_result.extruders_count, 0.0);
|
||||||
std::vector<double> filament_g(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_g += filament_g[id];
|
||||||
filament_total_cost += filament_cost[id];
|
filament_total_cost += filament_cost[id];
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_BINARIZED_GCODE
|
||||||
|
|
||||||
auto process_used_filament = [&](std::string& gcode_line) {
|
auto process_used_filament = [&](std::string& gcode_line) {
|
||||||
// Prefilter for parsing speed.
|
// Prefilter for parsing speed.
|
||||||
@ -4036,12 +4159,21 @@ void GCodeProcessor::post_process()
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool ret = false;
|
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 [mm] =", filament_mm);
|
||||||
ret |= process_tag(gcode_line, "; filament used [g] =", filament_g);
|
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, "; total filament used [g] =", { filament_total_g });
|
||||||
ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_cm3);
|
ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_cm3);
|
||||||
ret |= process_tag(gcode_line, "; filament cost =", filament_cost);
|
ret |= process_tag(gcode_line, "; filament cost =", filament_cost);
|
||||||
ret |= process_tag(gcode_line, "; total filament cost =", { filament_total_cost });
|
ret |= process_tag(gcode_line, "; total filament cost =", { filament_total_cost });
|
||||||
|
#endif // ENABLE_BINARIZED_GCODE
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4251,39 +4383,7 @@ void GCodeProcessor::post_process()
|
|||||||
|
|
||||||
#if ENABLE_BINARIZED_GCODE
|
#if ENABLE_BINARIZED_GCODE
|
||||||
if (m_binarizer.is_enabled()) {
|
if (m_binarizer.is_enabled()) {
|
||||||
// update print metadata
|
const BinaryGCode::EResult res = m_binarizer.finalize();
|
||||||
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);
|
|
||||||
if (res != BinaryGCode::EResult::Success)
|
if (res != BinaryGCode::EResult::Success)
|
||||||
throw Slic3r::RuntimeError(std::string("Error while finalizing the gcode binarizer.\n"));
|
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);
|
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 PrintStatistics::config() const
|
||||||
{
|
{
|
||||||
DynamicConfig config;
|
DynamicConfig config;
|
||||||
|
@ -528,6 +528,23 @@ struct PrintStatistics
|
|||||||
filament_stats.clear();
|
filament_stats.clear();
|
||||||
printing_extruders.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*>;
|
using PrintObjectPtrs = std::vector<PrintObject*>;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user