OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::_3MF_Importer Class Reference
Inheritance diagram for Slic3r::_3MF_Importer:
Collaboration diagram for Slic3r::_3MF_Importer:

Classes

struct  Component
struct  Geometry
struct  CurrentObject
struct  CurrentConfig
struct  Instance

Public Member Functions

 _3MF_Importer ()
 ~_3MF_Importer ()
bool load_model_from_file (const std::string &filename, Model &model, DynamicPrintConfig &config, ConfigSubstitutionContext &config_substitutions, bool check_version)
unsigned int version () const
void log_errors ()

Protected Member Functions

void add_error (const std::string &error)
void clear_errors ()

Private Types

typedef std::vector< Component > ComponentsList
typedef std::vector< Metadata > MetadataList
typedef std::map< int, int > IdToModelObjectMap
typedef std::map< int, ComponentsList > IdToAliasesMap
typedef std::vector< Instance > InstancesList
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
typedef std::map< int, std::vector< sla::DrainHole > > IdToSlaDrainHolesMap

Private Member Functions

void _destroy_xml_parser ()
void _stop_xml_parser (const std::string &msg=std::string())
bool parse_error () const
const char * parse_error_message () const
bool _load_model_from_file (const std::string &filename, Model &model, DynamicPrintConfig &config, ConfigSubstitutionContext &config_substitutions)
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, ConfigSubstitutionContext &config_substitutions)
void _extract_sla_support_points_from_archive (mz_zip_archive &archive, const mz_zip_archive_file_stat &stat)
void _extract_sla_drain_holes_from_archive (mz_zip_archive &archive, const mz_zip_archive_file_stat &stat)
void _extract_custom_gcode_per_print_z_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, ConfigSubstitutionContext &subs_context, const std::string &archive_filename)
bool _extract_model_config_from_archive (mz_zip_archive &archive, const mz_zip_archive_file_stat &stat, Model &model)
void _handle_start_model_xml_element (const char *name, const char **attributes)
void _handle_end_model_xml_element (const char *name)
void _handle_model_xml_characters (const XML_Char *s, int len)
void _handle_start_config_xml_element (const char *name, const char **attributes)
void _handle_end_config_xml_element (const char *name)
bool _handle_start_model (const char **attributes, unsigned int num_attributes)
bool _handle_end_model ()
bool _handle_start_resources (const char **attributes, unsigned int num_attributes)
bool _handle_end_resources ()
bool _handle_start_object (const char **attributes, unsigned int num_attributes)
bool _handle_end_object ()
bool _handle_start_mesh (const char **attributes, unsigned int num_attributes)
bool _handle_end_mesh ()
bool _handle_start_vertices (const char **attributes, unsigned int num_attributes)
bool _handle_end_vertices ()
bool _handle_start_vertex (const char **attributes, unsigned int num_attributes)
bool _handle_end_vertex ()
bool _handle_start_triangles (const char **attributes, unsigned int num_attributes)
bool _handle_end_triangles ()
bool _handle_start_triangle (const char **attributes, unsigned int num_attributes)
bool _handle_end_triangle ()
bool _handle_start_components (const char **attributes, unsigned int num_attributes)
bool _handle_end_components ()
bool _handle_start_component (const char **attributes, unsigned int num_attributes)
bool _handle_end_component ()
bool _handle_start_build (const char **attributes, unsigned int num_attributes)
bool _handle_end_build ()
bool _handle_start_item (const char **attributes, unsigned int num_attributes)
bool _handle_end_item ()
bool _handle_start_metadata (const char **attributes, unsigned int num_attributes)
bool _handle_end_metadata ()
bool _create_object_instance (int object_id, const Transform3d &transform, const bool printable, unsigned int recur_counter)
void _apply_transform (ModelInstance &instance, const Transform3d &transform)
bool _handle_start_config (const char **attributes, unsigned int num_attributes)
bool _handle_end_config ()
bool _handle_start_config_object (const char **attributes, unsigned int num_attributes)
bool _handle_end_config_object ()
bool _handle_start_config_volume (const char **attributes, unsigned int num_attributes)
bool _handle_start_config_volume_mesh (const char **attributes, unsigned int num_attributes)
bool _handle_end_config_volume ()
bool _handle_end_config_volume_mesh ()
bool _handle_start_config_metadata (const char **attributes, unsigned int num_attributes)
bool _handle_end_config_metadata ()
bool _generate_volumes (ModelObject &object, const Geometry &geometry, const ObjectMetadata::VolumeMetadataList &volumes, ConfigSubstitutionContext &config_substitutions)

Static Private Member Functions

static void XMLCALL _handle_start_model_xml_element (void *userData, const char *name, const char **attributes)
static void XMLCALL _handle_end_model_xml_element (void *userData, const char *name)
static void XMLCALL _handle_model_xml_characters (void *userData, const XML_Char *s, int len)
static void XMLCALL _handle_start_config_xml_element (void *userData, const char *name, const char **attributes)
static void XMLCALL _handle_end_config_xml_element (void *userData, const char *name)

Private Attributes

unsigned int m_version
bool m_check_version
boost::optional< Semver > m_prusaslicer_generator_version
unsigned int m_fdm_supports_painting_version = 0
unsigned int m_seam_painting_version = 0
unsigned int m_mm_painting_version = 0
XML_Parser m_xml_parser
bool m_parse_error { false }
std::string m_parse_error_message
Model * m_model
float m_unit_factor
CurrentObject m_curr_object
IdToModelObjectMap m_objects
IdToAliasesMap m_objects_aliases
InstancesList m_instances
IdToGeometryMap m_geometries
CurrentConfig m_curr_config
IdToMetadataMap m_objects_metadata
IdToLayerHeightsProfileMap m_layer_heights_profiles
IdToLayerConfigRangesMap m_layer_config_ranges
IdToSlaSupportPointsMap m_sla_support_points
IdToSlaDrainHolesMap m_sla_drain_holes
std::string m_curr_metadata_name
std::string m_curr_characters
std::string m_name
std::vector< std::string > m_errors

Detailed Description


Class Documentation

◆ Slic3r::_3MF_Importer::CurrentConfig

struct Slic3r::_3MF_Importer::CurrentConfig
Class Members
int object_id
int volume_id

◆ Slic3r::_3MF_Importer::ObjectMetadata

struct Slic3r::_3MF_Importer::ObjectMetadata
Collaboration diagram for Slic3r::_3MF_Importer::ObjectMetadata:
Class Members
typedef vector< VolumeMetadata > VolumeMetadataList
Class Members
MetadataList metadata
VolumeMetadataList volumes

Member Typedef Documentation

◆ ComponentsList

typedef std::vector<Component> Slic3r::_3MF_Importer::ComponentsList
private

◆ IdToAliasesMap

typedef std::map<int, ComponentsList> Slic3r::_3MF_Importer::IdToAliasesMap
private

◆ IdToGeometryMap

typedef std::map<int, Geometry> Slic3r::_3MF_Importer::IdToGeometryMap
private

◆ IdToLayerConfigRangesMap

◆ IdToLayerHeightsProfileMap

typedef std::map<int, std::vector<coordf_t> > Slic3r::_3MF_Importer::IdToLayerHeightsProfileMap
private

◆ IdToMetadataMap

◆ IdToModelObjectMap

typedef std::map<int, int> Slic3r::_3MF_Importer::IdToModelObjectMap
private

◆ IdToSlaDrainHolesMap

typedef std::map<int, std::vector<sla::DrainHole> > Slic3r::_3MF_Importer::IdToSlaDrainHolesMap
private

◆ IdToSlaSupportPointsMap

typedef std::map<int, std::vector<sla::SupportPoint> > Slic3r::_3MF_Importer::IdToSlaSupportPointsMap
private

◆ InstancesList

typedef std::vector<Instance> Slic3r::_3MF_Importer::InstancesList
private

◆ MetadataList

typedef std::vector<Metadata> Slic3r::_3MF_Importer::MetadataList
private

Constructor & Destructor Documentation

◆ _3MF_Importer()

Slic3r::_3MF_Importer::_3MF_Importer ( )
706 : m_version(0)
707 , m_check_version(false)
708 , m_xml_parser(nullptr)
709 , m_model(nullptr)
710 , m_unit_factor(1.0f)
713 , m_name("")
714 {
715 }
unsigned int m_version
Definition 3mf.cpp:564
Model * m_model
Definition 3mf.cpp:578
float m_unit_factor
Definition 3mf.cpp:579
std::string m_curr_metadata_name
Definition 3mf.cpp:591
std::string m_curr_characters
Definition 3mf.cpp:592
XML_Parser m_xml_parser
Definition 3mf.cpp:573
bool m_check_version
Definition 3mf.cpp:565
std::string m_name
Definition 3mf.cpp:593

References m_check_version, m_curr_characters, m_curr_metadata_name, m_model, m_name, m_unit_factor, m_version, and m_xml_parser.

Referenced by _extract_model_from_archive(), _handle_end_config_xml_element(), _handle_end_model_xml_element(), _handle_model_xml_characters(), _handle_start_config_xml_element(), and _handle_start_model_xml_element().

Here is the caller graph for this function:

◆ ~_3MF_Importer()

Slic3r::_3MF_Importer::~_3MF_Importer ( )
718 {
720 }
void _destroy_xml_parser()
Definition 3mf.cpp:749

References _destroy_xml_parser().

Here is the call graph for this function:

Member Function Documentation

◆ _apply_transform()

void Slic3r::_3MF_Importer::_apply_transform ( ModelInstance & instance,
const Transform3d & transform )
private
1973 {
1974 // Validate the affine matrix directly. Decomposing a valid mirrored transform to
1975 // rotation and scale is not stable across Eigen versions and may yield a zero diagonal.
1976 if (!transform.matrix().allFinite() || !transform.linear().fullPivLu().isInvertible())
1977 return;
1978
1979 instance.set_transformation(Slic3r::Geometry::Transformation(transform));
1980 }
Linef3 transform(const Linef3 &line, const Transform3d &t)
Definition Line.cpp:15

References _apply_transform(), Slic3r::ModelInstance::set_transformation(), and Slic3r::transform().

Referenced by _apply_transform(), and _handle_end_model().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _create_object_instance()

bool Slic3r::_3MF_Importer::_create_object_instance ( int object_id,
const Transform3d & transform,
const bool printable,
unsigned int recur_counter )
private
1927 {
1928 static const unsigned int MAX_RECURSIONS = 10;
1929
1930 // escape from circular aliasing
1931 if (recur_counter > MAX_RECURSIONS) {
1932 add_error("Too many recursions");
1933 return false;
1934 }
1935
1936 IdToAliasesMap::iterator it = m_objects_aliases.find(object_id);
1937 if (it == m_objects_aliases.end()) {
1938 add_error("Found item with invalid object id");
1939 return false;
1940 }
1941
1942 if (it->second.size() == 1 && it->second[0].object_id == object_id) {
1943 // aliasing to itself
1944
1945 IdToModelObjectMap::iterator object_item = m_objects.find(object_id);
1946 if (object_item == m_objects.end() || object_item->second == -1) {
1947 add_error("Found invalid object");
1948 return false;
1949 }
1950 else {
1951 ModelInstance* instance = m_model->objects[object_item->second]->add_instance();
1952 if (instance == nullptr) {
1953 add_error("Unable to add object instance");
1954 return false;
1955 }
1956 instance->printable = printable;
1957
1958 m_instances.emplace_back(instance, transform);
1959 }
1960 }
1961 else {
1962 // recursively process nested components
1963 for (const Component& component : it->second) {
1964 if (!_create_object_instance(component.object_id, transform * component.transform, printable, recur_counter + 1))
1965 return false;
1966 }
1967 }
1968
1969 return true;
1970 }
void add_error(const std::string &error)
Definition 3mf.cpp:423
bool _create_object_instance(int object_id, const Transform3d &transform, const bool printable, unsigned int recur_counter)
Definition 3mf.cpp:1926
IdToAliasesMap m_objects_aliases
Definition 3mf.cpp:582
InstancesList m_instances
Definition 3mf.cpp:583
IdToModelObjectMap m_objects
Definition 3mf.cpp:581
Definition 3mf.cpp:437

References _create_object_instance(), Slic3r::_3MF_Base::add_error(), m_instances, m_model, m_objects, m_objects_aliases, Slic3r::_3MF_Importer::Component::object_id, Slic3r::ModelInstance::printable, Slic3r::_3MF_Importer::Component::transform, and Slic3r::transform().

Referenced by _create_object_instance(), and _handle_start_item().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _destroy_xml_parser()

void Slic3r::_3MF_Importer::_destroy_xml_parser ( )
private
750 {
751 if (m_xml_parser != nullptr) {
752 XML_ParserFree(m_xml_parser);
753 m_xml_parser = nullptr;
754 }
755 }

References m_xml_parser.

Referenced by ~_3MF_Importer(), _extract_model_config_from_archive(), and _extract_model_from_archive().

Here is the caller graph for this function:

◆ _extract_custom_gcode_per_print_z_from_archive()

