mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Merge remote-tracking branch 'remotes/origin/ys_new_features'
This commit is contained in:
		
						commit
						0c95d4e0d9
					
				
					 26 changed files with 1603 additions and 165 deletions
				
			
		|  | @ -11,6 +11,7 @@ | |||
| #include <boost/algorithm/string/classification.hpp> | ||||
| #include <boost/algorithm/string/split.hpp> | ||||
| #include <boost/algorithm/string/predicate.hpp> | ||||
| #include <boost/algorithm/string/replace.hpp> | ||||
| #include <boost/filesystem/operations.hpp> | ||||
| #include <boost/nowide/fstream.hpp> | ||||
| #include <boost/nowide/cstdio.hpp> | ||||
|  | @ -33,6 +34,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 +333,7 @@ namespace Slic3r { | |||
|         typedef std::map<int, ObjectMetadata> IdToMetadataMap; | ||||
|         typedef std::map<int, Geometry> IdToGeometryMap; | ||||
|         typedef std::map<int, std::vector<coordf_t>> IdToLayerHeightsProfileMap; | ||||
|         typedef std::map<int, t_layer_config_ranges> IdToLayerConfigRangesMap; | ||||
|         typedef std::map<int, std::vector<sla::SupportPoint>> IdToSlaSupportPointsMap; | ||||
| 
 | ||||
|         // Version of the 3mf file
 | ||||
|  | @ -347,6 +350,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 +369,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 +481,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 +552,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 +603,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 +785,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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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) | ||||
|  | @ -1624,6 +1749,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); | ||||
|  | @ -1684,6 +1810,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!
 | ||||
|  | @ -2013,6 +2149,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 = ""; | ||||
|  |  | |||
|  | @ -106,6 +106,9 @@ struct AMFParserContext | |||
|                                         // amf/material/metadata
 | ||||
|         NODE_TYPE_OBJECT,               // amf/object
 | ||||
|                                         // amf/object/metadata
 | ||||
|         NODE_TYPE_LAYER_CONFIG,         // amf/object/layer_config_ranges
 | ||||
|         NODE_TYPE_RANGE,                // amf/object/layer_config_ranges/range
 | ||||
|                                         // amf/object/layer_config_ranges/range/metadata
 | ||||
|         NODE_TYPE_MESH,                 // amf/object/mesh
 | ||||
|         NODE_TYPE_VERTICES,             // amf/object/mesh/vertices
 | ||||
|         NODE_TYPE_VERTEX,               // amf/object/mesh/vertices/vertex
 | ||||
|  | @ -260,7 +263,9 @@ void AMFParserContext::startElement(const char *name, const char **atts) | |||
|                 m_value[0] = get_attribute(atts, "type"); | ||||
|                 node_type_new = NODE_TYPE_METADATA; | ||||
|             } | ||||
|         } else if (strcmp(name, "mesh") == 0) { | ||||
|         } else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT) | ||||
|                 node_type_new = NODE_TYPE_LAYER_CONFIG; | ||||
|         else if (strcmp(name, "mesh") == 0) { | ||||
|             if (m_path[1] == NODE_TYPE_OBJECT) | ||||
|                 node_type_new = NODE_TYPE_MESH; | ||||
|         } else if (strcmp(name, "instance") == 0) { | ||||
|  | @ -317,6 +322,10 @@ void AMFParserContext::startElement(const char *name, const char **atts) | |||
|             else if (strcmp(name, "mirrorz") == 0) | ||||
|                 node_type_new = NODE_TYPE_MIRRORZ; | ||||
|         } | ||||
|         else if (m_path[2] == NODE_TYPE_LAYER_CONFIG && strcmp(name, "range") == 0) { | ||||
|             assert(m_object); | ||||
|             node_type_new = NODE_TYPE_RANGE; | ||||
|         } | ||||
|         break; | ||||
|     case 4: | ||||
|         if (m_path[3] == NODE_TYPE_VERTICES) { | ||||
|  | @ -334,6 +343,10 @@ void AMFParserContext::startElement(const char *name, const char **atts) | |||
|             } else if (strcmp(name, "triangle") == 0) | ||||
|                 node_type_new = NODE_TYPE_TRIANGLE; | ||||
|         } | ||||
|         else if (m_path[3] == NODE_TYPE_RANGE && strcmp(name, "metadata") == 0) { | ||||
|             m_value[0] = get_attribute(atts, "type"); | ||||
|             node_type_new = NODE_TYPE_METADATA; | ||||
|         } | ||||
|         break; | ||||
|     case 5: | ||||
|         if (strcmp(name, "coordinates") == 0) { | ||||
|  | @ -571,8 +584,13 @@ void AMFParserContext::endElement(const char * /* name */) | |||
|                         config = &m_material->config; | ||||
|                     else if (m_path[1] == NODE_TYPE_OBJECT && m_object) | ||||
|                         config = &m_object->config; | ||||
|                 } else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME && m_volume) | ||||
|                 } | ||||
|                 else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME && m_volume) | ||||
|                     config = &m_volume->config; | ||||
|                 else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_RANGE && m_object && !m_object->layer_config_ranges.empty()) { | ||||
|                     auto it  = --m_object->layer_config_ranges.end(); | ||||
|                     config = &it->second; | ||||
|                 } | ||||
|                 if (config) | ||||
|                     config->set_deserialize(opt_key, m_value[1]); | ||||
|             } else if (m_path.size() == 3 && m_path[1] == NODE_TYPE_OBJECT && m_object && strcmp(opt_key, "layer_height_profile") == 0) { | ||||
|  | @ -609,6 +627,16 @@ void AMFParserContext::endElement(const char * /* name */) | |||
|                 } | ||||
|                 m_object->sla_points_status = sla::PointsStatus::UserModified; | ||||
|             } | ||||
|             else if (m_path.size() == 5 && m_path[1] == NODE_TYPE_OBJECT && m_path[3] == NODE_TYPE_RANGE &&  | ||||
|                      m_object && strcmp(opt_key, "layer_height_ranges") == 0) { | ||||
|                 // Parse object's layer_height_ranges, a semicolon separated doubles.
 | ||||
|                 char* p = const_cast<char*>(m_value[1].c_str()); | ||||
|                 char* end = strchr(p, ';'); | ||||
|                 *end = 0; | ||||
| 
 | ||||
|                 const t_layer_height_range range = {double(atof(p)), double(atof(end + 1))}; | ||||
|                 m_object->layer_config_ranges[range]; | ||||
|             } | ||||
|             else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME && m_volume) { | ||||
|                 if (strcmp(opt_key, "modifier") == 0) { | ||||
|                     // Is this volume a modifier volume?
 | ||||
|  | @ -907,6 +935,31 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) | |||
|         } | ||||
|         //FIXME Store the layer height ranges (ModelObject::layer_height_ranges)
 | ||||
| 
 | ||||
| 
 | ||||
|         // #ys_FIXME_experiment : Try to export layer config range
 | ||||
|         const t_layer_config_ranges& config_ranges = object->layer_config_ranges; | ||||
|         if (!config_ranges.empty()) | ||||
|         { | ||||
|             // Store the layer config range as a single semicolon separated list.
 | ||||
|             stream << "    <layer_config_ranges>\n"; | ||||
|             size_t layer_counter = 0; | ||||
|             for (auto range : config_ranges) { | ||||
|                 stream << "      <range id=\"" << layer_counter << "\">\n"; | ||||
| 
 | ||||
|                 stream << "        <metadata type=\"slic3r.layer_height_ranges\">"; | ||||
|                 stream << range.first.first << ";" << range.first.second << "</metadata>\n"; | ||||
| 
 | ||||
|                 for (const std::string& key : range.second.keys()) | ||||
|                     stream << "        <metadata type=\"slic3r." << key << "\">" << range.second.serialize(key) << "</metadata>\n"; | ||||
| 
 | ||||
|                 stream << "      </range>\n"; | ||||
|                 layer_counter++; | ||||
|             } | ||||
| 
 | ||||
|             stream << "    </layer_config_ranges>\n"; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         const std::vector<sla::SupportPoint>& sla_support_points = object->sla_support_points; | ||||
|         if (!sla_support_points.empty()) { | ||||
|             // Store the SLA supports as a single semicolon separated list.
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv