mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-08 22:35:15 -06:00
Merge branch 'master' into tm_arrange_selection
This commit is contained in:
commit
8d66b51e8c
31 changed files with 1156 additions and 441 deletions
|
@ -93,7 +93,7 @@ enum ConfigOptionMode {
|
|||
comExpert
|
||||
};
|
||||
|
||||
enum PrinterTechnology
|
||||
enum PrinterTechnology : unsigned char
|
||||
{
|
||||
// Fused Filament Fabrication
|
||||
ptFFF,
|
||||
|
|
|
@ -169,6 +169,9 @@ static inline Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2
|
|||
|
||||
std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const
|
||||
{
|
||||
if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool)
|
||||
throw std::invalid_argument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
|
||||
|
||||
std::string gcode;
|
||||
|
||||
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin
|
||||
|
@ -182,8 +185,11 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
|||
end_pos = Eigen::Rotation2Df(alpha) * end_pos;
|
||||
end_pos += m_wipe_tower_pos;
|
||||
}
|
||||
std::string tcr_rotated_gcode = tcr.priming ? tcr.gcode : rotate_wipe_tower_moves(tcr.gcode, tcr.start_pos, m_wipe_tower_pos, alpha);
|
||||
|
||||
|
||||
Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos;
|
||||
float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
|
||||
|
||||
std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation);
|
||||
|
||||
// Disable linear advance for the wipe tower operations.
|
||||
gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
|
||||
|
@ -285,17 +291,21 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
|||
|
||||
// This function postprocesses gcode_original, rotates and moves all G1 extrusions and returns resulting gcode
|
||||
// Starting position has to be supplied explicitely (otherwise it would fail in case first G1 command only contained one coordinate)
|
||||
std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gcode_original, const Vec2f& start_pos, const Vec2f& translation, float angle) const
|
||||
std::string WipeTowerIntegration::post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const
|
||||
{
|
||||
std::istringstream gcode_str(gcode_original);
|
||||
Vec2f extruder_offset = m_extruder_offsets[tcr.initial_tool].cast<float>();
|
||||
|
||||
std::istringstream gcode_str(tcr.gcode);
|
||||
std::string gcode_out;
|
||||
std::string line;
|
||||
Vec2f pos = start_pos;
|
||||
Vec2f transformed_pos;
|
||||
Vec2f pos = tcr.start_pos;
|
||||
Vec2f transformed_pos = pos;
|
||||
Vec2f old_pos(-1000.1f, -1000.1f);
|
||||
|
||||
while (gcode_str) {
|
||||
std::getline(gcode_str, line); // we read the gcode line by line
|
||||
|
||||
// All G1 commands should be translated and rotated
|
||||
if (line.find("G1 ") == 0) {
|
||||
std::ostringstream line_out;
|
||||
std::istringstream line_str(line);
|
||||
|
@ -317,17 +327,34 @@ std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gco
|
|||
|
||||
if (transformed_pos != old_pos) {
|
||||
line = line_out.str();
|
||||
char buf[2048] = "G1";
|
||||
std::ostringstream oss;
|
||||
oss << std::fixed << std::setprecision(3) << "G1 ";
|
||||
if (transformed_pos.x() != old_pos.x())
|
||||
sprintf(buf + strlen(buf), " X%.3f", transformed_pos.x());
|
||||
oss << " X" << transformed_pos.x() - extruder_offset.x();
|
||||
if (transformed_pos.y() != old_pos.y())
|
||||
sprintf(buf + strlen(buf), " Y%.3f", transformed_pos.y());
|
||||
oss << " Y" << transformed_pos.y() - extruder_offset.y();
|
||||
|
||||
line.replace(line.find("G1 "), 3, buf);
|
||||
line.replace(line.find("G1 "), 3, oss.str());
|
||||
old_pos = transformed_pos;
|
||||
}
|
||||
}
|
||||
|
||||
gcode_out += line + "\n";
|
||||
|
||||
// If this was a toolchange command, we should change current extruder offset
|
||||
if (line == "[toolchange_gcode]") {
|
||||
extruder_offset = m_extruder_offsets[tcr.new_tool].cast<float>();
|
||||
|
||||
// If the extruder offset changed, add an extra move so everything is continuous
|
||||
if (extruder_offset != m_extruder_offsets[tcr.initial_tool].cast<float>()) {
|
||||
std::ostringstream oss;
|
||||
oss << std::fixed << std::setprecision(3)
|
||||
<< "G1 X" << transformed_pos.x() - extruder_offset.x()
|
||||
<< " Y" << transformed_pos.y() - extruder_offset.y()
|
||||
<< "\n";
|
||||
gcode_out += oss.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
return gcode_out;
|
||||
}
|
||||
|
@ -2784,7 +2811,17 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||
// if we are running a single-extruder setup, just set the extruder and return nothing
|
||||
if (!m_writer.multiple_extruders) {
|
||||
m_placeholder_parser.set("current_extruder", extruder_id);
|
||||
return m_writer.toolchange(extruder_id);
|
||||
|
||||
std::string gcode;
|
||||
// Append the filament start G-code.
|
||||
const std::string &start_filament_gcode = m_config.start_filament_gcode.get_at(extruder_id);
|
||||
if (! start_filament_gcode.empty()) {
|
||||
// Process the start_filament_gcode for the filament.
|
||||
gcode += this->placeholder_parser_process("start_filament_gcode", start_filament_gcode, extruder_id);
|
||||
check_add_eol(gcode);
|
||||
}
|
||||
gcode += m_writer.toolchange(extruder_id);
|
||||
return gcode;
|
||||
}
|
||||
|
||||
// prepend retraction on the current extruder
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.wipe_tower_width.value)),
|
||||
m_wipe_tower_pos(float(print_config.wipe_tower_x.value), float(print_config.wipe_tower_y.value)),
|
||||
m_wipe_tower_rotation(float(print_config.wipe_tower_rotation_angle)),
|
||||
m_extruder_offsets(print_config.extruder_offset.values),
|
||||
m_priming(priming),
|
||||
m_tool_changes(tool_changes),
|
||||
m_final_purge(final_purge),
|
||||
|
@ -107,14 +108,16 @@ private:
|
|||
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
||||
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const;
|
||||
|
||||
// Postprocesses gcode: rotates and moves all G1 extrusions and returns result
|
||||
std::string rotate_wipe_tower_moves(const std::string& gcode_original, const Vec2f& start_pos, const Vec2f& translation, float angle) const;
|
||||
// Postprocesses gcode: rotates and moves G1 extrusions and returns result
|
||||
std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const;
|
||||
|
||||
// Left / right edges of the wipe tower, for the planning of wipe moves.
|
||||
const float m_left;
|
||||
const float m_right;
|
||||
const Vec2f m_wipe_tower_pos;
|
||||
const float m_wipe_tower_rotation;
|
||||
const std::vector<Vec2d> m_extruder_offsets;
|
||||
|
||||
// Reference to cached values at the Printer class.
|
||||
const std::vector<WipeTower::ToolChangeResult> &m_priming;
|
||||
const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
|
||||
|
|
|
@ -553,7 +553,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
|||
result.elapsed_time = writer.elapsed_time();
|
||||
result.extrusions = writer.extrusions();
|
||||
result.start_pos = writer.start_pos_rotated();
|
||||
result.end_pos = writer.pos_rotated();
|
||||
result.end_pos = writer.pos();
|
||||
|
||||
results.push_back(std::move(result));
|
||||
|
||||
|
@ -643,7 +643,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
|
|||
m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature);
|
||||
toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials.
|
||||
toolchange_Load(writer, cleaning_box);
|
||||
writer.travel(writer.x(),writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road
|
||||
writer.travel(writer.x(), writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road
|
||||
toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area.
|
||||
++ m_num_tool_changes;
|
||||
} else
|
||||
|
|
|
@ -139,13 +139,15 @@ public:
|
|||
|
||||
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
|
||||
|
||||
std::stringstream stream{m_semm ? ramming_parameters : std::string()};
|
||||
float speed = 0.f;
|
||||
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
||||
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
||||
m_filpar[idx].ramming_step_multiplicator /= 100;
|
||||
while (stream >> speed)
|
||||
m_filpar[idx].ramming_speed.push_back(speed);
|
||||
if (m_semm) {
|
||||
std::stringstream stream{ramming_parameters};
|
||||
float speed = 0.f;
|
||||
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
||||
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
||||
m_filpar[idx].ramming_step_multiplicator /= 100;
|
||||
while (stream >> speed)
|
||||
m_filpar[idx].ramming_speed.push_back(speed);
|
||||
}
|
||||
|
||||
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
|
||||
}
|
||||
|
@ -241,8 +243,8 @@ public:
|
|||
int cooling_moves = 0;
|
||||
float cooling_initial_speed = 0.f;
|
||||
float cooling_final_speed = 0.f;
|
||||
float ramming_line_width_multiplicator = 0.f;
|
||||
float ramming_step_multiplicator = 0.f;
|
||||
float ramming_line_width_multiplicator = 1.f;
|
||||
float ramming_step_multiplicator = 1.f;
|
||||
float max_e_speed = std::numeric_limits<float>::max();
|
||||
std::vector<float> ramming_speed;
|
||||
float nozzle_diameter;
|
||||
|
|
|
@ -1918,6 +1918,31 @@ bool model_volume_list_changed(const ModelObject &model_object_old, const ModelO
|
|||
return false;
|
||||
}
|
||||
|
||||
extern bool model_has_multi_part_objects(const Model &model)
|
||||
{
|
||||
for (const ModelObject *model_object : model.objects)
|
||||
if (model_object->volumes.size() != 1 || ! model_object->volumes.front()->is_model_part())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
extern bool model_has_advanced_features(const Model &model)
|
||||
{
|
||||
auto config_is_advanced = [](const DynamicPrintConfig &config) {
|
||||
return ! (config.empty() || (config.size() == 1 && config.cbegin()->first == "extruder"));
|
||||
};
|
||||
for (const ModelObject *model_object : model.objects) {
|
||||
// Is there more than one instance or advanced config data?
|
||||
if (model_object->instances.size() > 1 || config_is_advanced(model_object->config))
|
||||
return true;
|
||||
// Is there any modifier or advanced config data?
|
||||
for (const ModelVolume* model_volume : model_object->volumes)
|
||||
if (! model_volume->is_model_part() || config_is_advanced(model_volume->config))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
||||
void check_model_ids_validity(const Model &model)
|
||||
|
|
|
@ -18,6 +18,15 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace cereal {
|
||||
class BinaryInputArchive;
|
||||
class BinaryOutputArchive;
|
||||
template <class T> void load_optional(BinaryInputArchive &ar, std::shared_ptr<const T> &ptr);
|
||||
template <class T> void save_optional(BinaryOutputArchive &ar, const std::shared_ptr<const T> &ptr);
|
||||
template <class T> void load_by_value(BinaryInputArchive &ar, T &obj);
|
||||
template <class T> void save_by_value(BinaryOutputArchive &ar, const T &obj);
|
||||
}
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Model;
|
||||
|
@ -25,6 +34,7 @@ class ModelInstance;
|
|||
class ModelMaterial;
|
||||
class ModelObject;
|
||||
class ModelVolume;
|
||||
class ModelWipeTower;
|
||||
class Print;
|
||||
class SLAPrint;
|
||||
|
||||
|
@ -60,6 +70,21 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
namespace Internal {
|
||||
template<typename T>
|
||||
class StaticSerializationWrapper
|
||||
{
|
||||
public:
|
||||
StaticSerializationWrapper(T &wrap) : wrapped(wrap) {}
|
||||
private:
|
||||
friend class cereal::access;
|
||||
friend class UndoRedo::StackImpl;
|
||||
template<class Archive> void load(Archive &ar) { cereal::load_by_value(ar, wrapped); }
|
||||
template<class Archive> void save(Archive &ar) const { cereal::save_by_value(ar, wrapped); }
|
||||
T& wrapped;
|
||||
};
|
||||
}
|
||||
|
||||
typedef std::string t_model_material_id;
|
||||
typedef std::string t_model_material_attribute;
|
||||
typedef std::map<t_model_material_attribute, std::string> t_model_material_attributes;
|
||||
|
@ -134,7 +159,8 @@ private:
|
|||
ModelMaterial() : ObjectBase(-1), config(-1), m_model(nullptr) { assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
||||
template<class Archive> void serialize(Archive &ar) {
|
||||
assert(this->id().invalid()); assert(this->config.id().invalid());
|
||||
ar(attributes, config);
|
||||
Internal::StaticSerializationWrapper<ModelConfig> config_wrapper(config);
|
||||
ar(attributes, config_wrapper);
|
||||
// assert(this->id().valid()); assert(this->config.id().valid());
|
||||
}
|
||||
|
||||
|
@ -343,7 +369,8 @@ private:
|
|||
}
|
||||
template<class Archive> void serialize(Archive &ar) {
|
||||
ar(cereal::base_class<ObjectBase>(this));
|
||||
ar(name, input_file, instances, volumes, config, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation,
|
||||
Internal::StaticSerializationWrapper<ModelConfig> config_wrapper(config);
|
||||
ar(name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation,
|
||||
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid);
|
||||
}
|
||||
};
|
||||
|
@ -527,8 +554,25 @@ private:
|
|||
ModelVolume() : ObjectBase(-1), config(-1), object(nullptr) {
|
||||
assert(this->id().invalid()); assert(this->config.id().invalid());
|
||||
}
|
||||
template<class Archive> void serialize(Archive &ar) {
|
||||
ar(name, config, m_mesh, m_type, m_material_id, m_convex_hull, m_transformation, m_is_splittable);
|
||||
template<class Archive> void load(Archive &ar) {
|
||||
bool has_convex_hull;
|
||||
ar(name, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
||||
cereal::load_by_value(ar, config);
|
||||
assert(m_mesh);
|
||||
if (has_convex_hull) {
|
||||
cereal::load_optional(ar, m_convex_hull);
|
||||
if (! m_convex_hull && ! m_mesh->empty())
|
||||
// The convex hull was released from the Undo / Redo stack to conserve memory. Recalculate it.
|
||||
this->calculate_convex_hull();
|
||||
} else
|
||||
m_convex_hull.reset();
|
||||
}
|
||||
template<class Archive> void save(Archive &ar) const {
|
||||
bool has_convex_hull = m_convex_hull.get() != nullptr;
|
||||
ar(name, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
||||
cereal::save_by_value(ar, config);
|
||||
if (has_convex_hull)
|
||||
cereal::save_optional(ar, m_convex_hull);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -641,6 +685,35 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
class ModelWipeTower final : public ObjectBase
|
||||
{
|
||||
public:
|
||||
Vec2d position;
|
||||
double rotation;
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
friend class UndoRedo::StackImpl;
|
||||
friend class Model;
|
||||
|
||||
// Constructors to be only called by derived classes.
|
||||
// Default constructor to assign a unique ID.
|
||||
explicit ModelWipeTower() {}
|
||||
// Constructor with ignored int parameter to assign an invalid ID, to be replaced
|
||||
// by an existing ID copied from elsewhere.
|
||||
explicit ModelWipeTower(int) : ObjectBase(-1) {}
|
||||
// Copy constructor copies the ID.
|
||||
explicit ModelWipeTower(const ModelWipeTower &cfg) = default;
|
||||
|
||||
// Disabled methods.
|
||||
ModelWipeTower(ModelWipeTower &&rhs) = delete;
|
||||
ModelWipeTower& operator=(const ModelWipeTower &rhs) = delete;
|
||||
ModelWipeTower& operator=(ModelWipeTower &&rhs) = delete;
|
||||
|
||||
// For serialization / deserialization of ModelWipeTower composed into another class into the Undo / Redo stack as a separate object.
|
||||
template<typename Archive> void serialize(Archive &ar) { ar(position, rotation); }
|
||||
};
|
||||
|
||||
// The print bed content.
|
||||
// Description of a triangular model with multiple materials, multiple instances with various affine transformations
|
||||
// and with multiple modifier meshes.
|
||||
|
@ -656,6 +729,8 @@ public:
|
|||
ModelMaterialMap materials;
|
||||
// Objects are owned by a model. Each model may have multiple instances, each instance having its own transformation (shift, scale, rotation).
|
||||
ModelObjectPtrs objects;
|
||||
// Wipe tower object.
|
||||
ModelWipeTower wipe_tower;
|
||||
|
||||
// Default constructor assigns a new ID to the model.
|
||||
Model() { assert(this->id().valid()); }
|
||||
|
@ -733,7 +808,8 @@ private:
|
|||
friend class cereal::access;
|
||||
friend class UndoRedo::StackImpl;
|
||||
template<class Archive> void serialize(Archive &ar) {
|
||||
ar(materials, objects);
|
||||
Internal::StaticSerializationWrapper<ModelWipeTower> wipe_tower_wrapper(wipe_tower);
|
||||
ar(materials, objects, wipe_tower_wrapper);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -752,6 +828,12 @@ extern bool model_object_list_extended(const Model &model_old, const Model &mode
|
|||
// than the old ModelObject.
|
||||
extern bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type);
|
||||
|
||||
// If the model has multi-part objects, then it is currently not supported by the SLA mode.
|
||||
// Either the model cannot be loaded, or a SLA printer has to be activated.
|
||||
extern bool model_has_multi_part_objects(const Model &model);
|
||||
// If the model has advanced features, then it cannot be processed in simple mode.
|
||||
extern bool model_has_advanced_features(const Model &model);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
||||
void check_model_ids_validity(const Model &model);
|
||||
|
@ -760,4 +842,10 @@ void check_model_ids_equal(const Model &model1, const Model &model2);
|
|||
|
||||
} // namespace Slic3r
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume, cereal::specialization::member_load_save> {};
|
||||
template <class Archive> struct specialize<Archive, Slic3r::ModelConfig, cereal::specialization::member_serialize> {};
|
||||
}
|
||||
|
||||
#endif /* slic3r_Model_hpp_ */
|
||||
|
|
|
@ -607,6 +607,40 @@ void TriangleMesh::require_shared_vertices()
|
|||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - end";
|
||||
}
|
||||
|
||||
size_t TriangleMesh::memsize() const
|
||||
{
|
||||
size_t memsize = 8 + this->stl.memsize() + this->its.memsize();
|
||||
return memsize;
|
||||
}
|
||||
|
||||
// Release optional data from the mesh if the object is on the Undo / Redo stack only. Returns the amount of memory released.
|
||||
size_t TriangleMesh::release_optional()
|
||||
{
|
||||
size_t memsize_released = sizeof(stl_neighbors) * this->stl.neighbors_start.size() + this->its.memsize();
|
||||
// The indexed triangle set may be recalculated using the stl_generate_shared_vertices() function.
|
||||
this->its.clear();
|
||||
// The neighbors structure may be recalculated using the stl_check_facets_exact() function.
|
||||
this->stl.neighbors_start.clear();
|
||||
return memsize_released;
|
||||
}
|
||||
|
||||
// Restore optional data possibly released by release_optional().
|
||||
void TriangleMesh::restore_optional()
|
||||
{
|
||||
if (! this->stl.facet_start.empty()) {
|
||||
// Save the old stats before calling stl_check_faces_exact, as it may modify the statistics.
|
||||
stl_stats stats = this->stl.stats;
|
||||
if (this->stl.neighbors_start.empty()) {
|
||||
stl_reallocate(&this->stl);
|
||||
stl_check_facets_exact(&this->stl);
|
||||
}
|
||||
if (this->its.vertices.empty())
|
||||
stl_generate_shared_vertices(&this->stl, this->its);
|
||||
// Restore the old statistics.
|
||||
this->stl.stats = stats;
|
||||
}
|
||||
}
|
||||
|
||||
void TriangleMeshSlicer::init(const TriangleMesh *_mesh, throw_on_cancel_callback_type throw_on_cancel)
|
||||
{
|
||||
mesh = _mesh;
|
||||
|
|
|
@ -67,6 +67,12 @@ public:
|
|||
size_t facets_count() const { return this->stl.stats.number_of_facets; }
|
||||
bool empty() const { return this->facets_count() == 0; }
|
||||
bool is_splittable() const;
|
||||
// Estimate of the memory occupied by this structure, important for keeping an eye on the Undo / Redo stack allocation.
|
||||
size_t memsize() const;
|
||||
// Release optional data from the mesh if the object is on the Undo / Redo stack only. Returns the amount of memory released.
|
||||
size_t release_optional();
|
||||
// Restore optional data possibly released by release_optional().
|
||||
void restore_optional();
|
||||
|
||||
stl_file stl;
|
||||
indexed_triangle_set its;
|
||||
|
|
|
@ -21,6 +21,8 @@ extern std::string format_memsize_MB(size_t n);
|
|||
// The string is non-empty only if the loglevel >= info (3).
|
||||
extern std::string log_memory_info();
|
||||
extern void disable_multi_threading();
|
||||
// Returns the size of physical memory (RAM) in bytes.
|
||||
extern size_t total_physical_memory();
|
||||
|
||||
// Set a path with GUI resource files.
|
||||
void set_var_dir(const std::string &path);
|
||||
|
|
|
@ -7,10 +7,15 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#ifdef BSD
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <boost/log/core.hpp>
|
||||
|
@ -467,4 +472,75 @@ std::string log_memory_info()
|
|||
}
|
||||
#endif
|
||||
|
||||
// Returns the size of physical memory (RAM) in bytes.
|
||||
// http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system
|
||||
size_t total_physical_memory()
|
||||
{
|
||||
#if defined(_WIN32) && (defined(__CYGWIN__) || defined(__CYGWIN32__))
|
||||
// Cygwin under Windows. ------------------------------------
|
||||
// New 64-bit MEMORYSTATUSEX isn't available. Use old 32.bit
|
||||
MEMORYSTATUS status;
|
||||
status.dwLength = sizeof(status);
|
||||
GlobalMemoryStatus( &status );
|
||||
return (size_t)status.dwTotalPhys;
|
||||
#elif defined(_WIN32)
|
||||
// Windows. -------------------------------------------------
|
||||
// Use new 64-bit MEMORYSTATUSEX, not old 32-bit MEMORYSTATUS
|
||||
MEMORYSTATUSEX status;
|
||||
status.dwLength = sizeof(status);
|
||||
GlobalMemoryStatusEx( &status );
|
||||
return (size_t)status.ullTotalPhys;
|
||||
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
|
||||
// UNIX variants. -------------------------------------------
|
||||
// Prefer sysctl() over sysconf() except sysctl() HW_REALMEM and HW_PHYSMEM
|
||||
|
||||
#if defined(CTL_HW) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM64))
|
||||
int mib[2];
|
||||
mib[0] = CTL_HW;
|
||||
#if defined(HW_MEMSIZE)
|
||||
mib[1] = HW_MEMSIZE; // OSX. ---------------------
|
||||
#elif defined(HW_PHYSMEM64)
|
||||
mib[1] = HW_PHYSMEM64; // NetBSD, OpenBSD. ---------
|
||||
#endif
|
||||
int64_t size = 0; // 64-bit
|
||||
size_t len = sizeof( size );
|
||||
if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 )
|
||||
return (size_t)size;
|
||||
return 0L; // Failed?
|
||||
|
||||
#elif defined(_SC_AIX_REALMEM)
|
||||
// AIX. -----------------------------------------------------
|
||||
return (size_t)sysconf( _SC_AIX_REALMEM ) * (size_t)1024L;
|
||||
|
||||
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
|
||||
// FreeBSD, Linux, OpenBSD, and Solaris. --------------------
|
||||
return (size_t)sysconf( _SC_PHYS_PAGES ) *
|
||||
(size_t)sysconf( _SC_PAGESIZE );
|
||||
|
||||
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE)
|
||||
// Legacy. --------------------------------------------------
|
||||
return (size_t)sysconf( _SC_PHYS_PAGES ) *
|
||||
(size_t)sysconf( _SC_PAGE_SIZE );
|
||||
|
||||
#elif defined(CTL_HW) && (defined(HW_PHYSMEM) || defined(HW_REALMEM))
|
||||
// DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX. --------
|
||||
int mib[2];
|
||||
mib[0] = CTL_HW;
|
||||
#if defined(HW_REALMEM)
|
||||
mib[1] = HW_REALMEM; // FreeBSD. -----------------
|
||||
#elif defined(HW_PYSMEM)
|
||||
mib[1] = HW_PHYSMEM; // Others. ------------------
|
||||
#endif
|
||||
unsigned int size = 0; // 32-bit
|
||||
size_t len = sizeof( size );
|
||||
if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 )
|
||||
return (size_t)size;
|
||||
return 0L; // Failed?
|
||||
#endif // sysctl and sysconf variants
|
||||
|
||||
#else
|
||||
return 0L; // Unknown OS.
|
||||
#endif
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue