diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 8a898e5779..6a0ed586ca 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1136,7 +1136,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail this->print_machine_envelope(file, print); // Label all objects so printer knows about them since the start. - m_label_objects.init(print); + m_label_objects.init(print.objects(), print.config().gcode_label_objects, print.config().gcode_flavor); file.write(m_label_objects.all_objects_header()); // Update output variables after the extruders were initialized. @@ -1402,6 +1402,9 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail char buf[1024]; sprintf(buf, "%.2lf", m_max_layer_z); binary_data.printer_metadata.raw_data.emplace_back("max_layer_z", buf); + + // Now the objects info. + binary_data.printer_metadata.raw_data.emplace_back("objects_info", m_label_objects.all_objects_header_singleline_json()); } else { // if exporting gcode in ascii format, statistics export is done here @@ -1413,6 +1416,8 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail 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("; objects_info = %s\n", m_label_objects.all_objects_header_singleline_json().c_str()); + // if exporting gcode in ascii format, config export is done here // Append full config, delimited by two 'phony' configuration keys prusaslicer_config = begin and prusaslicer_config = end. // The delimiters are structured as configuration key / value pairs to be parsable by older versions of PrusaSlicer G-code viewer. diff --git a/src/libslic3r/GCode/LabelObjects.cpp b/src/libslic3r/GCode/LabelObjects.cpp index 17a829660f..aae9f09fb9 100644 --- a/src/libslic3r/GCode/LabelObjects.cpp +++ b/src/libslic3r/GCode/LabelObjects.cpp @@ -5,6 +5,8 @@ #include "Print.hpp" #include "TriangleMeshSlicer.hpp" +#include "boost/algorithm/string/replace.hpp" + namespace Slic3r::GCode { @@ -39,10 +41,10 @@ Polygon instance_outline(const PrintInstance* pi) }; // anonymous namespace -void LabelObjects::init(const Print& print) +void LabelObjects::init(const SpanOfConstPtrs& objects, LabelObjectsStyle label_object_style, GCodeFlavor gcode_flavor) { - m_label_objects_style = print.config().gcode_label_objects; - m_flavor = print.config().gcode_flavor; + m_label_objects_style = label_object_style; + m_flavor = gcode_flavor; if (m_label_objects_style == LabelObjectsStyle::Disabled) return; @@ -51,7 +53,7 @@ void LabelObjects::init(const Print& print) // Iterate over all PrintObjects and their PrintInstances, collect PrintInstances which // belong to the same ModelObject. - for (const PrintObject* po : print.objects()) + for (const PrintObject* po : objects) for (const PrintInstance& pi : po->instances()) model_object_to_print_instances[pi.model_instance->get_object()].emplace_back(&pi); @@ -87,7 +89,23 @@ void LabelObjects::init(const Print& print) } } - m_label_data.emplace(pi, LabelData{name, unique_id}); + // Now calculate the polygon and center for Cancel Object (this is not always used). + Polygon outline = instance_outline(pi); + assert(! outline.empty()); + outline.douglas_peucker(50000.f); + Point center = outline.centroid(); + char buffer[64]; + std::snprintf(buffer, sizeof(buffer) - 1, "%.3f,%.3f", unscale(center[0]), unscale(center[1])); + std::string center_str(buffer); + std::string polygon_str = std::string("["); + for (const Point& point : outline) { + std::snprintf(buffer, sizeof(buffer) - 1, "[%.3f,%.3f],", unscale(point[0]), unscale(point[1])); + polygon_str += buffer; + } + polygon_str.pop_back(); + polygon_str += "]"; + + m_label_data.emplace_back(LabelData{pi, name, center_str, polygon_str, unique_id}); ++unique_id; } } @@ -100,40 +118,36 @@ std::string LabelObjects::all_objects_header() const if (m_label_objects_style == LabelObjectsStyle::Disabled) return std::string(); - std::string out; - - // Let's sort the values according to unique_id so they are in the same order in which they were added. - std::vector> label_data_sorted; - for (const auto& pi_and_label : m_label_data) - label_data_sorted.emplace_back(pi_and_label); - std::sort(label_data_sorted.begin(), label_data_sorted.end(), [](const auto& ld1, const auto& ld2) { return ld1.second.unique_id < ld2.second.unique_id; }); + std::string out; out += "\n"; - for (const auto& [print_instance, label] : label_data_sorted) { - if (m_label_objects_style == LabelObjectsStyle::Firmware && m_flavor == gcfKlipper) { - char buffer[64]; - out += "EXCLUDE_OBJECT_DEFINE NAME='" + label.name + "'"; - Polygon outline = instance_outline(print_instance); - assert(! outline.empty()); - outline.douglas_peucker(50000.f); - Point center = outline.centroid(); - std::snprintf(buffer, sizeof(buffer) - 1, " CENTER=%.3f,%.3f", unscale(center[0]), unscale(center[1])); - out += buffer + std::string(" POLYGON=["); - for (const Point& point : outline) { - std::snprintf(buffer, sizeof(buffer) - 1, "[%.3f,%.3f],", unscale(point[0]), unscale(point[1])); - out += buffer; - } - out.pop_back(); - out += "]\n"; - } else { - out += start_object(*print_instance, IncludeName::Yes); - out += stop_object(*print_instance); + for (const LabelData& label : m_label_data) { + if (m_label_objects_style == LabelObjectsStyle::Firmware && m_flavor == gcfKlipper) + out += "EXCLUDE_OBJECT_DEFINE NAME='" + label.name + "' CENTER=" + label.center + " POLYGON=" + label.polygon + "\n"; + else { + out += start_object(*label.pi, IncludeName::Yes); + out += stop_object(*label.pi); } } out += "\n"; return out; } +std::string LabelObjects::all_objects_header_singleline_json() const +{ + std::string out; + out = "{\"objects\":["; + for (size_t i=0; i -#include +#include + +#include "libslic3r/Print.hpp" namespace Slic3r { @@ -21,20 +23,24 @@ public: No, Yes }; - void init(const Print& print); + void init(const SpanOfConstPtrs& objects, LabelObjectsStyle label_object_style, GCodeFlavor gcode_flavor); std::string all_objects_header() const; + std::string all_objects_header_singleline_json() const; std::string start_object(const PrintInstance& print_instance, IncludeName include_name) const; std::string stop_object(const PrintInstance& print_instance) const; private: struct LabelData { + const PrintInstance* pi; std::string name; + std::string center; + std::string polygon; int unique_id; }; LabelObjectsStyle m_label_objects_style; GCodeFlavor m_flavor; - std::unordered_map m_label_data; + std::vector m_label_data; };