void Slic3r::_3MF_Importer::_extract_custom_gcode_per_print_z_from_archive ( mz_zip_archive & archive,
const mz_zip_archive_file_stat & stat )
private
1421 {
1422 //if (stat.m_uncomp_size > 0) {
1423 // std::string buffer((size_t)stat.m_uncomp_size, 0);
1424 // mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
1425 // if (res == 0) {
1426 // add_error("Error while reading custom Gcodes per height data to buffer");
1427 // return;
1428 // }
1429
1430 // std::istringstream iss(buffer); // wrap returned xml to istringstream
1431 // pt::ptree main_tree;
1432 // pt::read_xml(iss, main_tree);
1433
1434 // if (main_tree.front().first != "custom_gcodes_per_print_z")
1435 // return;
1436 // pt::ptree code_tree = main_tree.front().second;
1437
1438 // m_model->custom_gcode_per_print_z.gcodes.clear();
1439
1440 // for (const auto& code : code_tree) {
1441 // if (code.first == "mode") {
1442 // pt::ptree tree = code.second;
1443 // std::string mode = tree.get<std::string>("<xmlattr>.value");
1444 // m_model->custom_gcode_per_print_z.mode = mode == CustomGCode::SingleExtruderMode ? CustomGCode::Mode::SingleExtruder :
1445 // mode == CustomGCode::MultiAsSingleMode ? CustomGCode::Mode::MultiAsSingle :
1446 // CustomGCode::Mode::MultiExtruder;
1447 // }
1448 // if (code.first != "code")
1449 // continue;
1450
1451 // pt::ptree tree = code.second;
1452 // double print_z = tree.get<double> ("<xmlattr>.print_z" );
1453 // int extruder = tree.get<int> ("<xmlattr>.extruder");
1454 // std::string color = tree.get<std::string> ("<xmlattr>.color" );
1455
1456 // CustomGCode::Type type;
1457 // std::string extra;
1458 // pt::ptree attr_tree = tree.find("<xmlattr>")->second;
1459 // if (attr_tree.find("type") == attr_tree.not_found()) {
1460 // // It means that data was saved in old version (2.2.0 and older) of PrusaSlicer
1461 // // read old data ...
1462 // std::string gcode = tree.get<std::string> ("<xmlattr>.gcode");
1463 // // ... and interpret them to the new data
1464 // type = gcode == "M600" ? CustomGCode::ColorChange :
1465 // gcode == "M601" ? CustomGCode::PausePrint :
1466 // gcode == "tool_change" ? CustomGCode::ToolChange : CustomGCode::Custom;
1467 // extra = type == CustomGCode::PausePrint ? color :
1468 // type == CustomGCode::Custom ? gcode : "";
1469 // }
1470 // else {
1471 // type = static_cast<CustomGCode::Type>(tree.get<int>("<xmlattr>.type"));
1472 // extra = tree.get<std::string>("<xmlattr>.extra");
1473 // }
1474 // m_model->custom_gcode_per_print_z.gcodes.push_back(CustomGCode::Item{print_z, type, extruder, color, extra}) ;
1475 // }
1476 //}
1477 }

References _extract_custom_gcode_per_print_z_from_archive().

Referenced by _extract_custom_gcode_per_print_z_from_archive().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _extract_layer_config_ranges_from_archive()

void Slic3r::_3MF_Importer::_extract_layer_config_ranges_from_archive ( mz_zip_archive & archive,
const mz_zip_archive_file_stat & stat,
ConfigSubstitutionContext & config_substitutions )
private
1150 {
1151 if (stat.m_uncomp_size > 0) {
1152 std::string buffer((size_t)stat.m_uncomp_size, 0);
1153 mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
1154 if (res == 0) {
1155 add_error("Error while reading layer config ranges data to buffer");
1156 return;
1157 }
1158
1159 std::istringstream iss(buffer); // wrap returned xml to istringstream
1160 pt::ptree objects_tree;
1161 pt::read_xml(iss, objects_tree);
1162
1163 for (const auto& object : objects_tree.get_child("objects")) {
1164 pt::ptree object_tree = object.second;
1165 int obj_idx = object_tree.get<int>("<xmlattr>.id", -1);
1166 if (obj_idx <= 0) {
1167 add_error("Found invalid object id");
1168 continue;
1169 }
1170
1171 IdToLayerConfigRangesMap::iterator object_item = m_layer_config_ranges.find(obj_idx);
1172 if (object_item != m_layer_config_ranges.end()) {
1173 add_error("Found duplicated layer config range");
1174 continue;
1175 }
1176
1177 t_layer_config_ranges config_ranges;
1178
1179 for (const auto& range : object_tree) {
1180 if (range.first != "range")
1181 continue;
1182 pt::ptree range_tree = range.second;
1183 double min_z = range_tree.get<double>("<xmlattr>.min_z");
1184 double max_z = range_tree.get<double>("<xmlattr>.max_z");
1185
1186 // get Z range information
1187 DynamicPrintConfig config;
1188
1189 for (const auto& option : range_tree) {
1190 if (option.first != "option")
1191 continue;
1192 std::string opt_key = option.second.get<std::string>("<xmlattr>.opt_key");
1193 std::string value = option.second.data();
1194 config.set_deserialize(opt_key, value, config_substitutions);
1195 }
1196
1197 config_ranges[{ min_z, max_z }].assign_config(std::move(config));
1198 }
1199
1200 if (!config_ranges.empty())
1201 m_layer_config_ranges.insert({ obj_idx, std::move(config_ranges) });
1202 }
1203 }
1204 }
IdToLayerConfigRangesMap m_layer_config_ranges
Definition 3mf.cpp:588
auto range(Cont &&cont)
Definition libslic3r.h:405
std::map< t_layer_height_range, ModelConfig > t_layer_config_ranges
Definition Slicing.hpp:160

References _extract_layer_config_ranges_from_archive(), Slic3r::_3MF_Base::add_error(), m_layer_config_ranges, and Slic3r::range().

Referenced by _extract_layer_config_ranges_from_archive().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _extract_layer_heights_profile_config_from_archive()

void Slic3r::_3MF_Importer::_extract_layer_heights_profile_config_from_archive ( mz_zip_archive & archive,
const mz_zip_archive_file_stat & stat )
private
1088 {
1089 if (stat.m_uncomp_size > 0) {
1090 std::string buffer((size_t)stat.m_uncomp_size, 0);
1091 mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
1092 if (res == 0) {
1093 add_error("Error while reading layer heights profile data to buffer");
1094 return;
1095 }
1096
1097 if (buffer.back() == '\n')
1098 buffer.pop_back();
1099
1100 std::vector<std::string> objects;
1101 boost::split(objects, buffer, boost::is_any_of("\n"), boost::token_compress_off);
1102
1103 for (const std::string& object : objects) {
1104 std::vector<std::string> object_data;
1105 boost::split(object_data, object, boost::is_any_of("|"), boost::token_compress_off);
1106 if (object_data.size() != 2) {
1107 add_error("Error while reading object data");
1108 continue;
1109 }
1110
1111 std::vector<std::string> object_data_id;
1112 boost::split(object_data_id, object_data[0], boost::is_any_of("="), boost::token_compress_off);
1113 if (object_data_id.size() != 2) {
1114 add_error("Error while reading object id");
1115 continue;
1116 }
1117
1118 int object_id = std::atoi(object_data_id[1].c_str());
1119 if (object_id == 0) {
1120 add_error("Found invalid object id");
1121 continue;
1122 }
1123
1124 IdToLayerHeightsProfileMap::iterator object_item = m_layer_heights_profiles.find(object_id);
1125 if (object_item != m_layer_heights_profiles.end()) {
1126 add_error("Found duplicated layer heights profile");
1127 continue;
1128 }
1129
1130 std::vector<std::string> object_data_profile;
1131 boost::split(object_data_profile, object_data[1], boost::is_any_of(";"), boost::token_compress_off);
1132 if (object_data_profile.size() <= 4 || object_data_profile.size() % 2 != 0) {
1133 add_error("Found invalid layer heights profile");
1134 continue;
1135 }
1136
1137 std::vector<coordf_t> profile;
1138 profile.reserve(object_data_profile.size());
1139
1140 for (const std::string& value : object_data_profile) {
1141 profile.push_back((coordf_t)std::atof(value.c_str()));
1142 }
1143
1144 m_layer_heights_profiles.insert({ object_id, profile });
1145 }
1146 }
1147 }
IdToLayerHeightsProfileMap m_layer_heights_profiles
Definition 3mf.cpp:587
double coordf_t
Definition GUI_ObjectList.hpp:46

References _extract_layer_heights_profile_config_from_archive(), Slic3r::_3MF_Base::add_error(), and m_layer_heights_profiles.

Referenced by _extract_layer_heights_profile_config_from_archive().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _extract_model_config_from_archive()

bool Slic3r::_3MF_Importer::_extract_model_config_from_archive ( mz_zip_archive & archive,
const mz_zip_archive_file_stat & stat,
Model & model )
private
1374 {
1375 if (stat.m_uncomp_size == 0) {
1376 add_error("Found invalid size");
1377 return false;
1378 }
1379
1381
1382 m_xml_parser = XML_ParserCreate(nullptr);
1383 if (m_xml_parser == nullptr) {
1384 add_error("Unable to create parser");
1385 return false;
1386 }
1387
1388 XML_SetUserData(m_xml_parser, (void*)this);
1390
1391 // expat sizes its buffer with an int, so a larger entry cannot be parsed in one piece.
1392 if (stat.m_uncomp_size > static_cast<mz_uint64>(std::numeric_limits<int>::max())) {
1393 add_error("Found invalid size");
1394 return false;
1395 }
1396 const int xml_size = static_cast<int>(stat.m_uncomp_size);
1397
1398 void* parser_buffer = XML_GetBuffer(m_xml_parser, xml_size);
1399 if (parser_buffer == nullptr) {
1400 add_error("Unable to create buffer");
1401 return false;
1402 }
1403
1404 mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, static_cast<size_t>(xml_size), 0);
1405 if (res == 0) {
1406 add_error("Error while reading config data to buffer");
1407 return false;
1408 }
1409
1410 if (!XML_ParseBuffer(m_xml_parser, xml_size, 1)) {
1411 char error_buf[1024];
1412 ::sprintf(error_buf, "Error (%s) while parsing xml file at line %d", XML_ErrorString(XML_GetErrorCode(m_xml_parser)), (int)XML_GetCurrentLineNumber(m_xml_parser));
1413 add_error(error_buf);
1414 return false;
1415 }
1416
1417 return true;
1418 }
void _handle_end_config_xml_element(const char *name)
Definition 3mf.cpp:1584
void _handle_start_config_xml_element(const char *name, const char **attributes)
Definition 3mf.cpp:1561

References _destroy_xml_parser(), _extract_model_config_from_archive(), _handle_end_config_xml_element(), _handle_start_config_xml_element(), Slic3r::_3MF_Base::add_error(), and m_xml_parser.

Referenced by _extract_model_config_from_archive(), and _load_model_from_file().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _extract_model_from_archive()

bool Slic3r::_3MF_Importer::_extract_model_from_archive ( mz_zip_archive & archive,
const mz_zip_archive_file_stat & stat )
private
1001 {
1002 if (stat.m_uncomp_size == 0) {
1003 add_error("Found invalid size");
1004 return false;
1005 }
1006
1008
1009 m_xml_parser = XML_ParserCreate(nullptr);
1010 if (m_xml_parser == nullptr) {
1011 add_error("Unable to create parser");
1012 return false;
1013 }
1014
1015 XML_SetUserData(m_xml_parser, (void*)this);
1017 XML_SetCharacterDataHandler(m_xml_parser, _3MF_Importer::_handle_model_xml_characters);
1018
1019 struct CallbackData
1020 {
1021 XML_Parser& parser;
1022 _3MF_Importer& importer;
1023 const mz_zip_archive_file_stat& stat;
1024
1025 CallbackData(XML_Parser& parser, _3MF_Importer& importer, const mz_zip_archive_file_stat& stat) : parser(parser), importer(importer), stat(stat) {}
1026 };
1027
1028 CallbackData data(m_xml_parser, *this, stat);
1029
1030 mz_bool res = 0;
1031
1032 try
1033 {
1034 res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
1035 CallbackData* data = (CallbackData*)pOpaque;
1036 if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0) || data->importer.parse_error()) {
1037 char error_buf[1024];
1038 ::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", data->importer.parse_error_message(), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
1039 throw Slic3r::FileIOError(error_buf);
1040 }
1041
1042 return n;
1043 }, &data, 0);
1044 }
1045 catch (const version_error& e)
1046 {
1047 // rethrow the exception
1048 throw Slic3r::FileIOError(e.what());
1049 }
1050 catch (std::exception& e)
1051 {
1052 add_error(e.what());
1053 return false;
1054 }
1055
1056 if (res == 0) {
1057 add_error("Error while extracting model data from zip archive");
1058 return false;
1059 }
1060
1061 return true;
1062 }
void _handle_end_model_xml_element(const char *name)
Definition 3mf.cpp:1518
void _handle_start_model_xml_element(const char *name, const char **attributes)
Definition 3mf.cpp:1479
void _handle_model_xml_characters(const XML_Char *s, int len)
Definition 3mf.cpp:1556

References _3MF_Importer(), _destroy_xml_parser(), _handle_end_model_xml_element(), _handle_model_xml_characters(), _handle_start_model_xml_element(), Slic3r::_3MF_Base::add_error(), and m_xml_parser.

Referenced by _load_model_from_file().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _extract_print_config_from_archive()

void Slic3r::_3MF_Importer::_extract_print_config_from_archive ( mz_zip_archive & archive,
const mz_zip_archive_file_stat & stat,
DynamicPrintConfig & config,
ConfigSubstitutionContext & subs_context,
const std::string & archive_filename )
private
1068 {
1069 if (stat.m_uncomp_size > 0) {
1070 std::string buffer((size_t)stat.m_uncomp_size, 0);
1071 mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
1072 if (res == 0) {
1073 add_error("Error while reading config data to buffer");
1074 return;
1075 }
1076 //FIXME Loading a "will be one day a legacy format" of configuration in a form of a G-code comment.
1077 // Each config line is prefixed with a semicolon (G-code comment), that is ugly.
1078
1079 // Replacing the legacy function with load_from_ini_string_commented leads to issues when
1080 // parsing 3MFs from before PrusaSlicer 2.0.0 (which can have duplicated entries in the INI.
1081 // See https://github.com/prusa3d/PrusaSlicer/issues/7155. We'll revert it for now.
1082 //config_substitutions.substitutions = config.load_from_ini_string_commented(std::move(buffer), config_substitutions.rule);
1083 ConfigBase::load_from_gcode_string_legacy(config, buffer.data(), config_substitutions);
1084 }
1085 }
static size_t load_from_gcode_string_legacy(ConfigBase &config, const char *str, ConfigSubstitutionContext &substitutions)
Definition Config.cpp:1264

References _extract_print_config_from_archive(), Slic3r::_3MF_Base::add_error(), and Slic3r::ConfigBase::load_from_gcode_string_legacy().

Referenced by _extract_print_config_from_archive().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _extract_sla_drain_holes_from_archive()

void Slic3r::_3MF_Importer::_extract_sla_drain_holes_from_archive ( mz_zip_archive & archive,
const mz_zip_archive_file_stat & stat )
private
1289 {
1290 if (stat.m_uncomp_size > 0) {
1291 std::string buffer(size_t(stat.m_uncomp_size), 0);
1292 mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
1293 if (res == 0) {
1294 add_error("Error while reading sla support points data to buffer");
1295 return;
1296 }
1297
1298 if (buffer.back() == '\n')
1299 buffer.pop_back();
1300
1301 std::vector<std::string> objects;
1302 boost::split(objects, buffer, boost::is_any_of("\n"), boost::token_compress_off);
1303
1304 // Info on format versioning - see 3mf.hpp
1305 int version = 0;
1306 std::string key("drain_holes_format_version=");
1307 if (!objects.empty() && objects[0].find(key) != std::string::npos) {
1308 objects[0].erase(objects[0].begin(), objects[0].begin() + long(key.size())); // removes the string
1309 version = std::stoi(objects[0]);
1310 objects.erase(objects.begin()); // pop the header
1311 }
1312
1313 for (const std::string& object : objects) {
1314 std::vector<std::string> object_data;
1315 boost::split(object_data, object, boost::is_any_of("|"), boost::token_compress_off);
1316
1317 if (object_data.size() != 2) {
1318 add_error("Error while reading object data");
1319 continue;
1320 }
1321
1322 std::vector<std::string> object_data_id;
1323 boost::split(object_data_id, object_data[0], boost::is_any_of("="), boost::token_compress_off);
1324 if (object_data_id.size() != 2) {
1325 add_error("Error while reading object id");
1326 continue;
1327 }
1328
1329 int object_id = std::atoi(object_data_id[1].c_str());
1330 if (object_id == 0) {
1331 add_error("Found invalid object id");
1332 continue;
1333 }
1334
1335 IdToSlaDrainHolesMap::iterator object_item = m_sla_drain_holes.find(object_id);
1336 if (object_item != m_sla_drain_holes.end()) {
1337 add_error("Found duplicated SLA drain holes");
1338 continue;
1339 }
1340
1341 std::vector<std::string> object_data_points;
1342 boost::split(object_data_points, object_data[1], boost::is_any_of(" "), boost::token_compress_off);
1343
1344 sla::DrainHoles sla_drain_holes;
1345
1346 if (version == 1) {
1347 for (unsigned int i=0; i<object_data_points.size(); i+=8)
1348 sla_drain_holes.emplace_back(Vec3f{float(std::atof(object_data_points[i+0].c_str())),
1349 float(std::atof(object_data_points[i+1].c_str())),
1350 float(std::atof(object_data_points[i+2].c_str()))},
1351 Vec3f{float(std::atof(object_data_points[i+3].c_str())),
1352 float(std::atof(object_data_points[i+4].c_str())),
1353 float(std::atof(object_data_points[i+5].c_str()))},
1354 float(std::atof(object_data_points[i+6].c_str())),
1355 float(std::atof(object_data_points[i+7].c_str())));
1356 }
1357
1358 // The holes are saved elevated above the mesh and deeper (bad idea indeed).
1359 // This is retained for compatibility.
1360 // Place the hole to the mesh and make it shallower to compensate.
1361 // The offset is 1 mm above the mesh.
1362 for (sla::DrainHole& hole : sla_drain_holes) {
1363 hole.pos += hole.normal.normalized();
1364 hole.height -= 1.f;
1365 }
1366
1367 if (!sla_drain_holes.empty())
1368 m_sla_drain_holes.insert({ object_id, sla_drain_holes });
1369 }
1370 }
1371 }
IdToSlaDrainHolesMap m_sla_drain_holes
Definition 3mf.cpp:590
unsigned int version() const
Definition 3mf.cpp:600
T * begin(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:838
std::vector< DrainHole > DrainHoles
Definition Hollowing.hpp:74
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65

References _extract_sla_drain_holes_from_archive(), Slic3r::_3MF_Base::add_error(), m_sla_drain_holes, and version().

Referenced by _extract_sla_drain_holes_from_archive().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _extract_sla_support_points_from_archive()

void Slic3r::_3MF_Importer::_extract_sla_support_points_from_archive ( mz_zip_archive & archive,
const mz_zip_archive_file_stat & stat )
private
1207 {
1208 if (stat.m_uncomp_size > 0) {
1209 std::string buffer((size_t)stat.m_uncomp_size, 0);
1210 mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
1211 if (res == 0) {
1212 add_error("Error while reading sla support points data to buffer");
1213 return;
1214 }
1215
1216 if (buffer.back() == '\n')
1217 buffer.pop_back();
1218
1219 std::vector<std::string> objects;
1220 boost::split(objects, buffer, boost::is_any_of("\n"), boost::token_compress_off);
1221
1222 // Info on format versioning - see 3mf.hpp
1223 int version = 0;
1224 std::string key("support_points_format_version=");
1225 if (!objects.empty() && objects[0].find(key) != std::string::npos) {
1226 objects[0].erase(objects[0].begin(), objects[0].begin() + long(key.size())); // removes the string
1227 version = std::stoi(objects[0]);
1228 objects.erase(objects.begin()); // pop the header
1229 }
1230
1231 for (const std::string& object : objects) {
1232 std::vector<std::string> object_data;
1233 boost::split(object_data, object, boost::is_any_of("|"), boost::token_compress_off);
1234
1235 if (object_data.size() != 2) {
1236 add_error("Error while reading object data");
1237 continue;
1238 }
1239
1240 std::vector<std::string> object_data_id;
1241 boost::split(object_data_id, object_data[0], boost::is_any_of("="), boost::token_compress_off);
1242 if (object_data_id.size() != 2) {
1243 add_error("Error while reading object id");
1244 continue;
1245 }
1246
1247 int object_id = std::atoi(object_data_id[1].c_str());
1248 if (object_id == 0) {
1249 add_error("Found invalid object id");
1250 continue;
1251 }
1252
1253 IdToSlaSupportPointsMap::iterator object_item = m_sla_support_points.find(object_id);
1254 if (object_item != m_sla_support_points.end()) {
1255 add_error("Found duplicated SLA support points");
1256 continue;
1257 }
1258
1259 std::vector<std::string> object_data_points;
1260 boost::split(object_data_points, object_data[1], boost::is_any_of(" "), boost::token_compress_off);
1261
1262 std::vector<sla::SupportPoint> sla_support_points;
1263
1264 if (version == 0) {
1265 for (unsigned int i=0; i<object_data_points.size(); i+=3)
1266 sla_support_points.emplace_back(float(std::atof(object_data_points[i+0].c_str())),
1267 float(std::atof(object_data_points[i+1].c_str())),
1268 float(std::atof(object_data_points[i+2].c_str())),
1269 0.4f,
1270 false);
1271 }
1272 if (version == 1) {
1273 for (unsigned int i=0; i<object_data_points.size(); i+=5)
1274 sla_support_points.emplace_back(float(std::atof(object_data_points[i+0].c_str())),
1275 float(std::atof(object_data_points[i+1].c_str())),
1276 float(std::atof(object_data_points[i+2].c_str())),
1277 float(std::atof(object_data_points[i+3].c_str())),
1278 //FIXME storing boolean as 0 / 1 and importing it as float.
1279 std::abs(std::atof(object_data_points[i+4].c_str()) - 1.) < EPSILON);
1280 }
1281
1282 if (!sla_support_points.empty())
1283 m_sla_support_points.insert({ object_id, sla_support_points });
1284 }
1285 }
1286 }
#define EPSILON
Definition ColorUtils.cpp:64
IdToSlaSupportPointsMap m_sla_support_points
Definition 3mf.cpp:589

References _extract_sla_support_points_from_archive(), Slic3r::_3MF_Base::add_error(), EPSILON, m_sla_support_points, and version().

Referenced by _extract_sla_support_points_from_archive().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _generate_volumes()

bool Slic3r::_3MF_Importer::_generate_volumes ( ModelObject & object,
const Geometry & geometry,
const ObjectMetadata::VolumeMetadataList & volumes,
ConfigSubstitutionContext & config_substitutions )
private
2126 {
2127 if (!object.volumes.empty()) {
2128 add_error("Found invalid volumes count");
2129 return false;
2130 }
2131
2132 unsigned int geo_tri_count = (unsigned int)geometry.triangles.size();
2133 unsigned int renamed_volumes_count = 0;
2134
2135 for (const ObjectMetadata::VolumeMetadata& volume_data : volumes) {
2136 if (geo_tri_count <= volume_data.first_triangle_id || geo_tri_count <= volume_data.last_triangle_id || volume_data.last_triangle_id < volume_data.first_triangle_id) {
2137 add_error("Found invalid triangle id");
2138 return false;
2139 }
2140
2141 Transform3d volume_matrix_to_object = Transform3d::Identity();
2142 bool has_transform = false;
2143 // extract the volume transformation from the volume's metadata, if present
2144 for (const Metadata& metadata : volume_data.metadata) {
2145 if (metadata.key == MATRIX_KEY) {
2146 volume_matrix_to_object = Slic3r::Geometry::transform3d_from_string(metadata.value);
2147 has_transform = ! volume_matrix_to_object.isApprox(Transform3d::Identity(), 1e-10);
2148 break;
2149 }
2150 }
2151
2152 // splits volume out of imported geometry
2153 indexed_triangle_set its;
2154 its.indices.assign(geometry.triangles.begin() + volume_data.first_triangle_id, geometry.triangles.begin() + volume_data.last_triangle_id + 1);
2155 const size_t triangles_count = its.indices.size();
2156 if (triangles_count == 0) {
2157 add_error("An empty triangle mesh found");
2158 return false;
2159 }
2160
2161 {
2162 int min_id = its.indices.front()[0];
2163 int max_id = min_id;
2164 for (const Vec3i32& face : its.indices) {
2165 for (const int tri_id : face) {
2166 if (tri_id < 0 || tri_id >= int(geometry.vertices.size())) {
2167 add_error("Found invalid vertex id");
2168 return false;
2169 }
2170 min_id = std::min(min_id, tri_id);
2171 max_id = std::max(max_id, tri_id);
2172 }
2173 }
2174 its.vertices.assign(geometry.vertices.begin() + min_id, geometry.vertices.begin() + max_id + 1);
2175
2176 // rebase indices to the current vertices list
2177 for (Vec3i32& face : its.indices)
2178 for (int& tri_id : face)
2179 tri_id -= min_id;
2180 }
2181
2183 *m_prusaslicer_generator_version >= *Semver::parse("2.4.0-alpha1") &&
2185 // PrusaSlicer 2.4.0-alpha2 contained a bug, where all vertices of a single object were saved for each volume the object contained.
2186 // Remove the vertices, that are not referenced by any face.
2187 its_compactify_vertices(its, true);
2188
2189 TriangleMesh triangle_mesh(std::move(its), volume_data.mesh_stats);
2190
2191 if (m_version == 0) {
2192 // if the 3mf was not produced by PrusaSlicer and there is only one instance,
2193 // bake the transformation into the geometry to allow the reload from disk command
2194 // to work properly
2195 if (object.instances.size() == 1) {
2196 triangle_mesh.transform(object.instances.front()->get_transformation().get_matrix(), false);
2197 object.instances.front()->set_transformation(Slic3r::Geometry::Transformation());
2198 //FIXME do the mesh fixing?
2199 }
2200 }
2201 if (triangle_mesh.volume() < 0)
2202 triangle_mesh.flip_triangles();
2203
2204 ModelVolume* volume = object.add_volume(std::move(triangle_mesh));
2205 // stores the volume matrix taken from the metadata, if present
2206 if (has_transform)
2207 volume->source.transform = Slic3r::Geometry::Transformation(volume_matrix_to_object);
2208
2209 // recreate custom supports, seam, mm segmentation and fuzzy skin from previously loaded attribute
2210 volume->supported_facets.reserve(triangles_count);
2211 volume->seam_facets.reserve(triangles_count);
2212 volume->mmu_segmentation_facets.reserve(triangles_count);
2213 volume->fuzzy_skin_facets.reserve(triangles_count);
2214 for (size_t i=0; i<triangles_count; ++i) {
2215 size_t index = volume_data.first_triangle_id + i;
2216 assert(index < geometry.custom_supports.size());
2217 assert(index < geometry.custom_seam.size());
2218 assert(index < geometry.mmu_segmentation.size());
2219 if (! geometry.custom_supports[index].empty())
2220 volume->supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]);
2221 if (! geometry.custom_seam[index].empty())
2222 volume->seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]);
2223 if (! geometry.mmu_segmentation[index].empty())
2224 volume->mmu_segmentation_facets.set_triangle_from_string(i, geometry.mmu_segmentation[index]);
2225 if (! geometry.fuzzy_skin[index].empty())
2226 volume->fuzzy_skin_facets.set_triangle_from_string(i, geometry.fuzzy_skin[index]);
2227 }
2228 volume->supported_facets.shrink_to_fit();
2229 volume->seam_facets.shrink_to_fit();
2230 volume->mmu_segmentation_facets.shrink_to_fit();
2231 volume->fuzzy_skin_facets.shrink_to_fit();
2232
2233 // Apply the seam mode after all base-type metadata, regardless of XML key order.
2234 ModelVolumeType precise_seam_type = ModelVolumeType::INVALID;
2235 // apply the remaining volume's metadata
2236 for (const Metadata& metadata : volume_data.metadata) {
2237 if (metadata.key == NAME_KEY)
2238 volume->name = metadata.value;
2239 else if ((metadata.key == MODIFIER_KEY) && (metadata.value == "1"))
2240 volume->set_type(ModelVolumeType::PARAMETER_MODIFIER);
2241 else if (metadata.key == VOLUME_TYPE_KEY)
2242 volume->set_type(type_from_string(metadata.value));
2243 else if (metadata.key == PRECISE_SEAM_TYPE_KEY)
2244 precise_seam_type = ModelVolume::type_from_string(metadata.value);
2245 else if (boost::starts_with(metadata.key, PRECISE_SEAM_CONFIG_PREFIX))
2246 continue; // Restore dormant settings only after the final volume type is known.
2247 else if (metadata.key == SOURCE_FILE_KEY)
2248 volume->source.input_file = metadata.value;
2249 else if (metadata.key == SOURCE_OBJECT_ID_KEY)
2250 volume->source.object_idx = ::atoi(metadata.value.c_str());
2251 else if (metadata.key == SOURCE_VOLUME_ID_KEY)
2252 volume->source.volume_idx = ::atoi(metadata.value.c_str());
2253 else if (metadata.key == SOURCE_OFFSET_X_KEY)
2254 volume->source.mesh_offset(0) = ::atof(metadata.value.c_str());
2255 else if (metadata.key == SOURCE_OFFSET_Y_KEY)
2256 volume->source.mesh_offset(1) = ::atof(metadata.value.c_str());
2257 else if (metadata.key == SOURCE_OFFSET_Z_KEY)
2258 volume->source.mesh_offset(2) = ::atof(metadata.value.c_str());
2259 else if (metadata.key == SOURCE_IN_INCHES)
2260 volume->source.is_converted_from_inches = metadata.value == "1";
2261 else if (metadata.key == SOURCE_IN_METERS)
2262 volume->source.is_converted_from_meters = metadata.value == "1";
2263 else
2264 volume->config.set_deserialize(metadata.key, metadata.value, config_substitutions);
2265 }
2266
2267 // Missing or unknown seam modes retain the ordinary modifier fallback.
2268 // Ignore seam metadata on other base types; legacy inline seam types still load above.
2269 if (volume->is_modifier() && is_precise_seam(precise_seam_type))
2270 volume->set_type(precise_seam_type);
2271
2272 // Unknown seam modes must remain inert modifiers, even when dormant settings are present.
2273 if (volume->is_precise_seam()) {
2274 for (const Metadata& metadata : volume_data.metadata) {
2275 if (boost::starts_with(metadata.key, PRECISE_SEAM_CONFIG_PREFIX)) {
2276 const std::string key = metadata.key.substr(sizeof(PRECISE_SEAM_CONFIG_PREFIX) - 1);
2277 if (!key.empty())
2278 volume->config.set_deserialize(key, metadata.value, config_substitutions);
2279 }
2280 }
2281 }
2282
2283 // this may happen for 3mf saved by 3rd part softwares
2284 if (volume->name.empty()) {
2285 volume->name = object.name;
2286 if (renamed_volumes_count > 0)
2287 volume->name += "_" + std::to_string(renamed_volumes_count + 1);
2288 ++renamed_volumes_count;
2289 }
2290 }
2291
2292 return true;
2293 }
static constexpr const char * SOURCE_VOLUME_ID_KEY
Definition 3mf.cpp:163
static constexpr const char * NAME_KEY
Definition 3mf.cpp:153
static constexpr const char * SOURCE_IN_METERS
Definition 3mf.cpp:168
static constexpr const char * MODIFIER_KEY
Definition 3mf.cpp:154
static constexpr const char * SOURCE_OFFSET_Z_KEY
Definition 3mf.cpp:166
static constexpr const char * SOURCE_OFFSET_X_KEY
Definition 3mf.cpp:164
static constexpr const char * SOURCE_IN_INCHES
Definition 3mf.cpp:167
static constexpr const char * SOURCE_OBJECT_ID_KEY
Definition 3mf.cpp:162
static constexpr char PRECISE_SEAM_CONFIG_PREFIX[]
Definition 3mf.cpp:159
static constexpr const char * SOURCE_OFFSET_Y_KEY
Definition 3mf.cpp:165
static constexpr const char * MATRIX_KEY
Definition 3mf.cpp:160
static constexpr const char * SOURCE_FILE_KEY
Definition 3mf.cpp:161
static constexpr const char * VOLUME_TYPE_KEY
Definition 3mf.cpp:155
static constexpr const char * PRECISE_SEAM_TYPE_KEY
Definition 3mf.cpp:157
static ModelVolumeType type_from_string(const std::string &s)
Definition Model.cpp:2910
static boost::optional< Semver > parse(const std::string &str)
Definition Semver.hpp:63
boost::optional< Semver > m_prusaslicer_generator_version
Definition 3mf.cpp:568
Transform3d transform3d_from_string(const std::string &transform_str)
Definition Geometry.cpp:732
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
ModelVolumeType
Definition Model.hpp:355
@ PARAMETER_MODIFIER
Definition Model.hpp:359
@ INVALID
Definition Model.hpp:356
ModelVolumeType type_from_string(const std::string &s)
Definition 3mf.cpp:396
Eigen::Matrix< int32_t, 3, 1, Eigen::DontAlign > Vec3i32
Definition Point.hpp:59
int its_compactify_vertices(indexed_triangle_set &its, bool shrink_to_fit)
Definition TriangleMesh.cpp:773
bool is_precise_seam(ModelVolumeType t)
Definition Model.hpp:373
Definition 3mf.cpp:517

References _generate_volumes(), Slic3r::_3MF_Base::add_error(), Slic3r::ModelVolume::config, Slic3r::_3MF_Importer::Geometry::custom_seam, Slic3r::_3MF_Importer::Geometry::custom_supports, Slic3r::TriangleMesh::flip_triangles(), Slic3r::_3MF_Importer::Geometry::fuzzy_skin, Slic3r::ModelVolume::fuzzy_skin_facets, Slic3r::ModelVolume::Source::input_file, Slic3r::INVALID, Slic3r::ModelVolume::Source::is_converted_from_inches, Slic3r::ModelVolume::Source::is_converted_from_meters, Slic3r::ModelVolume::is_modifier(), Slic3r::is_precise_seam(), Slic3r::ModelVolume::is_precise_seam(), Slic3r::its_compactify_vertices(), Slic3r::_3MF_Importer::Metadata::key, m_prusaslicer_generator_version, m_version, MATRIX_KEY, Slic3r::ModelVolume::Source::mesh_offset, Slic3r::_3MF_Importer::Geometry::mmu_segmentation, Slic3r::ModelVolume::mmu_segmentation_facets, MODIFIER_KEY, Slic3r::ModelVolume::name, NAME_KEY, Slic3r::ModelVolume::Source::object_idx, Slic3r::PARAMETER_MODIFIER, Slic3r::Semver::parse(), PRECISE_SEAM_CONFIG_PREFIX, PRECISE_SEAM_TYPE_KEY, Slic3r::FacetsAnnotation::reserve(), Slic3r::ModelVolume::seam_facets, Slic3r::ModelConfig::set_deserialize(), Slic3r::FacetsAnnotation::set_triangle_from_string(), Slic3r::ModelVolume::set_type(), Slic3r::FacetsAnnotation::shrink_to_fit(), Slic3r::ModelVolume::source, SOURCE_FILE_KEY, SOURCE_IN_INCHES, SOURCE_IN_METERS, SOURCE_OBJECT_ID_KEY, SOURCE_OFFSET_X_KEY, SOURCE_OFFSET_Y_KEY, SOURCE_OFFSET_Z_KEY, SOURCE_VOLUME_ID_KEY, Slic3r::ModelVolume::supported_facets, Slic3r::ModelVolume::Source::transform, Slic3r::TriangleMesh::transform(), Slic3r::Geometry::transform3d_from_string(), Slic3r::_3MF_Importer::Geometry::triangles, Slic3r::ModelVolume::type_from_string(), Slic3r::type_from_string(), Slic3r::_3MF_Importer::Metadata::value, Slic3r::_3MF_Importer::Geometry::vertices, Slic3r::TriangleMesh::volume(), Slic3r::ModelVolume::Source::volume_idx, and VOLUME_TYPE_KEY.

Referenced by _generate_volumes(), and _load_model_from_file().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_build()

bool Slic3r::_3MF_Importer::_handle_end_build ( )
private
1850 {
1851 // do nothing
1852 return true;
1853 }

References _handle_end_build().

Referenced by _handle_end_build(), and _handle_end_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_component()

bool Slic3r::_3MF_Importer::_handle_end_component ( )
private
1838 {
1839 // do nothing
1840 return true;
1841 }

References _handle_end_component().

Referenced by _handle_end_component(), and _handle_end_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_components()

bool Slic3r::_3MF_Importer::_handle_end_components ( )
private
1813 {
1814 // do nothing
1815 return true;
1816 }

References _handle_end_components().

Referenced by _handle_end_components(), and _handle_end_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_config()

bool Slic3r::_3MF_Importer::_handle_end_config ( )
private
1989 {
1990 // do nothing
1991 return true;
1992 }

References _handle_end_config().

Referenced by _handle_end_config(), and _handle_end_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_config_metadata()

bool Slic3r::_3MF_Importer::_handle_end_config_metadata ( )
private
2120 {
2121 // do nothing
2122 return true;
2123 }

References _handle_end_config_metadata().

Referenced by _handle_end_config_metadata(), and _handle_end_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_config_object()

bool Slic3r::_3MF_Importer::_handle_end_config_object ( )
private
2012 {
2013 // do nothing
2014 return true;
2015 }

References _handle_end_config_object().

Referenced by _handle_end_config_object(), and _handle_end_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_config_volume()

bool Slic3r::_3MF_Importer::_handle_end_config_volume ( )
private
2060 {
2061 // do nothing
2062 return true;
2063 }

References _handle_end_config_volume().

Referenced by _handle_end_config_volume(), and _handle_end_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_config_volume_mesh()

bool Slic3r::_3MF_Importer::_handle_end_config_volume_mesh ( )
private
2066 {
2067 // do nothing
2068 return true;
2069 }

References _handle_end_config_volume_mesh().

Referenced by _handle_end_config_volume_mesh(), and _handle_end_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_config_xml_element() [1/2]

void Slic3r::_3MF_Importer::_handle_end_config_xml_element ( const char * name)
private
1585 {
1586 if (m_xml_parser == nullptr)
1587 return;
1588
1589 bool res = true;
1590
1591 if (::strcmp(CONFIG_TAG, name) == 0)
1592 res = _handle_end_config();
1593 else if (::strcmp(OBJECT_TAG, name) == 0)
1595 else if (::strcmp(VOLUME_TAG, name) == 0)
1597 else if (::strcmp(MESH_TAG, name) == 0)
1599 else if (::strcmp(METADATA_TAG, name) == 0)
1601
1602 if (!res)
1604 }
static constexpr const char * VOLUME_TAG
Definition 3mf.cpp:124
static constexpr const char * MESH_TAG
Definition 3mf.cpp:112
static constexpr const char * CONFIG_TAG
Definition 3mf.cpp:123
static constexpr const char * METADATA_TAG
Definition 3mf.cpp:121
static constexpr const char * OBJECT_TAG
Definition 3mf.cpp:111
bool _handle_end_config_volume_mesh()
Definition 3mf.cpp:2065
bool _handle_end_config_metadata()
Definition 3mf.cpp:2119
void _stop_xml_parser(const std::string &msg=std::string())
Definition 3mf.cpp:757
bool _handle_end_config()
Definition 3mf.cpp:1988
bool _handle_end_config_volume()
Definition 3mf.cpp:2059
bool _handle_end_config_object()
Definition 3mf.cpp:2011

References _handle_end_config(), _handle_end_config_metadata(), _handle_end_config_object(), _handle_end_config_volume(), _handle_end_config_volume_mesh(), _handle_end_config_xml_element(), _stop_xml_parser(), CONFIG_TAG, m_xml_parser, MESH_TAG, METADATA_TAG, OBJECT_TAG, and VOLUME_TAG.

Referenced by _extract_model_config_from_archive(), _handle_end_config_xml_element(), and _handle_end_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_config_xml_element() [2/2]

void XMLCALL Slic3r::_3MF_Importer::_handle_end_config_xml_element ( void * userData,
const char * name )
staticprivate
2324 {
2325 _3MF_Importer* importer = (_3MF_Importer*)userData;
2326 if (importer != nullptr)
2327 importer->_handle_end_config_xml_element(name);
2328 }
_3MF_Importer()
Definition 3mf.cpp:705

References _3MF_Importer(), and _handle_end_config_xml_element().

Here is the call graph for this function:

◆ _handle_end_item()

bool Slic3r::_3MF_Importer::_handle_end_item ( )
private
1872 {
1873 // do nothing
1874 return true;
1875 }

References _handle_end_item().

Referenced by _handle_end_item(), and _handle_end_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_mesh()

bool Slic3r::_3MF_Importer::_handle_end_mesh ( )
private
1728 {
1729 // do nothing
1730 return true;
1731 }

References _handle_end_mesh().

Referenced by _handle_end_mesh(), and _handle_end_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_metadata()

bool Slic3r::_3MF_Importer::_handle_end_metadata ( )
private
1895 {
1897 m_version = (unsigned int)atoi(m_curr_characters.c_str());
1899 // std::string msg = _(L("The selected 3mf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatible."));
1900 // throw version_error(msg.c_str());
1901 const std::string msg = (boost::format(_(L("The selected 3mf file has been saved with a newer version of %1% and is not compatible."))) % std::string(SLIC3R_APP_NAME)).str();
1902 throw version_error(msg);
1903 }
1904 } else if (m_curr_metadata_name == "Application") {
1905 // Generator application of the 3MF.
1906 // SLIC3R_APP_KEY - SLIC3R_VERSION
1907 if (boost::starts_with(m_curr_characters, "PrusaSlicer-"))
1910 m_fdm_supports_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
1912 _(L("The selected 3MF contains FDM supports painted object using a newer version of PrusaSlicer and is not compatible.")));
1914 m_seam_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
1916 _(L("The selected 3MF contains seam painted object using a newer version of PrusaSlicer and is not compatible.")));
1918 m_mm_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
1920 _(L("The selected 3MF contains multi-material painted object using a newer version of PrusaSlicer and is not compatible.")));
1921 }
1922
1923 return true;
1924 }
const unsigned int SEAM_PAINTING_VERSION
Definition 3mf.cpp:88
const unsigned int VERSION_3MF_COMPATIBLE
Definition 3mf.cpp:81
const std::string SLIC3RPE_SEAM_PAINTING_VERSION
Definition 3mf.cpp:92
const std::string SLIC3RPE_FDM_SUPPORTS_PAINTING_VERSION
Definition 3mf.cpp:91
const unsigned int FDM_SUPPORTS_PAINTING_VERSION
Definition 3mf.cpp:87
const std::string SLIC3RPE_MM_PAINTING_VERSION
Definition 3mf.cpp:93
const unsigned int MM_PAINTING_VERSION
Definition 3mf.cpp:89
const char * SLIC3RPE_3MF_VERSION
Definition 3mf.cpp:82
#define _(s)
Definition 3mf.cpp:306
#define L(s)
Definition ExtrusionEntity.cpp:25
unsigned int m_fdm_supports_painting_version
Definition 3mf.cpp:569
unsigned int m_seam_painting_version
Definition 3mf.cpp:570
unsigned int m_mm_painting_version
Definition 3mf.cpp:571
static void check_painting_version(unsigned int loaded_version, unsigned int highest_supported_version, const std::string &error_msg)
Definition 3mf.cpp:1888

References _, _handle_end_metadata(), Slic3r::check_painting_version(), FDM_SUPPORTS_PAINTING_VERSION, L, m_check_version, m_curr_characters, m_curr_metadata_name, m_fdm_supports_painting_version, m_mm_painting_version, m_prusaslicer_generator_version, m_seam_painting_version, m_version, MM_PAINTING_VERSION, Slic3r::Semver::parse(), SEAM_PAINTING_VERSION, SLIC3RPE_3MF_VERSION, SLIC3RPE_FDM_SUPPORTS_PAINTING_VERSION, SLIC3RPE_MM_PAINTING_VERSION, SLIC3RPE_SEAM_PAINTING_VERSION, and VERSION_3MF_COMPATIBLE.

Referenced by _handle_end_metadata(), and _handle_end_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_model()

bool Slic3r::_3MF_Importer::_handle_end_model ( )
private
1613 {
1614 // deletes all non-built or non-instanced objects
1615 for (const IdToModelObjectMap::value_type& object : m_objects) {
1616 if (object.second >= int(m_model->objects.size())) {
1617 add_error("Unable to find object");
1618 return false;
1619 }
1620 ModelObject *model_object = m_model->objects[object.second];
1621 if (model_object != nullptr && model_object->instances.size() == 0)
1622 m_model->delete_object(model_object);
1623 }
1624
1625 if (m_version == 0) {
1626 // if the 3mf was not produced by PrusaSlicer and there is only one object,
1627 // set the object name to match the filename
1628 if (m_model->objects.size() == 1)
1629 m_model->objects.front()->name = m_name;
1630 }
1631
1632 // applies instances' matrices
1633 for (Instance& instance : m_instances) {
1634 if (instance.instance != nullptr && instance.instance->get_object() != nullptr)
1635 // apply the transform to the instance
1636 _apply_transform(*instance.instance, instance.transform);
1637 }
1638
1639 return true;
1640 }
void _apply_transform(ModelInstance &instance, const Transform3d &transform)
Definition 3mf.cpp:1972
Definition 3mf.cpp:505

References _apply_transform(), _handle_end_model(), Slic3r::_3MF_Base::add_error(), Slic3r::ModelObject::instances, m_instances, m_model, m_name, m_objects, and m_version.

Referenced by _handle_end_model(), and _handle_end_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_model_xml_element() [1/2]

void Slic3r::_3MF_Importer::_handle_end_model_xml_element ( const char * name)
private
1519 {
1520 if (m_xml_parser == nullptr)
1521 return;
1522
1523 bool res = true;
1524
1525 if (::strcmp(MODEL_TAG, name) == 0)
1526 res = _handle_end_model();
1527 else if (::strcmp(RESOURCES_TAG, name) == 0)
1528 res = _handle_end_resources();
1529 else if (::strcmp(OBJECT_TAG, name) == 0)
1530 res = _handle_end_object();
1531 else if (::strcmp(MESH_TAG, name) == 0)
1532 res = _handle_end_mesh();
1533 else if (::strcmp(VERTICES_TAG, name) == 0)
1534 res = _handle_end_vertices();
1535 else if (::strcmp(VERTEX_TAG, name) == 0)
1536 res = _handle_end_vertex();
1537 else if (::strcmp(TRIANGLES_TAG, name) == 0)
1538 res = _handle_end_triangles();
1539 else if (::strcmp(TRIANGLE_TAG, name) == 0)
1540 res = _handle_end_triangle();
1541 else if (::strcmp(COMPONENTS_TAG, name) == 0)
1542 res = _handle_end_components();
1543 else if (::strcmp(COMPONENT_TAG, name) == 0)
1544 res = _handle_end_component();
1545 else if (::strcmp(BUILD_TAG, name) == 0)
1546 res = _handle_end_build();
1547 else if (::strcmp(ITEM_TAG, name) == 0)
1548 res = _handle_end_item();
1549 else if (::strcmp(METADATA_TAG, name) == 0)
1550 res = _handle_end_metadata();
1551
1552 if (!res)
1554 }
static constexpr const char * BUILD_TAG
Definition 3mf.cpp:119
static constexpr const char * TRIANGLES_TAG
Definition 3mf.cpp:115
static constexpr const char * RESOURCES_TAG
Definition 3mf.cpp:110
static constexpr const char * VERTEX_TAG
Definition 3mf.cpp:114
static constexpr const char * ITEM_TAG
Definition 3mf.cpp:120
static constexpr const char * COMPONENTS_TAG
Definition 3mf.cpp:117
static constexpr const char * COMPONENT_TAG
Definition 3mf.cpp:118
static constexpr const char * MODEL_TAG
Definition 3mf.cpp:109
static constexpr const char * VERTICES_TAG
Definition 3mf.cpp:113
static constexpr const char * TRIANGLE_TAG
Definition 3mf.cpp:116
bool _handle_end_resources()
Definition 3mf.cpp:1648
bool _handle_end_build()
Definition 3mf.cpp:1849
bool _handle_end_component()
Definition 3mf.cpp:1837
bool _handle_end_metadata()
Definition 3mf.cpp:1894
bool _handle_end_vertex()
Definition 3mf.cpp:1757
bool _handle_end_item()
Definition 3mf.cpp:1871
bool _handle_end_components()
Definition 3mf.cpp:1812
bool _handle_end_object()
Definition 3mf.cpp:1679
bool _handle_end_vertices()
Definition 3mf.cpp:1740
bool _handle_end_triangles()
Definition 3mf.cpp:1770
bool _handle_end_triangle()
Definition 3mf.cpp:1799
bool _handle_end_model()
Definition 3mf.cpp:1612
bool _handle_end_mesh()
Definition 3mf.cpp:1727

References _handle_end_build(), _handle_end_component(), _handle_end_components(), _handle_end_item(), _handle_end_mesh(), _handle_end_metadata(), _handle_end_model(), _handle_end_model_xml_element(), _handle_end_object(), _handle_end_resources(), _handle_end_triangle(), _handle_end_triangles(), _handle_end_vertex(), _handle_end_vertices(), _stop_xml_parser(), BUILD_TAG, COMPONENT_TAG, COMPONENTS_TAG, ITEM_TAG, m_xml_parser, MESH_TAG, METADATA_TAG, MODEL_TAG, OBJECT_TAG, RESOURCES_TAG, TRIANGLE_TAG, TRIANGLES_TAG, VERTEX_TAG, and VERTICES_TAG.

Referenced by _extract_model_from_archive(), _handle_end_model_xml_element(), and _handle_end_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_model_xml_element() [2/2]

void XMLCALL Slic3r::_3MF_Importer::_handle_end_model_xml_element ( void * userData,
const char * name )
staticprivate
2303 {
2304 _3MF_Importer* importer = (_3MF_Importer*)userData;
2305 if (importer != nullptr)
2306 importer->_handle_end_model_xml_element(name);
2307 }

References _3MF_Importer(), and _handle_end_model_xml_element().

Here is the call graph for this function:

◆ _handle_end_object()

bool Slic3r::_3MF_Importer::_handle_end_object ( )
private
1680 {
1681 if (m_curr_object.object != nullptr) {
1682 if (m_curr_object.geometry.empty()) {
1683 // no geometry defined
1684 // remove the object from the model
1685 m_model->delete_object(m_curr_object.object);
1686
1687 if (m_curr_object.components.empty()) {
1688 // no components defined -> invalid object, delete it
1689 IdToModelObjectMap::iterator object_item = m_objects.find(m_curr_object.id);
1690 if (object_item != m_objects.end())
1691 m_objects.erase(object_item);
1692
1693 IdToAliasesMap::iterator alias_item = m_objects_aliases.find(m_curr_object.id);
1694 if (alias_item != m_objects_aliases.end())
1695 m_objects_aliases.erase(alias_item);
1696 }
1697 else
1698 // adds components to aliases
1699 m_objects_aliases.insert({ m_curr_object.id, m_curr_object.components });
1700 }
1701 else {
1702 // geometry defined, store it for later use
1703 m_geometries.insert({ m_curr_object.id, std::move(m_curr_object.geometry) });
1704
1705 // stores the object for later use
1706 if (m_objects.find(m_curr_object.id) == m_objects.end()) {
1707 m_objects.insert({ m_curr_object.id, m_curr_object.model_object_idx });
1708 m_objects_aliases.insert({ m_curr_object.id, { 1, Component(m_curr_object.id) } }); // aliases itself
1709 }
1710 else {
1711 add_error("Found object with duplicate id");
1712 return false;
1713 }
1714 }
1715 }
1716
1717 return true;
1718 }
IdToGeometryMap m_geometries
Definition 3mf.cpp:584
CurrentObject m_curr_object
Definition 3mf.cpp:580

References _handle_end_object(), Slic3r::_3MF_Base::add_error(), m_curr_object, m_geometries, m_model, m_objects, and m_objects_aliases.

Referenced by _handle_end_model_xml_element(), and _handle_end_object().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_resources()

bool Slic3r::_3MF_Importer::_handle_end_resources ( )
private
1649 {
1650 // do nothing
1651 return true;
1652 }

References _handle_end_resources().

Referenced by _handle_end_model_xml_element(), and _handle_end_resources().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_triangle()

bool Slic3r::_3MF_Importer::_handle_end_triangle ( )
private
1800 {
1801 // do nothing
1802 return true;
1803 }

References _handle_end_triangle().

Referenced by _handle_end_model_xml_element(), and _handle_end_triangle().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_triangles()

bool Slic3r::_3MF_Importer::_handle_end_triangles ( )
private
1771 {
1772 // do nothing
1773 return true;
1774 }

References _handle_end_triangles().

Referenced by _handle_end_model_xml_element(), and _handle_end_triangles().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_vertex()

bool Slic3r::_3MF_Importer::_handle_end_vertex ( )
private
1758 {
1759 // do nothing
1760 return true;
1761 }

References _handle_end_vertex().

Referenced by _handle_end_model_xml_element(), and _handle_end_vertex().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_end_vertices()

bool Slic3r::_3MF_Importer::_handle_end_vertices ( )
private
1741 {
1742 // do nothing
1743 return true;
1744 }

References _handle_end_vertices().

Referenced by _handle_end_model_xml_element(), and _handle_end_vertices().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_model_xml_characters() [1/2]

void Slic3r::_3MF_Importer::_handle_model_xml_characters ( const XML_Char * s,
int len )
private
1557 {
1558 m_curr_characters.append(s, len);
1559 }

References _handle_model_xml_characters(), and m_curr_characters.

Referenced by _extract_model_from_archive(), _handle_model_xml_characters(), and _handle_model_xml_characters().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_model_xml_characters() [2/2]

void XMLCALL Slic3r::_3MF_Importer::_handle_model_xml_characters ( void * userData,
const XML_Char * s,
int len )
staticprivate
2310 {
2311 _3MF_Importer* importer = (_3MF_Importer*)userData;
2312 if (importer != nullptr)
2313 importer->_handle_model_xml_characters(s, len);
2314 }

References _3MF_Importer(), and _handle_model_xml_characters().

Here is the call graph for this function:

◆ _handle_start_build()

bool Slic3r::_3MF_Importer::_handle_start_build ( const char ** attributes,
unsigned int num_attributes )
private
1844 {
1845 // do nothing
1846 return true;
1847 }

References _handle_start_build().

Referenced by _handle_start_build(), and _handle_start_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_component()

bool Slic3r::_3MF_Importer::_handle_start_component ( const char ** attributes,
unsigned int num_attributes )
private
1819 {
1820 int object_id = get_attribute_value_int(attributes, num_attributes, OBJECTID_ATTR);
1822
1823 IdToModelObjectMap::iterator object_item = m_objects.find(object_id);
1824 if (object_item == m_objects.end()) {
1825 IdToAliasesMap::iterator alias_item = m_objects_aliases.find(object_id);
1826 if (alias_item == m_objects_aliases.end()) {
1827 add_error("Found component with invalid object id");
1828 return false;
1829 }
1830 }
1831
1832 m_curr_object.components.emplace_back(object_id, transform);
1833
1834 return true;
1835 }
int get_attribute_value_int(const char **attributes, unsigned int attributes_size, const char *attribute_key)
Definition 3mf.cpp:225
Slic3r::Transform3d get_transform_from_3mf_specs_string(const std::string &mat_str)
Definition 3mf.cpp:239
std::string get_attribute_value_string(const char **attributes, unsigned int attributes_size, const char *attribute_key)
Definition 3mf.cpp:211
static constexpr const char * TRANSFORM_ATTR
Definition 3mf.cpp:137
static constexpr const char * OBJECTID_ATTR
Definition 3mf.cpp:136

References _handle_start_component(), Slic3r::_3MF_Base::add_error(), get_attribute_value_int(), get_attribute_value_string(), get_transform_from_3mf_specs_string(), m_curr_object, m_objects, m_objects_aliases, OBJECTID_ATTR, Slic3r::transform(), and TRANSFORM_ATTR.

Referenced by _handle_start_component(), and _handle_start_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_components()

bool Slic3r::_3MF_Importer::_handle_start_components ( const char ** attributes,
unsigned int num_attributes )
private
1806 {
1807 // reset current components
1808 m_curr_object.components.clear();
1809 return true;
1810 }

References _handle_start_components(), and m_curr_object.

Referenced by _handle_start_components(), and _handle_start_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_config()

bool Slic3r::_3MF_Importer::_handle_start_config ( const char ** attributes,
unsigned int num_attributes )
private
1983 {
1984 // do nothing
1985 return true;
1986 }

References _handle_start_config().

Referenced by _handle_start_config(), and _handle_start_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_config_metadata()

