From 4e0eb12ef6518e0a9e964612da626c86890d5e02 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 11 Jun 2019 14:39:41 +0200 Subject: [PATCH] Import/export of the Layers information to/from 3MF --- src/libslic3r/Format/3mf.cpp | 181 ++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 38b34c462..11202e7b3 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -33,6 +33,7 @@ const std::string RELATIONSHIPS_FILE = "_rels/.rels"; const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config"; const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config"; const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt"; +const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Slic3r_PE_layer_config_ranges.txt"; const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt"; const char* MODEL_TAG = "model"; @@ -331,6 +332,7 @@ namespace Slic3r { typedef std::map IdToMetadataMap; typedef std::map IdToGeometryMap; typedef std::map> IdToLayerHeightsProfileMap; + typedef std::map IdToLayerConfigRangesMap; typedef std::map> IdToSlaSupportPointsMap; // Version of the 3mf file @@ -347,6 +349,7 @@ namespace Slic3r { CurrentConfig m_curr_config; IdToMetadataMap m_objects_metadata; IdToLayerHeightsProfileMap m_layer_heights_profiles; + IdToLayerConfigRangesMap m_layer_config_ranges; IdToSlaSupportPointsMap m_sla_support_points; std::string m_curr_metadata_name; std::string m_curr_characters; @@ -365,6 +368,7 @@ namespace Slic3r { bool _load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config); bool _extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); void _extract_layer_heights_profile_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); + void _extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); void _extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, const std::string& archive_filename); @@ -476,6 +480,7 @@ namespace Slic3r { m_curr_config.volume_id = -1; m_objects_metadata.clear(); m_layer_heights_profiles.clear(); + m_layer_config_ranges.clear(); m_sla_support_points.clear(); m_curr_metadata_name.clear(); m_curr_characters.clear(); @@ -546,9 +551,14 @@ namespace Slic3r { if (boost::algorithm::iequals(name, LAYER_HEIGHTS_PROFILE_FILE)) { - // extract slic3r lazer heights profile file + // extract slic3r layer heights profile file _extract_layer_heights_profile_config_from_archive(archive, stat); } + if (boost::algorithm::iequals(name, LAYER_CONFIG_RANGES_FILE)) + { + // extract slic3r layer config ranges file + _extract_layer_config_ranges_from_archive(archive, stat); + } else if (boost::algorithm::iequals(name, SLA_SUPPORT_POINTS_FILE)) { // extract sla support points file @@ -592,6 +602,11 @@ namespace Slic3r { if (obj_layer_heights_profile != m_layer_heights_profiles.end()) model_object->layer_height_profile = obj_layer_heights_profile->second; + // m_layer_config_ranges are indexed by a 1 based model object index. + IdToLayerConfigRangesMap::iterator obj_layer_config_ranges = m_layer_config_ranges.find(object.second + 1); + if (obj_layer_config_ranges != m_layer_config_ranges.end()) + model_object->layer_config_ranges = obj_layer_config_ranges->second; + // m_sla_support_points are indexed by a 1 based model object index. IdToSlaSupportPointsMap::iterator obj_sla_support_points = m_sla_support_points.find(object.second + 1); if (obj_sla_support_points != m_sla_support_points.end() && !obj_sla_support_points->second.empty()) { @@ -769,6 +784,115 @@ namespace Slic3r { } } + void _3MF_Importer::_extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat) + { + if (stat.m_uncomp_size > 0) + { + std::string buffer((size_t)stat.m_uncomp_size, 0); + mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0); + if (res == 0) { + add_error("Error while reading layer config ranges data to buffer"); + return; + } + + if (buffer.back() == '|') + buffer.pop_back(); + + std::vector objects; + boost::split(objects, buffer, boost::is_any_of("|"), boost::token_compress_off); + + for (std::string& object : objects) + { + // delete all spaces + boost::replace_all(object, " ", ""); + + std::vector object_data; + boost::split(object_data, object, boost::is_any_of("*"), boost::token_compress_off); + /* there should be at least one layer config range in the object + * object_data[0] => object information + * object_data[i>=1] => range information + */ + if (object_data.size() < 2) { + add_error("Error while reading object data"); + continue; + } + + std::vector object_data_id; + boost::split(object_data_id, object_data[0], boost::is_any_of("="), boost::token_compress_off); + if (object_data_id.size() != 2) { + add_error("Error while reading object id"); + continue; + } + + // get object information + int object_id = std::atoi(object_data_id[1].c_str()); + if (object_id == 0) { + add_error("Found invalid object id"); + continue; + } + + IdToLayerConfigRangesMap::iterator object_item = m_layer_config_ranges.find(object_id); + if (object_item != m_layer_config_ranges.end()) { + add_error("Found duplicated layer config range"); + continue; + } + + t_layer_config_ranges config_ranges; + + // get ranges information + for (size_t i = 1; i < object_data.size(); ++i) + { + if (object_data[i].back() == '\n') + object_data[i].pop_back(); + + std::vector range_data; + boost::split(range_data, object_data[i], boost::is_any_of("\n"), boost::token_compress_off); + /* There should be at least two options for layer config range + * range_data[0] => Z range information + * range_data[i>=1] => configuration for the range + */ + if (range_data.size() < 3) { + add_error("Found invalid layer config range"); + continue; + } + + std::vector z_range_str; + boost::split(z_range_str, range_data[0], boost::is_any_of("="), boost::token_compress_off); + if (z_range_str.size() != 2) { + add_error("Error while reading layer config range"); + continue; + } + + std::vector z_values; + boost::split(z_values, z_range_str[1], boost::is_any_of(";"), boost::token_compress_off); + if (z_values.size() != 2) { + add_error("Found invalid layer config range"); + continue; + } + + // get Z range information + t_layer_height_range z_range = { (coordf_t)std::atof(z_values[0].c_str()) , (coordf_t)std::atof(z_values[1].c_str()) }; + DynamicPrintConfig& config = config_ranges[z_range]; + + // get configuration options for the range + for (size_t j = 1; j < range_data.size(); ++j) + { + std::vector key_val; + boost::split(key_val, range_data[j], boost::is_any_of("="), boost::token_compress_off); + if (key_val.size() != 2) { + add_error("Error while reading config value"); + continue; + } + config.set_deserialize(key_val[0], key_val[1]); + } + } + + if (!config_ranges.empty()) + m_layer_config_ranges.insert(IdToLayerConfigRangesMap::value_type(object_id, config_ranges)); + } + } + } + void _3MF_Importer::_extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat) { if (stat.m_uncomp_size > 0) @@ -1622,6 +1746,7 @@ namespace Slic3r { bool _add_mesh_to_object_stream(std::stringstream& stream, ModelObject& object, VolumeToOffsetsMap& volumes_offsets); bool _add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items); bool _add_layer_height_profile_file_to_archive(mz_zip_archive& archive, Model& model); + bool _add_layer_config_ranges_file_to_archive(mz_zip_archive& archive, Model& model); bool _add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model); bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config); bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data); @@ -1682,6 +1807,16 @@ namespace Slic3r { return false; } + // Adds layer config ranges file ("Metadata/Slic3r_PE_layer_config_ranges.txt"). + // All layer height profiles of all ModelObjects are stored here, indexed by 1 based index of the ModelObject in Model. + // The index differes from the index of an object ID of an object instance of a 3MF file! + if (!_add_layer_config_ranges_file_to_archive(archive, model)) + { + close_zip_writer(&archive); + boost::filesystem::remove(filename); + return false; + } + // Adds sla support points file ("Metadata/Slic3r_PE_sla_support_points.txt"). // All sla support points of all ModelObjects are stored here, indexed by 1 based index of the ModelObject in Model. // The index differes from the index of an object ID of an object instance of a 3MF file! @@ -2012,6 +2147,50 @@ namespace Slic3r { return true; } + bool _3MF_Exporter::_add_layer_config_ranges_file_to_archive(mz_zip_archive& archive, Model& model) + { + std::string out = ""; + char buffer[1024]; + + unsigned int object_cnt = 0; + for (const ModelObject* object : model.objects) + { + object_cnt++; + const t_layer_config_ranges& ranges = object->layer_config_ranges; + if (!ranges.empty()) + { + sprintf(buffer, "object_id=%d\n", object_cnt); + out += buffer; + + // Store the layer config ranges. + for (const auto& range : ranges) + { + // store minX and maxZ + sprintf(buffer, "*z_range = %f;%f\n", range.first.first, range.first.second); + out += buffer; + + // store range configuration + const DynamicPrintConfig& config = range.second; + for (const std::string& key : config.keys()) + out += " " + key + " = " + config.serialize(key) + "\n"; + } + + out += "|"; + } + } + + if (!out.empty()) + { + if (!mz_zip_writer_add_mem(&archive, LAYER_CONFIG_RANGES_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) + { + add_error("Unable to add layer heights profile file to archive"); + return false; + } + } + + return true; + } + bool _3MF_Exporter::_add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model) { std::string out = "";