mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 07:34:03 -06:00
Merge branch 'master' into tm_sla_printer_mirror
This commit is contained in:
commit
97cbb5344e
109 changed files with 25034 additions and 8806 deletions
|
@ -160,6 +160,8 @@ add_library(libslic3r STATIC
|
|||
MTUtils.hpp
|
||||
Zipper.hpp
|
||||
Zipper.cpp
|
||||
miniz_extension.hpp
|
||||
miniz_extension.cpp
|
||||
SLA/SLABoilerPlate.hpp
|
||||
SLA/SLABasePool.hpp
|
||||
SLA/SLABasePool.cpp
|
||||
|
@ -181,6 +183,7 @@ if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
|||
endif ()
|
||||
|
||||
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB)
|
||||
target_include_directories(libslic3r SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
|
||||
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBNEST2D_INCLUDES} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_link_libraries(libslic3r
|
||||
libnest2d
|
||||
|
|
|
@ -508,10 +508,12 @@ void ConfigBase::load_from_gcode_file(const std::string &file)
|
|||
boost::nowide::ifstream ifs(file);
|
||||
{
|
||||
const char slic3r_gcode_header[] = "; generated by Slic3r ";
|
||||
const char prusaslicer_gcode_header[] = "; generated by PrusaSlicer ";
|
||||
std::string firstline;
|
||||
std::getline(ifs, firstline);
|
||||
if (strncmp(slic3r_gcode_header, firstline.c_str(), strlen(slic3r_gcode_header)) != 0)
|
||||
throw std::runtime_error("Not a Slic3r generated g-code.");
|
||||
if (strncmp(slic3r_gcode_header, firstline.c_str(), strlen(slic3r_gcode_header)) != 0 &&
|
||||
strncmp(prusaslicer_gcode_header, firstline.c_str(), strlen(prusaslicer_gcode_header)) != 0)
|
||||
throw std::runtime_error("Not a PrusaSlicer / Slic3r PE generated g-code.");
|
||||
}
|
||||
ifs.seekg(0, ifs.end);
|
||||
auto file_length = ifs.tellg();
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
#include <expat.h>
|
||||
#include <Eigen/Dense>
|
||||
#include <miniz/miniz_zip.h>
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
// VERSION NUMBERS
|
||||
// 0 : .3mf, files saved by older slic3r or other applications. No version definition in them.
|
||||
|
@ -247,7 +248,10 @@ namespace Slic3r {
|
|||
|
||||
struct CurrentObject
|
||||
{
|
||||
// ID of the object inside the 3MF file, 1 based.
|
||||
int id;
|
||||
// Index of the ModelObject in its respective Model, zero based.
|
||||
int model_object_idx;
|
||||
Geometry geometry;
|
||||
ModelObject* object;
|
||||
ComponentsList components;
|
||||
|
@ -260,6 +264,7 @@ namespace Slic3r {
|
|||
void reset()
|
||||
{
|
||||
id = -1;
|
||||
model_object_idx = -1;
|
||||
geometry.reset();
|
||||
object = nullptr;
|
||||
components.clear();
|
||||
|
@ -319,7 +324,8 @@ namespace Slic3r {
|
|||
VolumeMetadataList volumes;
|
||||
};
|
||||
|
||||
typedef std::map<int, ModelObject*> IdToModelObjectMap;
|
||||
// Map from a 1 based 3MF object ID to a 0 based ModelObject index inside m_model->objects.
|
||||
typedef std::map<int, int> IdToModelObjectMap;
|
||||
typedef std::map<int, ComponentsList> IdToAliasesMap;
|
||||
typedef std::vector<Instance> InstancesList;
|
||||
typedef std::map<int, ObjectMetadata> IdToMetadataMap;
|
||||
|
@ -497,10 +503,8 @@ namespace Slic3r {
|
|||
{
|
||||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
mz_bool res = mz_zip_reader_init_file(&archive, filename.c_str(), 0);
|
||||
if (res == 0)
|
||||
{
|
||||
|
||||
if (!open_zip_reader(&archive, filename)) {
|
||||
add_error("Unable to open the file");
|
||||
return false;
|
||||
}
|
||||
|
@ -524,7 +528,7 @@ namespace Slic3r {
|
|||
// valid model name -> extract model
|
||||
if (!_extract_model_from_archive(archive, stat))
|
||||
{
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
add_error("Archive does not contain a valid model");
|
||||
return false;
|
||||
}
|
||||
|
@ -560,7 +564,7 @@ namespace Slic3r {
|
|||
// extract slic3r model config file
|
||||
if (!_extract_model_config_from_archive(archive, stat, model))
|
||||
{
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
add_error("Archive does not contain a valid model config");
|
||||
return false;
|
||||
}
|
||||
|
@ -568,10 +572,11 @@ namespace Slic3r {
|
|||
}
|
||||
}
|
||||
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
|
||||
for (const IdToModelObjectMap::value_type& object : m_objects)
|
||||
{
|
||||
ModelObject *model_object = m_model->objects[object.second];
|
||||
ObjectMetadata::VolumeMetadataList volumes;
|
||||
ObjectMetadata::VolumeMetadataList* volumes_ptr = nullptr;
|
||||
|
||||
|
@ -582,14 +587,16 @@ namespace Slic3r {
|
|||
return false;
|
||||
}
|
||||
|
||||
IdToLayerHeightsProfileMap::iterator obj_layer_heights_profile = m_layer_heights_profiles.find(object.first);
|
||||
// m_layer_heights_profiles are indexed by a 1 based model object index.
|
||||
IdToLayerHeightsProfileMap::iterator obj_layer_heights_profile = m_layer_heights_profiles.find(object.second + 1);
|
||||
if (obj_layer_heights_profile != m_layer_heights_profiles.end())
|
||||
object.second->layer_height_profile = obj_layer_heights_profile->second;
|
||||
model_object->layer_height_profile = obj_layer_heights_profile->second;
|
||||
|
||||
IdToSlaSupportPointsMap::iterator obj_sla_support_points = m_sla_support_points.find(object.first);
|
||||
// m_sla_support_points are indexed by a 1 based model object index.
|
||||
IdToSlaSupportPointsMap::iterator obj_sla_support_points = m_sla_support_points.find(object.second + 1);
|
||||
if (obj_sla_support_points != m_sla_support_points.end() && !obj_sla_support_points->second.empty()) {
|
||||
object.second->sla_support_points = obj_sla_support_points->second;
|
||||
object.second->sla_points_status = sla::PointsStatus::UserModified;
|
||||
model_object->sla_support_points = obj_sla_support_points->second;
|
||||
model_object->sla_points_status = sla::PointsStatus::UserModified;
|
||||
}
|
||||
|
||||
IdToMetadataMap::iterator obj_metadata = m_objects_metadata.find(object.first);
|
||||
|
@ -601,9 +608,9 @@ namespace Slic3r {
|
|||
for (const Metadata& metadata : obj_metadata->second.metadata)
|
||||
{
|
||||
if (metadata.key == "name")
|
||||
object.second->name = metadata.value;
|
||||
model_object->name = metadata.value;
|
||||
else
|
||||
object.second->config.set_deserialize(metadata.key, metadata.value);
|
||||
model_object->config.set_deserialize(metadata.key, metadata.value);
|
||||
}
|
||||
|
||||
// select object's detected volumes
|
||||
|
@ -620,7 +627,7 @@ namespace Slic3r {
|
|||
volumes_ptr = &volumes;
|
||||
}
|
||||
|
||||
if (!_generate_volumes(*object.second, obj_geometry->second, *volumes_ptr))
|
||||
if (!_generate_volumes(*model_object, obj_geometry->second, *volumes_ptr))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -828,19 +835,20 @@ namespace Slic3r {
|
|||
|
||||
if (version == 0) {
|
||||
for (unsigned int i=0; i<object_data_points.size(); i+=3)
|
||||
sla_support_points.emplace_back(std::atof(object_data_points[i+0].c_str()),
|
||||
std::atof(object_data_points[i+1].c_str()),
|
||||
std::atof(object_data_points[i+2].c_str()),
|
||||
sla_support_points.emplace_back(float(std::atof(object_data_points[i+0].c_str())),
|
||||
float(std::atof(object_data_points[i+1].c_str())),
|
||||
float(std::atof(object_data_points[i+2].c_str())),
|
||||
0.4f,
|
||||
false);
|
||||
}
|
||||
if (version == 1) {
|
||||
for (unsigned int i=0; i<object_data_points.size(); i+=5)
|
||||
sla_support_points.emplace_back(std::atof(object_data_points[i+0].c_str()),
|
||||
std::atof(object_data_points[i+1].c_str()),
|
||||
std::atof(object_data_points[i+2].c_str()),
|
||||
std::atof(object_data_points[i+3].c_str()),
|
||||
std::atof(object_data_points[i+4].c_str()));
|
||||
sla_support_points.emplace_back(float(std::atof(object_data_points[i+0].c_str())),
|
||||
float(std::atof(object_data_points[i+1].c_str())),
|
||||
float(std::atof(object_data_points[i+2].c_str())),
|
||||
float(std::atof(object_data_points[i+3].c_str())),
|
||||
//FIXME storing boolean as 0 / 1 and importing it as float.
|
||||
std::abs(std::atof(object_data_points[i+4].c_str()) - 1.) < EPSILON);
|
||||
}
|
||||
|
||||
if (!sla_support_points.empty())
|
||||
|
@ -1029,8 +1037,9 @@ namespace Slic3r {
|
|||
// deletes all non-built or non-instanced objects
|
||||
for (const IdToModelObjectMap::value_type& object : m_objects)
|
||||
{
|
||||
if ((object.second != nullptr) && (object.second->instances.size() == 0))
|
||||
m_model->delete_object(object.second);
|
||||
ModelObject *model_object = m_model->objects[object.second];
|
||||
if ((model_object != nullptr) && (model_object->instances.size() == 0))
|
||||
m_model->delete_object(model_object);
|
||||
}
|
||||
|
||||
// applies instances' matrices
|
||||
|
@ -1070,6 +1079,7 @@ namespace Slic3r {
|
|||
if (is_valid_object_type(get_attribute_value_string(attributes, num_attributes, TYPE_ATTR)))
|
||||
{
|
||||
// create new object (it may be removed later if no instances are generated from it)
|
||||
m_curr_object.model_object_idx = (int)m_model->objects.size();
|
||||
m_curr_object.object = m_model->add_object();
|
||||
if (m_curr_object.object == nullptr)
|
||||
{
|
||||
|
@ -1121,7 +1131,7 @@ namespace Slic3r {
|
|||
// stores the object for later use
|
||||
if (m_objects.find(m_curr_object.id) == m_objects.end())
|
||||
{
|
||||
m_objects.insert(IdToModelObjectMap::value_type(m_curr_object.id, m_curr_object.object));
|
||||
m_objects.insert(IdToModelObjectMap::value_type(m_curr_object.id, m_curr_object.model_object_idx));
|
||||
m_objects_aliases.insert(IdToAliasesMap::value_type(m_curr_object.id, ComponentsList(1, Component(m_curr_object.id)))); // aliases itself
|
||||
}
|
||||
else
|
||||
|
@ -1328,14 +1338,14 @@ namespace Slic3r {
|
|||
// aliasing to itself
|
||||
|
||||
IdToModelObjectMap::iterator object_item = m_objects.find(object_id);
|
||||
if ((object_item == m_objects.end()) || (object_item->second == nullptr))
|
||||
if ((object_item == m_objects.end()) || (object_item->second == -1))
|
||||
{
|
||||
add_error("Found invalid object");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelInstance* instance = object_item->second->add_instance();
|
||||
ModelInstance* instance = m_model->objects[object_item->second]->add_instance();
|
||||
if (instance == nullptr)
|
||||
{
|
||||
add_error("Unable to add object instance");
|
||||
|
@ -1600,8 +1610,6 @@ namespace Slic3r {
|
|||
typedef std::vector<BuildItem> BuildItemsList;
|
||||
typedef std::map<int, ObjectData> IdToObjectDataMap;
|
||||
|
||||
IdToObjectDataMap m_objects_data;
|
||||
|
||||
public:
|
||||
bool save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config);
|
||||
|
||||
|
@ -1609,14 +1617,14 @@ namespace Slic3r {
|
|||
bool _save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config);
|
||||
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
|
||||
bool _add_relationships_file_to_archive(mz_zip_archive& archive);
|
||||
bool _add_model_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||
bool _add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data);
|
||||
bool _add_object_to_model_stream(std::stringstream& stream, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets);
|
||||
bool _add_mesh_to_object_stream(std::stringstream& stream, ModelObject& object, VolumeToOffsetsMap& volumes_offsets);
|
||||
bool _add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items);
|
||||
bool _add_layer_height_profile_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||
bool _add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||
bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config);
|
||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model);
|
||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data);
|
||||
};
|
||||
|
||||
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config)
|
||||
|
@ -1630,83 +1638,92 @@ namespace Slic3r {
|
|||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
m_objects_data.clear();
|
||||
|
||||
mz_bool res = mz_zip_writer_init_file(&archive, filename.c_str(), 0);
|
||||
if (res == 0)
|
||||
{
|
||||
if (!open_zip_writer(&archive, filename)) {
|
||||
add_error("Unable to open the file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// adds content types file
|
||||
// Adds content types file ("[Content_Types].xml";).
|
||||
// The content of this file is the same for each PrusaSlicer 3mf.
|
||||
if (!_add_content_types_file_to_archive(archive))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// adds relationships file
|
||||
// Adds relationships file ("_rels/.rels").
|
||||
// The content of this file is the same for each PrusaSlicer 3mf.
|
||||
// The relationshis file contains a reference to the geometry file "3D/3dmodel.model", the name was chosen to be compatible with CURA.
|
||||
if (!_add_relationships_file_to_archive(archive))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// adds model file
|
||||
if (!_add_model_file_to_archive(archive, model))
|
||||
// Adds model file ("3D/3dmodel.model").
|
||||
// This is the one and only file that contains all the geometry (vertices and triangles) of all ModelVolumes.
|
||||
IdToObjectDataMap objects_data;
|
||||
if (!_add_model_file_to_archive(archive, model, objects_data))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// adds layer height profile file
|
||||
// Adds layer height profile file ("Metadata/Slic3r_PE_layer_heights_profile.txt").
|
||||
// All layer height profiles of all ModelObjects are stored here, indexed by 1 based index of the ModelObject in Model.
|
||||
// The index differes from the index of an object ID of an object instance of a 3MF file!
|
||||
if (!_add_layer_height_profile_file_to_archive(archive, model))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// adds sla support points file
|
||||
// Adds sla support points file ("Metadata/Slic3r_PE_sla_support_points.txt").
|
||||
// All sla support points of all ModelObjects are stored here, indexed by 1 based index of the ModelObject in Model.
|
||||
// The index differes from the index of an object ID of an object instance of a 3MF file!
|
||||
if (!_add_sla_support_points_file_to_archive(archive, model))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// adds slic3r print config file
|
||||
// Adds slic3r print config file ("Metadata/Slic3r_PE.config").
|
||||
// This file contains the content of FullPrintConfing / SLAFullPrintConfig.
|
||||
if (config != nullptr)
|
||||
{
|
||||
if (!_add_print_config_file_to_archive(archive, *config))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// adds slic3r model config file
|
||||
if (!_add_model_config_file_to_archive(archive, model))
|
||||
// Adds slic3r model config file ("Metadata/Slic3r_PE_model.config").
|
||||
// This file contains all the attributes of all ModelObjects and their ModelVolumes (names, parameter overrides).
|
||||
// As there is just a single Indexed Triangle Set data stored per ModelObject, offsets of volumes into their respective Indexed Triangle Set data
|
||||
// is stored here as well.
|
||||
if (!_add_model_config_file_to_archive(archive, model, objects_data))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mz_zip_writer_finalize_archive(&archive))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
add_error("Unable to finalize the archive");
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1750,7 +1767,7 @@ namespace Slic3r {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Exporter::_add_model_file_to_archive(mz_zip_archive& archive, Model& model)
|
||||
bool _3MF_Exporter::_add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data)
|
||||
{
|
||||
std::stringstream stream;
|
||||
// https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
|
||||
|
@ -1763,17 +1780,24 @@ namespace Slic3r {
|
|||
stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_3MF_VERSION << "\">" << VERSION_3MF << "</" << METADATA_TAG << ">\n";
|
||||
stream << " <" << RESOURCES_TAG << ">\n";
|
||||
|
||||
// Instance transformations, indexed by the 3MF object ID (which is a linear serialization of all instances of all ModelObjects).
|
||||
BuildItemsList build_items;
|
||||
|
||||
// The object_id here is a one based identifier of the first instance of a ModelObject in the 3MF file, where
|
||||
// all the object instances of all ModelObjects are stored and indexed in a 1 based linear fashion.
|
||||
// Therefore the list of object_ids here may not be continuous.
|
||||
unsigned int object_id = 1;
|
||||
for (ModelObject* obj : model.objects)
|
||||
{
|
||||
if (obj == nullptr)
|
||||
continue;
|
||||
|
||||
// Index of an object in the 3MF file corresponding to the 1st instance of a ModelObject.
|
||||
unsigned int curr_id = object_id;
|
||||
IdToObjectDataMap::iterator object_it = m_objects_data.insert(IdToObjectDataMap::value_type(curr_id, ObjectData(obj))).first;
|
||||
|
||||
IdToObjectDataMap::iterator object_it = objects_data.insert(IdToObjectDataMap::value_type(curr_id, ObjectData(obj))).first;
|
||||
// Store geometry of all ModelVolumes contained in a single ModelObject into a single 3MF indexed triangle set object.
|
||||
// object_it->second.volumes_offsets will contain the offsets of the ModelVolumes in that single indexed triangle set.
|
||||
// object_id will be increased to point to the 1st instance of the next ModelObject.
|
||||
if (!_add_object_to_model_stream(stream, object_id, *obj, build_items, object_it->second.volumes_offsets))
|
||||
{
|
||||
add_error("Unable to add object to archive");
|
||||
|
@ -1783,6 +1807,7 @@ namespace Slic3r {
|
|||
|
||||
stream << " </" << RESOURCES_TAG << ">\n";
|
||||
|
||||
// Store the transformations of all the ModelInstances of all ModelObjects, indexed in a linear fashion.
|
||||
if (!_add_build_to_model_stream(stream, build_items))
|
||||
{
|
||||
add_error("Unable to add build to archive");
|
||||
|
@ -1807,6 +1832,7 @@ namespace Slic3r {
|
|||
unsigned int id = 0;
|
||||
for (const ModelInstance* instance : object.instances)
|
||||
{
|
||||
assert(instance != nullptr);
|
||||
if (instance == nullptr)
|
||||
continue;
|
||||
|
||||
|
@ -1829,6 +1855,8 @@ namespace Slic3r {
|
|||
}
|
||||
|
||||
Transform3d t = instance->get_matrix();
|
||||
// instance_id is just a 1 indexed index in build_items.
|
||||
assert(instance_id == build_items.size() + 1);
|
||||
build_items.emplace_back(instance_id, t);
|
||||
|
||||
stream << " </" << OBJECT_TAG << ">\n";
|
||||
|
@ -2045,13 +2073,13 @@ namespace Slic3r {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model)
|
||||
bool _3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
stream << "<" << CONFIG_TAG << ">\n";
|
||||
|
||||
for (const IdToObjectDataMap::value_type& obj_metadata : m_objects_data)
|
||||
for (const IdToObjectDataMap::value_type& obj_metadata : objects_data)
|
||||
{
|
||||
const ModelObject* obj = obj_metadata.second.object;
|
||||
if (obj != nullptr)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <string.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <expat/expat.h>
|
||||
#include <expat.h>
|
||||
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <miniz/miniz_zip.h>
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
#if 0
|
||||
// Enable debugging and assert in this file.
|
||||
|
@ -717,14 +717,14 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
|||
if (stat.m_uncomp_size == 0)
|
||||
{
|
||||
printf("Found invalid size\n");
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(nullptr); // encoding
|
||||
if (!parser) {
|
||||
printf("Couldn't allocate memory for parser\n");
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -737,7 +737,7 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
|||
if (parser_buffer == nullptr)
|
||||
{
|
||||
printf("Unable to create buffer\n");
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -745,14 +745,14 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
|||
if (res == 0)
|
||||
{
|
||||
printf("Error while reading model data to buffer\n");
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!XML_ParseBuffer(parser, (int)stat.m_uncomp_size, 1))
|
||||
{
|
||||
printf("Error (%s) while parsing xml file at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -774,8 +774,7 @@ bool load_amf_archive(const char *path, DynamicPrintConfig *config, Model *model
|
|||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
mz_bool res = mz_zip_reader_init_file(&archive, path, 0);
|
||||
if (res == 0)
|
||||
if (!open_zip_reader(&archive, path))
|
||||
{
|
||||
printf("Unable to init zip reader\n");
|
||||
return false;
|
||||
|
@ -793,7 +792,7 @@ bool load_amf_archive(const char *path, DynamicPrintConfig *config, Model *model
|
|||
{
|
||||
if (!extract_model_from_archive(archive, stat, config, model, version))
|
||||
{
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
printf("Archive does not contain a valid model");
|
||||
return false;
|
||||
}
|
||||
|
@ -814,7 +813,7 @@ bool load_amf_archive(const char *path, DynamicPrintConfig *config, Model *model
|
|||
}
|
||||
#endif // forward compatibility
|
||||
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -854,9 +853,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
|||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
mz_bool res = mz_zip_writer_init_file(&archive, export_path.c_str(), 0);
|
||||
if (res == 0)
|
||||
return false;
|
||||
if (!open_zip_writer(&archive, export_path)) return false;
|
||||
|
||||
std::stringstream stream;
|
||||
// https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
|
||||
|
@ -1018,19 +1015,19 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
|||
|
||||
if (!mz_zip_writer_add_mem(&archive, internal_amf_filename.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(export_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mz_zip_writer_finalize_archive(&archive))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(export_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_zip_writer_end(&archive);
|
||||
close_zip_writer(&archive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
#include <miniz/miniz_zip.h>
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
|
@ -298,10 +299,11 @@ bool load_prus(const char *path, Model *model)
|
|||
{
|
||||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
mz_bool res = mz_zip_reader_init_file(&archive, path, 0);
|
||||
|
||||
size_t n_models_initial = model->objects.size();
|
||||
mz_bool res = MZ_FALSE;
|
||||
try {
|
||||
if (res == MZ_FALSE)
|
||||
if (!open_zip_reader(&archive, path))
|
||||
throw std::runtime_error(std::string("Unable to init zip reader for ") + path);
|
||||
std::vector<char> scene_xml_data;
|
||||
// For grouping multiple STLs into a single ModelObject for multi-material prints.
|
||||
|
@ -326,11 +328,11 @@ bool load_prus(const char *path, Model *model)
|
|||
}
|
||||
}
|
||||
} catch (std::exception &ex) {
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
mz_zip_reader_end(&archive);
|
||||
close_zip_reader(&archive);
|
||||
return model->objects.size() > n_models_initial;
|
||||
}
|
||||
|
||||
|
|
|
@ -781,6 +781,8 @@ void GCode::_do_export(Print &print, FILE *file)
|
|||
m_placeholder_parser.set("initial_tool", initial_extruder_id);
|
||||
m_placeholder_parser.set("initial_extruder", initial_extruder_id);
|
||||
m_placeholder_parser.set("current_extruder", initial_extruder_id);
|
||||
//Set variable for total layer count so it can be used in custom gcode.
|
||||
m_placeholder_parser.set("total_layer_count", m_layer_count);
|
||||
// Useful for sequential prints.
|
||||
m_placeholder_parser.set("current_object_idx", 0);
|
||||
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
|
||||
|
|
|
@ -327,7 +327,10 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
|
|||
LayerTools <_prev = m_layer_tools[j - 1];
|
||||
LayerTools <_next = m_layer_tools[j + 1];
|
||||
assert(! lt_prev.extruders.empty() && ! lt_next.extruders.empty());
|
||||
assert(lt_prev.extruders.back() == lt_next.extruders.front());
|
||||
// FIXME: Following assert tripped when running combine_infill.t. I decided to comment it out for now.
|
||||
// If it is a bug, it's likely not critical, because this code is unchanged for a long time. It might
|
||||
// still be worth looking into it more and decide if it is a bug or an obsolete assert.
|
||||
//assert(lt_prev.extruders.back() == lt_next.extruders.front());
|
||||
lt_extra.has_wipe_tower = true;
|
||||
lt_extra.extruders.push_back(lt_next.extruders.front());
|
||||
lt_extra.wipe_tower_partitions = lt_next.wipe_tower_partitions;
|
||||
|
|
|
@ -1180,7 +1180,6 @@ Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation,
|
|||
|
||||
Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& rotation_matrix)
|
||||
{
|
||||
#if ENABLE_NEW_EULER_ANGLES
|
||||
// reference: http://www.gregslabaugh.net/publications/euler.pdf
|
||||
Vec3d angles1 = Vec3d::Zero();
|
||||
Vec3d angles2 = Vec3d::Zero();
|
||||
|
@ -1219,40 +1218,7 @@ Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>&
|
|||
double min_2 = angles2.cwiseAbs().minCoeff();
|
||||
bool use_1 = (min_1 < min_2) || (is_approx(min_1, min_2) && (angles1.norm() <= angles2.norm()));
|
||||
|
||||
Vec3d angles = use_1 ? angles1 : angles2;
|
||||
#else
|
||||
auto y_only = [](const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& matrix) -> bool {
|
||||
return (matrix(0, 1) == 0.0) && (matrix(1, 0) == 0.0) && (matrix(1, 1) == 1.0) && (matrix(1, 2) == 0.0) && (matrix(2, 1) == 0.0);
|
||||
};
|
||||
|
||||
// see: https://www.learnopencv.com/rotation-matrix-to-euler-angles/
|
||||
double cy_abs = ::sqrt(sqr(rotation_matrix(0, 0)) + sqr(rotation_matrix(1, 0)));
|
||||
|
||||
Vec3d angles = Vec3d::Zero();
|
||||
|
||||
if (cy_abs >= 1e-6)
|
||||
{
|
||||
angles(0) = ::atan2(rotation_matrix(2, 1), rotation_matrix(2, 2));
|
||||
angles(1) = ::atan2(-rotation_matrix(2, 0), cy_abs);
|
||||
angles(2) = ::atan2(rotation_matrix(1, 0), rotation_matrix(0, 0));
|
||||
|
||||
// this is an hack to try to avoid this function to return "strange" values due to gimbal lock
|
||||
if (y_only(rotation_matrix) && (angles(0) == (double)PI) && (angles(2) == (double)PI))
|
||||
{
|
||||
angles(0) = 0.0;
|
||||
angles(1) = ::atan2(rotation_matrix(2, 0), cy_abs) - (double)PI;
|
||||
angles(2) = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angles(0) = 0.0;
|
||||
angles(1) = ::atan2(-rotation_matrix(2, 0), cy_abs);
|
||||
angles(2) = (angles(1) >= 0.0) ? ::atan2(rotation_matrix(1, 2), rotation_matrix(1, 1)) : ::atan2(-rotation_matrix(1, 2), rotation_matrix(1, 1));
|
||||
}
|
||||
#endif // ENABLE_NEW_EULER_ANGLES
|
||||
|
||||
return angles;
|
||||
return use_1 ? angles1 : angles2;
|
||||
}
|
||||
|
||||
Vec3d extract_euler_angles(const Transform3d& transform)
|
||||
|
@ -1288,18 +1254,8 @@ void Transformation::Flags::set(bool dont_translate, bool dont_rotate, bool dont
|
|||
}
|
||||
|
||||
Transformation::Transformation()
|
||||
#if !ENABLE_VOLUMES_CENTERING_FIXES
|
||||
: m_offset(Vec3d::Zero())
|
||||
, m_rotation(Vec3d::Zero())
|
||||
, m_scaling_factor(Vec3d::Ones())
|
||||
, m_mirror(Vec3d::Ones())
|
||||
, m_matrix(Transform3d::Identity())
|
||||
, m_dirty(false)
|
||||
#endif // !ENABLE_VOLUMES_CENTERING_FIXES
|
||||
{
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
reset();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
}
|
||||
|
||||
Transformation::Transformation(const Transform3d& transform)
|
||||
|
@ -1420,7 +1376,6 @@ void Transformation::set_from_transform(const Transform3d& transform)
|
|||
// std::cout << "something went wrong in extracting data from matrix" << std::endl;
|
||||
}
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void Transformation::reset()
|
||||
{
|
||||
m_offset = Vec3d::Zero();
|
||||
|
@ -1430,7 +1385,6 @@ void Transformation::reset()
|
|||
m_matrix = Transform3d::Identity();
|
||||
m_dirty = false;
|
||||
}
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
|
||||
const Transform3d& Transformation::get_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
|
||||
{
|
||||
|
|
|
@ -253,9 +253,7 @@ public:
|
|||
|
||||
void set_from_transform(const Transform3d& transform);
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void reset();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
|
||||
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const;
|
||||
|
||||
|
|
|
@ -503,9 +503,7 @@ void Model::convert_multipart_object(unsigned int max_extruders)
|
|||
{
|
||||
new_v->name = o->name;
|
||||
new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders));
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
new_v->translate(-o->origin_translation);
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -681,9 +679,7 @@ ModelVolume* ModelObject::add_volume(const TriangleMesh &mesh)
|
|||
{
|
||||
ModelVolume* v = new ModelVolume(this, mesh);
|
||||
this->volumes.push_back(v);
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
v->center_geometry();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
this->invalidate_bounding_box();
|
||||
return v;
|
||||
}
|
||||
|
@ -692,9 +688,7 @@ ModelVolume* ModelObject::add_volume(TriangleMesh &&mesh)
|
|||
{
|
||||
ModelVolume* v = new ModelVolume(this, std::move(mesh));
|
||||
this->volumes.push_back(v);
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
v->center_geometry();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
this->invalidate_bounding_box();
|
||||
return v;
|
||||
}
|
||||
|
@ -703,9 +697,7 @@ ModelVolume* ModelObject::add_volume(const ModelVolume &other)
|
|||
{
|
||||
ModelVolume* v = new ModelVolume(this, other);
|
||||
this->volumes.push_back(v);
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
v->center_geometry();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
this->invalidate_bounding_box();
|
||||
return v;
|
||||
}
|
||||
|
@ -714,9 +706,7 @@ ModelVolume* ModelObject::add_volume(const ModelVolume &other, TriangleMesh &&me
|
|||
{
|
||||
ModelVolume* v = new ModelVolume(this, other, std::move(mesh));
|
||||
this->volumes.push_back(v);
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
v->center_geometry();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
this->invalidate_bounding_box();
|
||||
return v;
|
||||
}
|
||||
|
@ -727,7 +717,6 @@ void ModelObject::delete_volume(size_t idx)
|
|||
delete *i;
|
||||
this->volumes.erase(i);
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
if (this->volumes.size() == 1)
|
||||
{
|
||||
// only one volume left
|
||||
|
@ -743,24 +732,6 @@ void ModelObject::delete_volume(size_t idx)
|
|||
v->set_transformation(t);
|
||||
v->set_new_unique_id();
|
||||
}
|
||||
#else
|
||||
if (this->volumes.size() == 1)
|
||||
{
|
||||
// only one volume left
|
||||
// center it and update the instances accordingly
|
||||
// rationale: the volume may be shifted with respect to the object center and this may lead to wrong rotation and scaling
|
||||
// when modifying the instance matrix of the derived GLVolume
|
||||
ModelVolume* v = this->volumes.front();
|
||||
v->center_geometry();
|
||||
const Vec3d& vol_offset = v->get_offset();
|
||||
for (ModelInstance* inst : this->instances)
|
||||
{
|
||||
inst->set_offset(inst->get_offset() + inst->get_matrix(true) * vol_offset);
|
||||
}
|
||||
v->set_offset(Vec3d::Zero());
|
||||
v->set_new_unique_id();
|
||||
}
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
|
||||
this->invalidate_bounding_box();
|
||||
}
|
||||
|
@ -903,28 +874,15 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
|
|||
if (! m_raw_bounding_box_valid) {
|
||||
m_raw_bounding_box_valid = true;
|
||||
m_raw_bounding_box.reset();
|
||||
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
if (this->instances.empty())
|
||||
throw std::invalid_argument("Can't call raw_bounding_box() with no instances");
|
||||
|
||||
const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true);
|
||||
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
for (const ModelVolume *v : this->volumes)
|
||||
if (v->is_model_part()) {
|
||||
#if !ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
if (this->instances.empty())
|
||||
throw std::invalid_argument("Can't call raw_bounding_box() with no instances");
|
||||
#endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
|
||||
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
m_raw_bounding_box.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix()));
|
||||
#else
|
||||
// unmaintaned
|
||||
assert(false);
|
||||
// vol_mesh.transform(v->get_matrix());
|
||||
// m_raw_bounding_box_valid.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true));
|
||||
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
}
|
||||
{
|
||||
if (v->is_model_part())
|
||||
m_raw_bounding_box.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix()));
|
||||
}
|
||||
}
|
||||
return m_raw_bounding_box;
|
||||
}
|
||||
|
@ -933,22 +891,11 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
|
|||
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
const Transform3d& inst_matrix = this->instances[instance_idx]->get_transformation().get_matrix(dont_translate);
|
||||
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
for (ModelVolume *v : this->volumes)
|
||||
{
|
||||
if (v->is_model_part())
|
||||
{
|
||||
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
bb.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix()));
|
||||
#else
|
||||
// not maintained
|
||||
assert(false);
|
||||
//mesh.transform(v->get_matrix());
|
||||
//bb.merge(this->instances[instance_idx]->transform_mesh_bounding_box(mesh, dont_translate));
|
||||
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
}
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
@ -1007,22 +954,11 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const
|
|||
return hull;
|
||||
}
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void ModelObject::center_around_origin(bool include_modifiers)
|
||||
#else
|
||||
void ModelObject::center_around_origin()
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
{
|
||||
// calculate the displacements needed to
|
||||
// center this object around the origin
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
BoundingBoxf3 bb = include_modifiers ? full_raw_mesh_bounding_box() : raw_mesh_bounding_box();
|
||||
#else
|
||||
BoundingBoxf3 bb;
|
||||
for (ModelVolume *v : this->volumes)
|
||||
if (v->is_model_part())
|
||||
bb.merge(v->mesh.bounding_box());
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
|
||||
// Shift is the vector from the center of the bounding box to the origin
|
||||
Vec3d shift = -bb.center();
|
||||
|
@ -1309,9 +1245,6 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
|||
for (const ModelInstance *model_instance : this->instances)
|
||||
new_object->add_instance(*model_instance);
|
||||
ModelVolume* new_vol = new_object->add_volume(*volume, std::move(*mesh));
|
||||
#if !ENABLE_VOLUMES_CENTERING_FIXES
|
||||
new_vol->center_geometry();
|
||||
#endif // !ENABLE_VOLUMES_CENTERING_FIXES
|
||||
|
||||
for (ModelInstance* model_instance : new_object->instances)
|
||||
{
|
||||
|
@ -1605,7 +1538,6 @@ bool ModelVolume::is_splittable() const
|
|||
|
||||
void ModelVolume::center_geometry()
|
||||
{
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
Vec3d shift = mesh.bounding_box().center();
|
||||
if (!shift.isApprox(Vec3d::Zero()))
|
||||
{
|
||||
|
@ -1613,12 +1545,6 @@ void ModelVolume::center_geometry()
|
|||
m_convex_hull.translate(-(float)shift(0), -(float)shift(1), -(float)shift(2));
|
||||
translate(shift);
|
||||
}
|
||||
#else
|
||||
Vec3d shift = -mesh.bounding_box().center();
|
||||
mesh.translate((float)shift(0), (float)shift(1), (float)shift(2));
|
||||
m_convex_hull.translate((float)shift(0), (float)shift(1), (float)shift(2));
|
||||
translate(-shift);
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
}
|
||||
|
||||
void ModelVolume::calculate_convex_hull()
|
||||
|
|
|
@ -243,11 +243,8 @@ public:
|
|||
// This method is used by the auto arrange function.
|
||||
Polygon convex_hull_2d(const Transform3d &trafo_instance) const;
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void center_around_origin(bool include_modifiers = true);
|
||||
#else
|
||||
void center_around_origin();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
|
||||
void ensure_on_bed();
|
||||
void translate_instances(const Vec3d& vector);
|
||||
void translate_instance(size_t instance_idx, const Vec3d& vector);
|
||||
|
|
|
@ -51,7 +51,7 @@ void Print::reload_object(size_t /* idx */)
|
|||
this->invalidate_all_steps();
|
||||
/* TODO: this method should check whether the per-object config and per-material configs
|
||||
have changed in such a way that regions need to be rearranged or we can just apply
|
||||
the diff and invalidate something. Same logic as apply_config()
|
||||
the diff and invalidate something. Same logic as apply()
|
||||
For now we just re-add all objects since we haven't implemented this incremental logic yet.
|
||||
This should also check whether object volumes (parts) have changed. */
|
||||
// collect all current model objects
|
||||
|
@ -83,7 +83,7 @@ PrintRegion* Print::add_region(const PrintRegionConfig &config)
|
|||
return m_regions.back();
|
||||
}
|
||||
|
||||
// Called by Print::apply_config().
|
||||
// Called by Print::apply().
|
||||
// This method only accepts PrintConfig option keys.
|
||||
bool Print::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
|
||||
{
|
||||
|
@ -422,10 +422,32 @@ void Print::add_model_object(ModelObject* model_object, int idx)
|
|||
}
|
||||
}
|
||||
|
||||
bool Print::apply_config(DynamicPrintConfig config)
|
||||
// This function is only called through the Perl-C++ binding from the unit tests, should be
|
||||
// removed when unit tests are rewritten to C++.
|
||||
bool Print::apply_config_perl_tests_only(DynamicPrintConfig config)
|
||||
{
|
||||
tbb::mutex::scoped_lock lock(this->state_mutex());
|
||||
|
||||
|
||||
// Perl unit tests were failing in case the preset was not normalized (e.g. https://github.com/prusa3d/PrusaSlicer/issues/2288 was caused
|
||||
// by too short max_layer_height vector. Calling the necessary function Preset::normalize(...) is not currently possible because there is no
|
||||
// access to preset. This should be solved when the unit tests are rewritten to C++. For now we just copy-pasted code from Preset.cpp
|
||||
// to make sure the unit tests pass (functions set_num_extruders and nozzle_options()).
|
||||
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("nozzle_diameter", true));
|
||||
assert(nozzle_diameter != nullptr);
|
||||
const auto &defaults = FullPrintConfig::defaults();
|
||||
for (const std::string &key : { "nozzle_diameter", "min_layer_height", "max_layer_height", "extruder_offset",
|
||||
"retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed",
|
||||
"retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe",
|
||||
"retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour" })
|
||||
{
|
||||
auto *opt = config.option(key, true);
|
||||
assert(opt != nullptr);
|
||||
assert(opt->is_vector());
|
||||
unsigned int num_extruders = (unsigned int)nozzle_diameter->values.size();
|
||||
static_cast<ConfigOptionVectorBase*>(opt)->resize(num_extruders, defaults.option(key));
|
||||
}
|
||||
|
||||
// we get a copy of the config object so we can modify it safely
|
||||
config.normalize();
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ public:
|
|||
// The following three methods are used by the Perl tests only. Get rid of them!
|
||||
void reload_object(size_t idx);
|
||||
void add_model_object(ModelObject* model_object, int idx = -1);
|
||||
bool apply_config(DynamicPrintConfig config);
|
||||
bool apply_config_perl_tests_only(DynamicPrintConfig config);
|
||||
|
||||
void process() override;
|
||||
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
|
||||
// Set the step as started. Block on mutex while the Print / PrintObject / PrintRegion objects are being
|
||||
// modified by the UI thread.
|
||||
// This is necessary to block until the Print::apply_config() updates its state, which may
|
||||
// This is necessary to block until the Print::apply() updates its state, which may
|
||||
// influence the processing step being entered.
|
||||
template<typename ThrowIfCanceled>
|
||||
bool set_started(StepType step, tbb::mutex &mtx, ThrowIfCanceled throw_if_canceled) {
|
||||
|
|
|
@ -435,7 +435,7 @@ SupportLayerPtrs::const_iterator PrintObject::insert_support_layer(SupportLayerP
|
|||
return m_support_layers.insert(pos, new SupportLayer(id, this, height, print_z, slice_z));
|
||||
}
|
||||
|
||||
// Called by Print::apply_config().
|
||||
// Called by Print::apply().
|
||||
// This method only accepts PrintObjectConfig and PrintRegionConfig option keys.
|
||||
bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <agg/agg_path_storage.h>
|
||||
|
||||
// Experimental minz image write:
|
||||
#include <miniz/miniz_tdef.h>
|
||||
#include <miniz.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
|
@ -757,8 +757,8 @@ public:
|
|||
|
||||
template<class T> inline const Pillar& pillar(T id) const {
|
||||
static_assert(std::is_integral<T>::value, "Invalid index type");
|
||||
assert(id >= 0 && id < m_pillars.size() &&
|
||||
id < std::numeric_limits<size_t>::max());
|
||||
assert(id >= 0 && size_t(id) < m_pillars.size() &&
|
||||
size_t(id) < std::numeric_limits<size_t>::max());
|
||||
return m_pillars[size_t(id)];
|
||||
}
|
||||
|
||||
|
|
|
@ -425,7 +425,10 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||
print_object->set_trafo(sla_trafo(*this, model_object), model_object.instances.front()->is_left_handed());
|
||||
|
||||
print_object->set_instances(std::move(new_instances));
|
||||
print_object->config_apply(config, true);
|
||||
|
||||
SLAPrintObjectConfig new_config = m_default_object_config;
|
||||
normalize_and_apply_config(new_config, model_object.config);
|
||||
print_object->config_apply(new_config, true);
|
||||
print_objects_new.emplace_back(print_object);
|
||||
new_objects = true;
|
||||
}
|
||||
|
@ -1530,7 +1533,7 @@ SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object):
|
|||
|
||||
SLAPrintObject::~SLAPrintObject() {}
|
||||
|
||||
// Called by SLAPrint::apply_config().
|
||||
// Called by SLAPrint::apply().
|
||||
// This method only accepts SLAPrintObjectConfig option keys.
|
||||
bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
|
||||
{
|
||||
|
|
|
@ -28,19 +28,6 @@
|
|||
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha4 techs
|
||||
//====================
|
||||
#define ENABLE_1_42_0_ALPHA4 1
|
||||
|
||||
// Changed algorithm to extract euler angles from rotation matrix
|
||||
#define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4)
|
||||
// Modified initial default placement of generic subparts
|
||||
#define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4)
|
||||
// Bunch of fixes related to volumes centering
|
||||
#define ENABLE_VOLUMES_CENTERING_FIXES (1 && ENABLE_1_42_0_ALPHA4)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha7 techs
|
||||
//====================
|
||||
|
@ -59,12 +46,4 @@
|
|||
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.rc techs
|
||||
//====================
|
||||
#define ENABLE_1_42_0_RC 1
|
||||
|
||||
// Disables Edit->Deselect all item menu item
|
||||
#define DISABLE_DESELECT_ALL_MENU_ITEM (1 && ENABLE_1_42_0_RC)
|
||||
|
||||
#endif // _technologies_h_
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#include "ClipperUtils.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "Tesselate.hpp"
|
||||
#include "qhull/src/libqhullcpp/Qhull.h"
|
||||
#include "qhull/src/libqhullcpp/QhullFacetList.h"
|
||||
#include "qhull/src/libqhullcpp/QhullVertexSet.h"
|
||||
#include <libqhullcpp/Qhull.h>
|
||||
#include <libqhullcpp/QhullFacetList.h>
|
||||
#include <libqhullcpp/QhullVertexSet.h>
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#include <exception>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "Zipper.hpp"
|
||||
#include "miniz/miniz_zip.h"
|
||||
#include "miniz_extension.hpp"
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "I18N.hpp"
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
|
@ -126,9 +123,9 @@ Zipper::Zipper(const std::string &zipfname, e_compression compression)
|
|||
|
||||
memset(&m_impl->arch, 0, sizeof(m_impl->arch));
|
||||
|
||||
// Initialize the archive data
|
||||
if(!mz_zip_writer_init_file(&m_impl->arch, zipfname.c_str(), 0))
|
||||
if (!open_zip_writer(&m_impl->arch, zipfname)) {
|
||||
m_impl->blow_up();
|
||||
}
|
||||
}
|
||||
|
||||
Zipper::~Zipper()
|
||||
|
@ -144,7 +141,7 @@ Zipper::~Zipper()
|
|||
}
|
||||
|
||||
// The file should be closed no matter what...
|
||||
if(!mz_zip_writer_end(&m_impl->arch))
|
||||
if(!close_zip_writer(&m_impl->arch))
|
||||
BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef ZIPPER_HPP
|
||||
#define ZIPPER_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
|
|
59
src/libslic3r/miniz_extension.cpp
Normal file
59
src/libslic3r/miniz_extension.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "miniz_extension.hpp"
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
#include "boost/nowide/cstdio.hpp"
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
bool open_zip(mz_zip_archive *zip, const char *fname, bool isread)
|
||||
{
|
||||
if (!zip) return false;
|
||||
const char *mode = isread ? "rb" : "wb";
|
||||
|
||||
FILE *f = nullptr;
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
f = boost::nowide::fopen(fname, mode);
|
||||
#elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE)
|
||||
f = fopen64(fname, mode);
|
||||
#else
|
||||
f = fopen(fname, mode);
|
||||
#endif
|
||||
|
||||
if (!f) {
|
||||
zip->m_last_error = MZ_ZIP_FILE_OPEN_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
return isread ? mz_zip_reader_init_cfile(zip, f, 0, 0)
|
||||
: mz_zip_writer_init_cfile(zip, f, 0);
|
||||
}
|
||||
|
||||
bool close_zip(mz_zip_archive *zip, bool isread)
|
||||
{
|
||||
bool ret = false;
|
||||
if (zip) {
|
||||
FILE *f = mz_zip_get_cfile(zip);
|
||||
ret = bool(isread ? mz_zip_reader_end(zip)
|
||||
: mz_zip_writer_end(zip));
|
||||
if (f) fclose(f);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bool open_zip_reader(mz_zip_archive *zip, const std::string &fname)
|
||||
{
|
||||
return open_zip(zip, fname.c_str(), true);
|
||||
}
|
||||
|
||||
bool open_zip_writer(mz_zip_archive *zip, const std::string &fname)
|
||||
{
|
||||
return open_zip(zip, fname.c_str(), false);
|
||||
}
|
||||
|
||||
bool close_zip_reader(mz_zip_archive *zip) { return close_zip(zip, true); }
|
||||
bool close_zip_writer(mz_zip_archive *zip) { return close_zip(zip, false); }
|
||||
|
||||
}
|
16
src/libslic3r/miniz_extension.hpp
Normal file
16
src/libslic3r/miniz_extension.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef MINIZ_EXTENSION_HPP
|
||||
#define MINIZ_EXTENSION_HPP
|
||||
|
||||
#include <string>
|
||||
#include <miniz.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
bool open_zip_reader(mz_zip_archive *zip, const std::string &fname_utf8);
|
||||
bool open_zip_writer(mz_zip_archive *zip, const std::string &fname_utf8);
|
||||
bool close_zip_reader(mz_zip_archive *zip);
|
||||
bool close_zip_writer(mz_zip_archive *zip);
|
||||
|
||||
}
|
||||
|
||||
#endif // MINIZ_EXTENSION_HPP
|
Loading…
Add table
Add a link
Reference in a new issue