bool Slic3r::_3MF_Importer::_handle_start_config_metadata ( const char ** attributes,
unsigned int num_attributes )
private
2072 {
2073 IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id);
2074 if (object == m_objects_metadata.end()) {
2075 add_error("Cannot assign metadata to valid object id");
2076 return false;
2077 }
2078
2079 std::string type = get_attribute_value_string(attributes, num_attributes, TYPE_ATTR);
2080 std::string key = get_attribute_value_string(attributes, num_attributes, KEY_ATTR);
2081 std::string value = get_attribute_value_string(attributes, num_attributes, VALUE_ATTR);
2082
2083 // filter the prusa model config keys
2084 std::vector<std::string> valid_keys = {
2085 "name",
2086 "volume_type",
2088 "matrix",
2089 "source_file",
2090 "source_object_id",
2091 "source_volume_id",
2092 "source_offset_x",
2093 "source_offset_y",
2094 "source_offset_z",
2095 "extruder",
2096 "modifier"
2097 };
2098
2099 auto itor = std::find(valid_keys.begin(), valid_keys.end(), key);
2100 if (itor == valid_keys.end() && !(type == VOLUME_TYPE && boost::starts_with(key, PRECISE_SEAM_CONFIG_PREFIX))) {
2101 // do nothing if not valid keys
2102 return true;
2103 }
2104
2105 if (type == OBJECT_TYPE)
2106 object->second.metadata.emplace_back(key, value);
2107 else if (type == VOLUME_TYPE) {
2108 if (size_t(m_curr_config.volume_id) < object->second.volumes.size())
2109 object->second.volumes[m_curr_config.volume_id].metadata.emplace_back(key, value);
2110 }
2111 else {
2112 add_error("Found invalid metadata type");
2113 return false;
2114 }
2115
2116 return true;
2117 }
static constexpr const char * VOLUME_TYPE
Definition 3mf.cpp:151
static constexpr const char * OBJECT_TYPE
Definition 3mf.cpp:150
static constexpr const char * VALUE_ATTR
Definition 3mf.cpp:146
static constexpr const char * TYPE_ATTR
Definition 3mf.cpp:128
static constexpr const char * KEY_ATTR
Definition 3mf.cpp:145
IdToMetadataMap m_objects_metadata
Definition 3mf.cpp:586
CurrentConfig m_curr_config
Definition 3mf.cpp:585

References _handle_start_config_metadata(), Slic3r::_3MF_Base::add_error(), get_attribute_value_string(), KEY_ATTR, m_curr_config, m_objects_metadata, OBJECT_TYPE, PRECISE_SEAM_CONFIG_PREFIX, PRECISE_SEAM_TYPE_KEY, TYPE_ATTR, VALUE_ATTR, and VOLUME_TYPE.

Referenced by _handle_start_config_metadata(), and _handle_start_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_config_object()

bool Slic3r::_3MF_Importer::_handle_start_config_object ( const char ** attributes,
unsigned int num_attributes )
private
1995 {
1996 int object_id = get_attribute_value_int(attributes, num_attributes, ID_ATTR);
1997 IdToMetadataMap::iterator object_item = m_objects_metadata.find(object_id);
1998 if (object_item != m_objects_metadata.end()) {
1999 add_error("Found duplicated object id");
2000 return false;
2001 }
2002
2003 // Added because of github #3435, currently not used by PrusaSlicer
2004 // int instances_count_id = get_attribute_value_int(attributes, num_attributes, INSTANCESCOUNT_ATTR);
2005
2006 m_objects_metadata.insert({ object_id, ObjectMetadata() });
2007 m_curr_config.object_id = object_id;
2008 return true;
2009 }
static constexpr const char * ID_ATTR
Definition 3mf.cpp:129

References _handle_start_config_object(), Slic3r::_3MF_Base::add_error(), get_attribute_value_int(), ID_ATTR, m_curr_config, and m_objects_metadata.

Referenced by _handle_start_config_object(), and _handle_start_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_config_volume()

bool Slic3r::_3MF_Importer::_handle_start_config_volume ( const char ** attributes,
unsigned int num_attributes )
private
2018 {
2019 IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id);
2020 if (object == m_objects_metadata.end()) {
2021 add_error("Cannot assign volume to a valid object");
2022 return false;
2023 }
2024
2025 m_curr_config.volume_id = (int)object->second.volumes.size();
2026
2027 unsigned int first_triangle_id = (unsigned int)get_attribute_value_int(attributes, num_attributes, FIRST_TRIANGLE_ID_ATTR);
2028 unsigned int last_triangle_id = (unsigned int)get_attribute_value_int(attributes, num_attributes, LAST_TRIANGLE_ID_ATTR);
2029
2030 object->second.volumes.emplace_back(first_triangle_id, last_triangle_id);
2031 return true;
2032 }
static constexpr const char * FIRST_TRIANGLE_ID_ATTR
Definition 3mf.cpp:147
static constexpr const char * LAST_TRIANGLE_ID_ATTR
Definition 3mf.cpp:148

References _handle_start_config_volume(), Slic3r::_3MF_Base::add_error(), FIRST_TRIANGLE_ID_ATTR, get_attribute_value_int(), LAST_TRIANGLE_ID_ATTR, m_curr_config, and m_objects_metadata.

Referenced by _handle_start_config_volume(), and _handle_start_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_config_volume_mesh()

bool Slic3r::_3MF_Importer::_handle_start_config_volume_mesh ( const char ** attributes,
unsigned int num_attributes )
private
2035 {
2036 IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id);
2037 if (object == m_objects_metadata.end()) {
2038 add_error("Cannot assign volume mesh to a valid object");
2039 return false;
2040 }
2041 if (object->second.volumes.empty()) {
2042 add_error("Cannot assign mesh to a valid olume");
2043 return false;
2044 }
2045
2046 ObjectMetadata::VolumeMetadata& volume = object->second.volumes.back();
2047
2048 int edges_fixed = get_attribute_value_int(attributes, num_attributes, MESH_STAT_EDGES_FIXED );
2049 int degenerate_facets = get_attribute_value_int(attributes, num_attributes, MESH_STAT_DEGENERATED_FACETS);
2050 int facets_removed = get_attribute_value_int(attributes, num_attributes, MESH_STAT_FACETS_REMOVED );
2051 int facets_reversed = get_attribute_value_int(attributes, num_attributes, MESH_STAT_FACETS_RESERVED );
2052 int backwards_edges = get_attribute_value_int(attributes, num_attributes, MESH_STAT_BACKWARDS_EDGES );
2053
2054 volume.mesh_stats = { edges_fixed, degenerate_facets, facets_removed, facets_reversed, backwards_edges };
2055
2056 return true;
2057 }
static constexpr const char * MESH_STAT_BACKWARDS_EDGES
Definition 3mf.cpp:174
static constexpr const char * MESH_STAT_EDGES_FIXED
Definition 3mf.cpp:170
static constexpr const char * MESH_STAT_FACETS_RESERVED
Definition 3mf.cpp:173
static constexpr const char * MESH_STAT_FACETS_REMOVED
Definition 3mf.cpp:172
static constexpr const char * MESH_STAT_DEGENERATED_FACETS
Definition 3mf.cpp:171

References _handle_start_config_volume_mesh(), Slic3r::_3MF_Base::add_error(), get_attribute_value_int(), m_curr_config, m_objects_metadata, MESH_STAT_BACKWARDS_EDGES, MESH_STAT_DEGENERATED_FACETS, MESH_STAT_EDGES_FIXED, MESH_STAT_FACETS_REMOVED, MESH_STAT_FACETS_RESERVED, and Slic3r::_3MF_Importer::ObjectMetadata::VolumeMetadata::mesh_stats.

Referenced by _handle_start_config_volume_mesh(), and _handle_start_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_config_xml_element() [1/2]

void Slic3r::_3MF_Importer::_handle_start_config_xml_element ( const char * name,
const char ** attributes )
private
1562 {
1563 if (m_xml_parser == nullptr)
1564 return;
1565
1566 bool res = true;
1567 unsigned int num_attributes = (unsigned int)XML_GetSpecifiedAttributeCount(m_xml_parser);
1568
1569 if (::strcmp(CONFIG_TAG, name) == 0)
1570 res = _handle_start_config(attributes, num_attributes);
1571 else if (::strcmp(OBJECT_TAG, name) == 0)
1572 res = _handle_start_config_object(attributes, num_attributes);
1573 else if (::strcmp(VOLUME_TAG, name) == 0)
1574 res = _handle_start_config_volume(attributes, num_attributes);
1575 else if (::strcmp(MESH_TAG, name) == 0)
1576 res = _handle_start_config_volume_mesh(attributes, num_attributes);
1577 else if (::strcmp(METADATA_TAG, name) == 0)
1578 res = _handle_start_config_metadata(attributes, num_attributes);
1579
1580 if (!res)
1582 }
bool _handle_start_config_object(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1994
bool _handle_start_config_volume_mesh(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:2034
bool _handle_start_config(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1982
bool _handle_start_config_metadata(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:2071
bool _handle_start_config_volume(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:2017

References _handle_start_config(), _handle_start_config_metadata(), _handle_start_config_object(), _handle_start_config_volume(), _handle_start_config_volume_mesh(), _handle_start_config_xml_element(), _stop_xml_parser(), CONFIG_TAG, m_xml_parser, MESH_TAG, METADATA_TAG, OBJECT_TAG, and VOLUME_TAG.

Referenced by _extract_model_config_from_archive(), _handle_start_config_xml_element(), and _handle_start_config_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_config_xml_element() [2/2]

void XMLCALL Slic3r::_3MF_Importer::_handle_start_config_xml_element ( void * userData,
const char * name,
const char ** attributes )
staticprivate
2317 {
2318 _3MF_Importer* importer = (_3MF_Importer*)userData;
2319 if (importer != nullptr)
2320 importer->_handle_start_config_xml_element(name, attributes);
2321 }

References _3MF_Importer(), and _handle_start_config_xml_element().

Here is the call graph for this function:

◆ _handle_start_item()

bool Slic3r::_3MF_Importer::_handle_start_item ( const char ** attributes,
unsigned int num_attributes )
private
1856 {
1857 // we are ignoring the following attributes
1858 // thumbnail
1859 // partnumber
1860 // pid
1861 // pindex
1862 // see specifications
1863
1864 int object_id = get_attribute_value_int(attributes, num_attributes, OBJECTID_ATTR);
1866 int printable = get_attribute_value_bool(attributes, num_attributes, PRINTABLE_ATTR);
1867
1868 return _create_object_instance(object_id, transform, printable, 1);
1869 }
bool get_attribute_value_bool(const char **attributes, unsigned int attributes_size, const char *attribute_key)
Definition 3mf.cpp:233
static constexpr const char * PRINTABLE_ATTR
Definition 3mf.cpp:138

References _create_object_instance(), _handle_start_item(), get_attribute_value_bool(), get_attribute_value_int(), get_attribute_value_string(), get_transform_from_3mf_specs_string(), OBJECTID_ATTR, PRINTABLE_ATTR, Slic3r::transform(), and TRANSFORM_ATTR.

Referenced by _handle_start_item(), and _handle_start_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_mesh()

bool Slic3r::_3MF_Importer::_handle_start_mesh ( const char ** attributes,
unsigned int num_attributes )
private
1721 {
1722 // reset current geometry
1723 m_curr_object.geometry.reset();
1724 return true;
1725 }

References _handle_start_mesh(), and m_curr_object.

Referenced by _handle_start_mesh(), and _handle_start_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_metadata()

bool Slic3r::_3MF_Importer::_handle_start_metadata ( const char ** attributes,
unsigned int num_attributes )
private
1878 {
1879 m_curr_characters.clear();
1880
1881 std::string name = get_attribute_value_string(attributes, num_attributes, NAME_ATTR);
1882 if (!name.empty())
1883 m_curr_metadata_name = name;
1884
1885 return true;
1886 }
static constexpr const char * NAME_ATTR
Definition 3mf.cpp:127

References _handle_start_metadata(), get_attribute_value_string(), m_curr_characters, m_curr_metadata_name, and NAME_ATTR.

Referenced by _handle_start_metadata(), and _handle_start_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_model()

bool Slic3r::_3MF_Importer::_handle_start_model ( const char ** attributes,
unsigned int num_attributes )
private
1607 {
1608 m_unit_factor = get_unit_factor(get_attribute_value_string(attributes, num_attributes, UNIT_ATTR));
1609 return true;
1610 }
static constexpr const char * UNIT_ATTR
Definition 3mf.cpp:126
float get_unit_factor(const std::string &unit)
Definition 3mf.cpp:268

References _handle_start_model(), get_attribute_value_string(), get_unit_factor(), m_unit_factor, and UNIT_ATTR.

Referenced by _handle_start_model(), and _handle_start_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_model_xml_element() [1/2]

void Slic3r::_3MF_Importer::_handle_start_model_xml_element ( const char * name,
const char ** attributes )
private
1480 {
1481 if (m_xml_parser == nullptr)
1482 return;
1483
1484 bool res = true;
1485 unsigned int num_attributes = (unsigned int)XML_GetSpecifiedAttributeCount(m_xml_parser);
1486
1487 if (::strcmp(MODEL_TAG, name) == 0)
1488 res = _handle_start_model(attributes, num_attributes);
1489 else if (::strcmp(RESOURCES_TAG, name) == 0)
1490 res = _handle_start_resources(attributes, num_attributes);
1491 else if (::strcmp(OBJECT_TAG, name) == 0)
1492 res = _handle_start_object(attributes, num_attributes);
1493 else if (::strcmp(MESH_TAG, name) == 0)
1494 res = _handle_start_mesh(attributes, num_attributes);
1495 else if (::strcmp(VERTICES_TAG, name) == 0)
1496 res = _handle_start_vertices(attributes, num_attributes);
1497 else if (::strcmp(VERTEX_TAG, name) == 0)
1498 res = _handle_start_vertex(attributes, num_attributes);
1499 else if (::strcmp(TRIANGLES_TAG, name) == 0)
1500 res = _handle_start_triangles(attributes, num_attributes);
1501 else if (::strcmp(TRIANGLE_TAG, name) == 0)
1502 res = _handle_start_triangle(attributes, num_attributes);
1503 else if (::strcmp(COMPONENTS_TAG, name) == 0)
1504 res = _handle_start_components(attributes, num_attributes);
1505 else if (::strcmp(COMPONENT_TAG, name) == 0)
1506 res = _handle_start_component(attributes, num_attributes);
1507 else if (::strcmp(BUILD_TAG, name) == 0)
1508 res = _handle_start_build(attributes, num_attributes);
1509 else if (::strcmp(ITEM_TAG, name) == 0)
1510 res = _handle_start_item(attributes, num_attributes);
1511 else if (::strcmp(METADATA_TAG, name) == 0)
1512 res = _handle_start_metadata(attributes, num_attributes);
1513
1514 if (!res)
1516 }
bool _handle_start_build(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1843
bool _handle_start_mesh(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1720
bool _handle_start_component(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1818
bool _handle_start_object(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1654
bool _handle_start_resources(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1642
bool _handle_start_vertices(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1733
bool _handle_start_item(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1855
bool _handle_start_model(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1606
bool _handle_start_triangle(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1776
bool _handle_start_vertex(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1746
bool _handle_start_metadata(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1877
bool _handle_start_triangles(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1763
bool _handle_start_components(const char **attributes, unsigned int num_attributes)
Definition 3mf.cpp:1805

References _handle_start_build(), _handle_start_component(), _handle_start_components(), _handle_start_item(), _handle_start_mesh(), _handle_start_metadata(), _handle_start_model(), _handle_start_model_xml_element(), _handle_start_object(), _handle_start_resources(), _handle_start_triangle(), _handle_start_triangles(), _handle_start_vertex(), _handle_start_vertices(), _stop_xml_parser(), BUILD_TAG, COMPONENT_TAG, COMPONENTS_TAG, ITEM_TAG, m_xml_parser, MESH_TAG, METADATA_TAG, MODEL_TAG, OBJECT_TAG, RESOURCES_TAG, TRIANGLE_TAG, TRIANGLES_TAG, VERTEX_TAG, and VERTICES_TAG.

Referenced by _extract_model_from_archive(), _handle_start_model_xml_element(), and _handle_start_model_xml_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_model_xml_element() [2/2]

void XMLCALL Slic3r::_3MF_Importer::_handle_start_model_xml_element ( void * userData,
const char * name,
const char ** attributes )
staticprivate
2296 {
2297 _3MF_Importer* importer = (_3MF_Importer*)userData;
2298 if (importer != nullptr)
2299 importer->_handle_start_model_xml_element(name, attributes);
2300 }

References _3MF_Importer(), and _handle_start_model_xml_element().

Here is the call graph for this function:

◆ _handle_start_object()

bool Slic3r::_3MF_Importer::_handle_start_object ( const char ** attributes,
unsigned int num_attributes )
private
1655 {
1656 // reset current data
1657 m_curr_object.reset();
1658
1659 if (is_valid_object_type(get_attribute_value_string(attributes, num_attributes, TYPE_ATTR))) {
1660 // create new object (it may be removed later if no instances are generated from it)
1661 m_curr_object.model_object_idx = (int)m_model->objects.size();
1662 m_curr_object.object = m_model->add_object();
1663 if (m_curr_object.object == nullptr) {
1664 add_error("Unable to create object");
1665 return false;
1666 }
1667
1668 // set object data
1669 m_curr_object.object->name = get_attribute_value_string(attributes, num_attributes, NAME_ATTR);
1670 if (m_curr_object.object->name.empty())
1671 m_curr_object.object->name = m_name + "_" + std::to_string(m_model->objects.size());
1672
1673 m_curr_object.id = get_attribute_value_int(attributes, num_attributes, ID_ATTR);
1674 }
1675
1676 return true;
1677 }
bool is_valid_object_type(const std::string &type)
Definition 3mf.cpp:287

References _handle_start_object(), Slic3r::_3MF_Base::add_error(), get_attribute_value_int(), get_attribute_value_string(), ID_ATTR, is_valid_object_type(), m_curr_object, m_model, m_name, NAME_ATTR, and TYPE_ATTR.

Referenced by _handle_start_model_xml_element(), and _handle_start_object().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_resources()

bool Slic3r::_3MF_Importer::_handle_start_resources ( const char ** attributes,
unsigned int num_attributes )
private
1643 {
1644 // do nothing
1645 return true;
1646 }

References _handle_start_resources().

Referenced by _handle_start_model_xml_element(), and _handle_start_resources().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_triangle()

bool Slic3r::_3MF_Importer::_handle_start_triangle ( const char ** attributes,
unsigned int num_attributes )
private
1777 {
1778 // we are ignoring the following attributes:
1779 // p1
1780 // p2
1781 // p3
1782 // pid
1783 // see specifications
1784
1785 // appends the triangle's vertices indices
1786 // missing values are set equal to ZERO
1787 m_curr_object.geometry.triangles.emplace_back(
1788 get_attribute_value_int(attributes, num_attributes, V1_ATTR),
1789 get_attribute_value_int(attributes, num_attributes, V2_ATTR),
1790 get_attribute_value_int(attributes, num_attributes, V3_ATTR));
1791
1792 m_curr_object.geometry.custom_supports.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SUPPORTS_ATTR));
1793 m_curr_object.geometry.custom_seam.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SEAM_ATTR));
1794 m_curr_object.geometry.fuzzy_skin.push_back(get_attribute_value_string(attributes, num_attributes, FUZZY_SKIN_ATTR));
1795 m_curr_object.geometry.mmu_segmentation.push_back(get_attribute_value_string(attributes, num_attributes, MMU_SEGMENTATION_ATTR));
1796 return true;
1797 }
static constexpr const char * MMU_SEGMENTATION_ATTR
Definition 3mf.cpp:142
static constexpr const char * CUSTOM_SEAM_ATTR
Definition 3mf.cpp:141
static constexpr const char * CUSTOM_SUPPORTS_ATTR
Definition 3mf.cpp:140
static constexpr const char * FUZZY_SKIN_ATTR
Definition 3mf.cpp:143
static constexpr const char * V3_ATTR
Definition 3mf.cpp:135
static constexpr const char * V1_ATTR
Definition 3mf.cpp:133
static constexpr const char * V2_ATTR
Definition 3mf.cpp:134

References _handle_start_triangle(), CUSTOM_SEAM_ATTR, CUSTOM_SUPPORTS_ATTR, FUZZY_SKIN_ATTR, get_attribute_value_int(), get_attribute_value_string(), m_curr_object, MMU_SEGMENTATION_ATTR, V1_ATTR, V2_ATTR, and V3_ATTR.

Referenced by _handle_start_model_xml_element(), and _handle_start_triangle().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_triangles()

bool Slic3r::_3MF_Importer::_handle_start_triangles ( const char ** attributes,
unsigned int num_attributes )
private
1764 {
1765 // reset current triangles
1766 m_curr_object.geometry.triangles.clear();
1767 return true;
1768 }

References _handle_start_triangles(), and m_curr_object.

Referenced by _handle_start_model_xml_element(), and _handle_start_triangles().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_vertex()

bool Slic3r::_3MF_Importer::_handle_start_vertex ( const char ** attributes,
unsigned int num_attributes )
private
1747 {
1748 // appends the vertex coordinates
1749 // missing values are set equal to ZERO
1750 m_curr_object.geometry.vertices.emplace_back(
1751 m_unit_factor * get_attribute_value_float(attributes, num_attributes, X_ATTR),
1752 m_unit_factor * get_attribute_value_float(attributes, num_attributes, Y_ATTR),
1753 m_unit_factor * get_attribute_value_float(attributes, num_attributes, Z_ATTR));
1754 return true;
1755 }
static constexpr const char * X_ATTR
Definition 3mf.cpp:130
static constexpr const char * Y_ATTR
Definition 3mf.cpp:131
static constexpr const char * Z_ATTR
Definition 3mf.cpp:132
float get_attribute_value_float(const char **attributes, unsigned int attributes_size, const char *attribute_key)
Definition 3mf.cpp:217

References _handle_start_vertex(), get_attribute_value_float(), m_curr_object, m_unit_factor, X_ATTR, Y_ATTR, and Z_ATTR.

Referenced by _handle_start_model_xml_element(), and _handle_start_vertex().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _handle_start_vertices()

bool Slic3r::_3MF_Importer::_handle_start_vertices ( const char ** attributes,
unsigned int num_attributes )
private
1734 {
1735 // reset current vertices
1736 m_curr_object.geometry.vertices.clear();
1737 return true;
1738 }

References _handle_start_vertices(), and m_curr_object.

Referenced by _handle_start_model_xml_element(), and _handle_start_vertices().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _load_model_from_file()

bool Slic3r::_3MF_Importer::_load_model_from_file ( const std::string & filename,
Model & model,
DynamicPrintConfig & config,
ConfigSubstitutionContext & config_substitutions )
private
768 {
769 mz_zip_archive archive;
770 mz_zip_zero_struct(&archive);
771
772 if (!open_zip_reader(&archive, filename)) {
773 add_error("Unable to open the file");
774 return false;
775 }
776
777 mz_uint num_entries = mz_zip_reader_get_num_files(&archive);
778
779 mz_zip_archive_file_stat stat;
780
781 m_name = boost::filesystem::path(filename).stem().string();
782
783 // we first loop the entries to read from the archive the .model file only, in order to extract the version from it
784 for (mz_uint i = 0; i < num_entries; ++i) {
785 if (mz_zip_reader_file_stat(&archive, i, &stat)) {
786 std::string name(stat.m_filename);
787 std::replace(name.begin(), name.end(), '\\', '/');
788
789 if (boost::algorithm::istarts_with(name, MODEL_FOLDER) && boost::algorithm::iends_with(name, MODEL_EXTENSION)) {
790 try
791 {
792 // valid model name -> extract model
793 if (!_extract_model_from_archive(archive, stat)) {
794 close_zip_reader(&archive);
795 add_error("Archive does not contain a valid model");
796 return false;
797 }
798 }
799 catch (const std::exception& e)
800 {
801 // ensure the zip archive is closed and rethrow the exception
802 close_zip_reader(&archive);
803 throw Slic3r::FileIOError(e.what());
804 }
805 }
806 }
807 }
808
809 // we then loop again the entries to read other files stored in the archive
810 for (mz_uint i = 0; i < num_entries; ++i) {
811 if (mz_zip_reader_file_stat(&archive, i, &stat)) {
812 std::string name(stat.m_filename);
813 std::replace(name.begin(), name.end(), '\\', '/');
814
815 /*
816 if (boost::algorithm::iequals(name, LAYER_HEIGHTS_PROFILE_FILE)) {
817 // extract slic3r layer heights profile file
818 _extract_layer_heights_profile_config_from_archive(archive, stat);
819 }
820 else if (boost::algorithm::iequals(name, LAYER_CONFIG_RANGES_FILE)) {
821 // extract slic3r layer config ranges file
822 _extract_layer_config_ranges_from_archive(archive, stat, config_substitutions);
823 }
824 else if (boost::algorithm::iequals(name, SLA_SUPPORT_POINTS_FILE)) {
825 // extract sla support points file
826 _extract_sla_support_points_from_archive(archive, stat);
827 }
828 else if (boost::algorithm::iequals(name, SLA_DRAIN_HOLES_FILE)) {
829 // extract sla support points file
830 _extract_sla_drain_holes_from_archive(archive, stat);
831 }
832 else if (boost::algorithm::iequals(name, PRINT_CONFIG_FILE)) {
833 // extract slic3r print config file
834 _extract_print_config_from_archive(archive, stat, config, config_substitutions, filename);
835 }
836 else if (boost::algorithm::iequals(name, CUSTOM_GCODE_PER_PRINT_Z_FILE)) {
837 // extract slic3r layer config ranges file
838 _extract_custom_gcode_per_print_z_from_archive(archive, stat);
839 }
840 */
841 // only read the model config for Prusa 3mf
842 if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE)) {
843 // extract slic3r model config file
844 if (!_extract_model_config_from_archive(archive, stat, model)) {
845 close_zip_reader(&archive);
846 add_error("Archive does not contain a valid model config");
847 return false;
848 }
849 }
850 }
851 }
852
853 close_zip_reader(&archive);
854
855 if (m_version == 0) {
856 // if the 3mf was not produced by PrusaSlicer and there is more than one instance,
857 // split the object in as many objects as instances
858 size_t curr_models_count = m_model->objects.size();
859 size_t i = 0;
860 while (i < curr_models_count) {
861 ModelObject* model_object = m_model->objects[i];
862 if (model_object->instances.size() > 1) {
863 // select the geometry associated with the original model object
864 const Geometry* geometry = nullptr;
865 for (const IdToModelObjectMap::value_type& object : m_objects) {
866 if (object.second == int(i)) {
867 IdToGeometryMap::const_iterator obj_geometry = m_geometries.find(object.first);
868 if (obj_geometry == m_geometries.end()) {
869 add_error("Unable to find object geometry");
870 return false;
871 }
872 geometry = &obj_geometry->second;
873 break;
874 }
875 }
876
877 if (geometry == nullptr) {
878 add_error("Unable to find object geometry");
879 return false;
880 }
881
882 // use the geometry to create the volumes in the new model objects
883 ObjectMetadata::VolumeMetadataList volumes(1, { 0, (unsigned int)geometry->triangles.size() - 1 });
884
885 // for each instance after the 1st, create a new model object containing only that instance
886 // and copy into it the geometry
887 while (model_object->instances.size() > 1) {
888 ModelObject* new_model_object = m_model->add_object(*model_object);
889 new_model_object->clear_instances();
890 new_model_object->add_instance(*model_object->instances.back());
891 model_object->delete_last_instance();
892 if (!_generate_volumes(*new_model_object, *geometry, volumes, config_substitutions))
893 return false;
894 }
895 }
896 ++i;
897 }
898 }
899
900 for (const IdToModelObjectMap::value_type& object : m_objects) {
901 if (object.second >= int(m_model->objects.size())) {
902 add_error("Unable to find object");
903 return false;
904 }
905 ModelObject* model_object = m_model->objects[object.second];
906 IdToGeometryMap::const_iterator obj_geometry = m_geometries.find(object.first);
907 if (obj_geometry == m_geometries.end()) {
908 add_error("Unable to find object geometry");
909 return false;
910 }
911
912 // m_layer_heights_profiles are indexed by a 1 based model object index.
913 IdToLayerHeightsProfileMap::iterator obj_layer_heights_profile = m_layer_heights_profiles.find(object.second + 1);
914 if (obj_layer_heights_profile != m_layer_heights_profiles.end())
915 model_object->layer_height_profile.set(std::move(obj_layer_heights_profile->second));
916
917 // m_layer_config_ranges are indexed by a 1 based model object index.
918 IdToLayerConfigRangesMap::iterator obj_layer_config_ranges = m_layer_config_ranges.find(object.second + 1);
919 if (obj_layer_config_ranges != m_layer_config_ranges.end())
920 model_object->layer_config_ranges = std::move(obj_layer_config_ranges->second);
921
922 // m_sla_support_points are indexed by a 1 based model object index.
923 IdToSlaSupportPointsMap::iterator obj_sla_support_points = m_sla_support_points.find(object.second + 1);
924 if (obj_sla_support_points != m_sla_support_points.end() && !obj_sla_support_points->second.empty()) {
925 model_object->sla_support_points = std::move(obj_sla_support_points->second);
926 model_object->sla_points_status = sla::PointsStatus::UserModified;
927 }
928
929 IdToSlaDrainHolesMap::iterator obj_drain_holes = m_sla_drain_holes.find(object.second + 1);
930 if (obj_drain_holes != m_sla_drain_holes.end() && !obj_drain_holes->second.empty()) {
931 model_object->sla_drain_holes = std::move(obj_drain_holes->second);
932 }
933
935 ObjectMetadata::VolumeMetadataList* volumes_ptr = nullptr;
936
937 IdToMetadataMap::iterator obj_metadata = m_objects_metadata.find(object.first);
938 if (obj_metadata != m_objects_metadata.end()) {
939 // config data has been found, this model was saved using slic3r pe
940
941 // apply object's name and config data
942 for (const Metadata& metadata : obj_metadata->second.metadata) {
943 if (metadata.key == "name")
944 model_object->name = metadata.value;
945 else
946 model_object->config.set_deserialize(metadata.key, metadata.value, config_substitutions);
947 }
948
949 // select object's detected volumes
950 volumes_ptr = &obj_metadata->second.volumes;
951 }
952 else {
953 // config data not found, this model was not saved using slic3r pe
954
955 // add the entire geometry as the single volume to generate
956 volumes.emplace_back(0, (int)obj_geometry->second.triangles.size() - 1);
957
958 // select as volumes
959 volumes_ptr = &volumes;
960 }
961
962 if (!_generate_volumes(*model_object, obj_geometry->second, *volumes_ptr, config_substitutions))
963 return false;
964 }
965
966 int object_idx = 0;
967 for (ModelObject* o : model.objects) {
968 int volume_idx = 0;
969 for (ModelVolume* v : o->volumes) {
970 if (v->source.input_file.empty() && v->type() == ModelVolumeType::MODEL_PART) {
971 v->source.input_file = filename;
972 if (v->source.volume_idx == -1)
973 v->source.volume_idx = volume_idx;
974 if (v->source.object_idx == -1)
975 v->source.object_idx = object_idx;
976 }
977 ++volume_idx;
978 }
979 ++object_idx;
980 }
981
982 //BBS: copy object isteadof instance
983 int object_size = model.objects.size();
984 for (int obj_index = 0; obj_index < object_size; obj_index ++) {
985 ModelObject* object = model.objects[obj_index];
986 while (object->instances.size() > 1) {
987 ModelObject* new_model_object = model.add_object(*object);
988 new_model_object->clear_instances();
989 new_model_object->add_instance(*object->instances.back());
990 object->delete_last_instance();
991 }
992 }
993
994// // fixes the min z of the model if negative
995// model.adjust_min_z();
996
997 return true;
998 }
const std::string MODEL_EXTENSION
Definition 3mf.cpp:96
const std::string MODEL_CONFIG_FILE
Definition 3mf.cpp:102
const std::string MODEL_FOLDER
Definition 3mf.cpp:95
bool _generate_volumes(ModelObject &object, const Geometry &geometry, const ObjectMetadata::VolumeMetadataList &volumes, ConfigSubstitutionContext &config_substitutions)
Definition 3mf.cpp:2125
bool _extract_model_from_archive(mz_zip_archive &archive, const mz_zip_archive_file_stat &stat)
Definition 3mf.cpp:1000
std::vector< VolumeMetadata > VolumeMetadataList
Definition 3mf.cpp:546
bool _extract_model_config_from_archive(mz_zip_archive &archive, const mz_zip_archive_file_stat &stat, Model &model)
Definition 3mf.cpp:1373
@ UserModified
Definition SupportPoint.hpp:17
@ MODEL_PART
Definition Model.hpp:357
bool open_zip_reader(mz_zip_archive *zip, const std::string &fname)
Definition miniz_extension.cpp:119
bool close_zip_reader(mz_zip_archive *zip)
Definition miniz_extension.cpp:129
Definition 3mf.cpp:457

References _extract_model_config_from_archive(), _extract_model_from_archive(), _generate_volumes(), Slic3r::_3MF_Base::add_error(), Slic3r::ModelObject::add_instance(), Slic3r::Model::add_object(), Slic3r::ModelObject::clear_instances(), Slic3r::close_zip_reader(), Slic3r::ModelObject::config, Slic3r::ModelObject::delete_last_instance(), Slic3r::ModelVolume::Source::input_file, Slic3r::ModelObject::instances, Slic3r::_3MF_Importer::Metadata::key, Slic3r::ModelObject::layer_config_ranges, Slic3r::ModelObject::layer_height_profile, m_geometries, m_layer_config_ranges, m_layer_heights_profiles, m_model, m_name, m_objects, m_objects_metadata, m_sla_drain_holes, m_sla_support_points, m_version, MODEL_CONFIG_FILE, MODEL_EXTENSION, MODEL_FOLDER, Slic3r::MODEL_PART, Slic3r::ModelObject::name, Slic3r::ModelVolume::Source::object_idx, Slic3r::Model::objects, Slic3r::open_zip_reader(), Slic3r::LayerHeightProfile::set(), Slic3r::ModelConfig::set_deserialize(), Slic3r::ModelObject::sla_drain_holes, Slic3r::ModelObject::sla_points_status, Slic3r::ModelObject::sla_support_points, Slic3r::ModelVolume::source, Slic3r::_3MF_Importer::Geometry::triangles, Slic3r::ModelVolume::type(), Slic3r::sla::UserModified, Slic3r::_3MF_Importer::Metadata::value, Slic3r::ModelVolume::Source::volume_idx, and Slic3r::ModelObject::volumes.

Referenced by load_model_from_file().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _stop_xml_parser()

void Slic3r::_3MF_Importer::_stop_xml_parser ( const std::string & msg = std::string())
private
758 {
759 assert(! m_parse_error);
760 assert(m_parse_error_message.empty());
761 assert(m_xml_parser != nullptr);
762 m_parse_error = true;
764 XML_StopParser(m_xml_parser, false);
765 }
bool m_parse_error
Definition 3mf.cpp:576
std::string m_parse_error_message
Definition 3mf.cpp:577

References m_parse_error, m_parse_error_message, and m_xml_parser.

Referenced by _handle_end_config_xml_element(), _handle_end_model_xml_element(), _handle_start_config_xml_element(), and _handle_start_model_xml_element().

Here is the caller graph for this function:

◆ add_error()

void Slic3r::_3MF_Base::add_error ( const std::string & error)
inlineprotectedinherited
423{ m_errors.push_back(error); }
std::vector< std::string > m_errors
Definition 3mf.cpp:420

References m_errors.

Referenced by Slic3r::_3MF_Exporter::_add_build_to_model_stream(), Slic3r::_3MF_Exporter::_add_content_types_file_to_archive(), Slic3r::_3MF_Exporter::_add_layer_config_ranges_file_to_archive(), Slic3r::_3MF_Exporter::_add_layer_height_profile_file_to_archive(), Slic3r::_3MF_Exporter::_add_mesh_to_object_stream(), Slic3r::_3MF_Exporter::_add_model_config_file_to_archive(), Slic3r::_3MF_Exporter::_add_model_file_to_archive(), Slic3r::_3MF_Exporter::_add_object_to_model_stream(), Slic3r::_3MF_Exporter::_add_print_config_file_to_archive(), Slic3r::_3MF_Exporter::_add_relationships_file_to_archive(), Slic3r::_3MF_Exporter::_add_sla_drain_holes_file_to_archive(), Slic3r::_3MF_Exporter::_add_sla_support_points_file_to_archive(), Slic3r::_3MF_Exporter::_add_thumbnail_file_to_archive(), Slic3r::_3MF_Importer::_create_object_instance(), Slic3r::_3MF_Importer::_extract_layer_config_ranges_from_archive(), Slic3r::_3MF_Importer::_extract_layer_heights_profile_config_from_archive(), Slic3r::_3MF_Importer::_extract_model_config_from_archive(), Slic3r::_3MF_Importer::_extract_model_from_archive(), Slic3r::_3MF_Importer::_extract_print_config_from_archive(), Slic3r::_3MF_Importer::_extract_sla_drain_holes_from_archive(), Slic3r::_3MF_Importer::_extract_sla_support_points_from_archive(), Slic3r::_3MF_Importer::_generate_volumes(), Slic3r::_3MF_Importer::_handle_end_model(), Slic3r::_3MF_Importer::_handle_end_object(), Slic3r::_3MF_Importer::_handle_start_component(), Slic3r::_3MF_Importer::_handle_start_config_metadata(), Slic3r::_3MF_Importer::_handle_start_config_object(), Slic3r::_3MF_Importer::_handle_start_config_volume(), Slic3r::_3MF_Importer::_handle_start_config_volume_mesh(), Slic3r::_3MF_Importer::_handle_start_object(), Slic3r::_3MF_Importer::_load_model_from_file(), and Slic3r::_3MF_Exporter::_save_model_to_file().

Here is the caller graph for this function:

◆ clear_errors()

void Slic3r::_3MF_Base::clear_errors ( )
inlineprotectedinherited
424{ m_errors.clear(); }

References m_errors.

Referenced by Slic3r::_3MF_Importer::load_model_from_file(), and Slic3r::_3MF_Exporter::save_model_to_file().

Here is the caller graph for this function:

◆ load_model_from_file()

bool Slic3r::_3MF_Importer::load_model_from_file ( const std::string & filename,
Model & model,
DynamicPrintConfig & config,
ConfigSubstitutionContext & config_substitutions,
bool check_version )
723 {
724 m_version = 0;
728 m_check_version = check_version;
729 m_model = &model;
730 m_unit_factor = 1.0f;
731 m_curr_object.reset();
732 m_objects.clear();
733 m_objects_aliases.clear();
734 m_instances.clear();
735 m_geometries.clear();
736 m_curr_config.object_id = -1;
737 m_curr_config.volume_id = -1;
738 m_objects_metadata.clear();
740 m_layer_config_ranges.clear();
741 m_sla_support_points.clear();
742 m_curr_metadata_name.clear();
743 m_curr_characters.clear();
744 clear_errors();
745
746 return _load_model_from_file(filename, model, config, config_substitutions);
747 }
void clear_errors()
Definition 3mf.cpp:424
bool _load_model_from_file(const std::string &filename, Model &model, DynamicPrintConfig &config, ConfigSubstitutionContext &config_substitutions)
Definition 3mf.cpp:767

References _load_model_from_file(), Slic3r::_3MF_Base::clear_errors(), m_check_version, m_curr_characters, m_curr_config, m_curr_metadata_name, m_curr_object, m_fdm_supports_painting_version, m_geometries, m_instances, m_layer_config_ranges, m_layer_heights_profiles, m_mm_painting_version, m_model, m_objects, m_objects_aliases, m_objects_metadata, m_seam_painting_version, m_sla_support_points, m_unit_factor, and m_version.

Referenced by Slic3r::load_3mf().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_errors()

void Slic3r::_3MF_Base::log_errors ( )
inlineinherited
428 {
429 for (const std::string& error : m_errors)
430 BOOST_LOG_TRIVIAL(error) << error;
431 }

References m_errors.

Referenced by Slic3r::load_3mf(), and Slic3r::store_3mf().

Here is the caller graph for this function:

◆ parse_error()

bool Slic3r::_3MF_Importer::parse_error ( ) const
inlineprivate
606{ return m_parse_error; }

References m_parse_error.

◆ parse_error_message()

const char * Slic3r::_3MF_Importer::parse_error_message ( ) const
inlineprivate
607 {
608 return m_parse_error ?
609 // The error was signalled by the user code, not the expat parser.
610 (m_parse_error_message.empty() ? "Invalid 3MF format" : m_parse_error_message.c_str()) :
611 // The error was signalled by the expat parser.
612 XML_ErrorString(XML_GetErrorCode(m_xml_parser));
613 }

References m_parse_error, m_parse_error_message, and m_xml_parser.

◆ version()

unsigned int Slic3r::_3MF_Importer::version ( ) const
inline
600{ return m_version; }

References m_version.

Referenced by _extract_sla_drain_holes_from_archive(), _extract_sla_support_points_from_archive(), and Slic3r::load_3mf().

Here is the caller graph for this function:

Member Data Documentation

◆ m_check_version

bool Slic3r::_3MF_Importer::m_check_version
private

◆ m_curr_characters

std::string Slic3r::_3MF_Importer::m_curr_characters
private

◆ m_curr_config

◆ m_curr_metadata_name

std::string Slic3r::_3MF_Importer::m_curr_metadata_name
private

◆ m_curr_object

◆ m_errors

std::vector<std::string> Slic3r::_3MF_Base::m_errors
privateinherited

Referenced by add_error(), clear_errors(), and log_errors().

◆ m_fdm_supports_painting_version

unsigned int Slic3r::_3MF_Importer::m_fdm_supports_painting_version = 0
private

◆ m_geometries

IdToGeometryMap Slic3r::_3MF_Importer::m_geometries
private

◆ m_instances

InstancesList Slic3r::_3MF_Importer::m_instances
private

◆ m_layer_config_ranges

IdToLayerConfigRangesMap Slic3r::_3MF_Importer::m_layer_config_ranges
private

◆ m_layer_heights_profiles

IdToLayerHeightsProfileMap Slic3r::_3MF_Importer::m_layer_heights_profiles
private

◆ m_mm_painting_version

unsigned int Slic3r::_3MF_Importer::m_mm_painting_version = 0
private

◆ m_model

◆ m_name

std::string Slic3r::_3MF_Importer::m_name
private

◆ m_objects

◆ m_objects_aliases

IdToAliasesMap Slic3r::_3MF_Importer::m_objects_aliases
private

◆ m_objects_metadata

◆ m_parse_error

bool Slic3r::_3MF_Importer::m_parse_error { false }
private
576{ false };

Referenced by _stop_xml_parser(), parse_error(), and parse_error_message().

◆ m_parse_error_message

std::string Slic3r::_3MF_Importer::m_parse_error_message
private

◆ m_prusaslicer_generator_version

boost::optional<Semver> Slic3r::_3MF_Importer::m_prusaslicer_generator_version
private

◆ m_seam_painting_version

unsigned int Slic3r::_3MF_Importer::m_seam_painting_version = 0
private

◆ m_sla_drain_holes

IdToSlaDrainHolesMap Slic3r::_3MF_Importer::m_sla_drain_holes
private

◆ m_sla_support_points

IdToSlaSupportPointsMap Slic3r::_3MF_Importer::m_sla_support_points
private

◆ m_unit_factor

float Slic3r::_3MF_Importer::m_unit_factor
private

◆ m_version

unsigned int Slic3r::_3MF_Importer::m_version
private

◆ m_xml_parser


The documentation for this class was generated from the following file:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Format/3mf.cpp