Skip to content

Commit

Permalink
SPE-1103 Added menu items for the conversation of the volumes from/to…
Browse files Browse the repository at this point in the history
… meters

Related to #4521
  • Loading branch information
YuSanka committed Feb 10, 2021
1 parent 8049dd1 commit e664100
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 43 deletions.
5 changes: 5 additions & 0 deletions src/libslic3r/Format/3mf.cpp
Expand Up @@ -115,6 +115,7 @@ static constexpr const char* SOURCE_OFFSET_X_KEY = "source_offset_x";
static constexpr const char* SOURCE_OFFSET_Y_KEY = "source_offset_y";
static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
static constexpr const char* SOURCE_IN_INCHES = "source_in_inches";
static constexpr const char* SOURCE_IN_METERS = "source_in_meters";

const unsigned int VALID_OBJECT_TYPES_COUNT = 1;
const char* VALID_OBJECT_TYPES[] =
Expand Down Expand Up @@ -1913,6 +1914,8 @@ namespace Slic3r {
volume->source.mesh_offset(2) = ::atof(metadata.value.c_str());
else if (metadata.key == SOURCE_IN_INCHES)
volume->source.is_converted_from_inches = metadata.value == "1";
else if (metadata.key == SOURCE_IN_METERS)
volume->source.is_converted_from_meters = metadata.value == "1";
else
volume->config.set_deserialize(metadata.key, metadata.value);
}
Expand Down Expand Up @@ -2822,6 +2825,8 @@ namespace Slic3r {
}
if (volume->source.is_converted_from_inches)
stream << prefix << SOURCE_IN_INCHES << "\" " << VALUE_ATTR << "=\"1\"/>\n";
if (volume->source.is_converted_from_meters)
stream << prefix << SOURCE_IN_METERS << "\" " << VALUE_ATTR << "=\"1\"/>\n";
}

// stores volume's config data
Expand Down
5 changes: 5 additions & 0 deletions src/libslic3r/Format/AMF.cpp
Expand Up @@ -798,6 +798,9 @@ void AMFParserContext::endElement(const char * /* name */)
else if (strcmp(opt_key, "source_in_inches") == 0) {
m_volume->source.is_converted_from_inches = m_value[1] == "1";
}
else if (strcmp(opt_key, "source_in_meters") == 0) {
m_volume->source.is_converted_from_meters = m_value[1] == "1";
}
}
} else if (m_path.size() == 3) {
if (m_path[1] == NODE_TYPE_MATERIAL) {
Expand Down Expand Up @@ -1232,6 +1235,8 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config,
}
if (volume->source.is_converted_from_inches)
stream << " <metadata type=\"slic3r.source_in_inches\">1</metadata>\n";
if (volume->source.is_converted_from_meters)
stream << " <metadata type=\"slic3r.source_in_meters\">1</metadata>\n";
stream << std::setprecision(std::numeric_limits<float>::max_digits10);
const indexed_triangle_set &its = volume->mesh().its;
for (size_t i = 0; i < its.indices.size(); ++i) {
Expand Down
22 changes: 18 additions & 4 deletions src/libslic3r/Model.cpp
Expand Up @@ -491,7 +491,7 @@ void Model::convert_from_meters(bool only_small_volumes)
if (! only_small_volumes || obj->get_object_stl_stats().volume < 0.001) { // 0.001 = 0.1*0.1*0.1;
obj->scale_mesh_after_creation(Vec3d(m_to_mm, m_to_mm, m_to_mm));
for (ModelVolume* v : obj->volumes)
v->source.is_converted_from_inches = true;
v->source.is_converted_from_meters = true;
}
}

Expand Down Expand Up @@ -1046,13 +1046,14 @@ void ModelObject::scale_mesh_after_creation(const Vec3d &versor)
this->invalidate_bounding_box();
}

void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial, std::vector<int> volume_idxs)
void ModelObject::convert_units(ModelObjectPtrs& new_objects, ConversionType conv_type, std::vector<int> volume_idxs)
{
BOOST_LOG_TRIVIAL(trace) << "ModelObject::convert_units - start";

ModelObject* new_object = new_clone(*this);

double koef = from_imperial ? 25.4 : 0.0393700787;
double koef = conv_type == ConversionType::CONV_FROM_INCH ? 25.4 : conv_type == ConversionType::CONV_TO_INCH ? 0.0393700787 :
conv_type == ConversionType::CONV_FROM_METER ? 1000 : conv_type == ConversionType::CONV_TO_METER ? 0.001 : 1;
const Vec3d versor = Vec3d(koef, koef, koef);

new_object->set_model(nullptr);
Expand Down Expand Up @@ -1080,6 +1081,8 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial
vol->source.input_file = volume->source.input_file;
vol->source.object_idx = (int)new_objects.size();
vol->source.volume_idx = vol_idx;
vol->source.is_converted_from_inches = volume->source.is_converted_from_inches;
vol->source.is_converted_from_meters = volume->source.is_converted_from_meters;

vol->supported_facets.assign(volume->supported_facets);
vol->seam_facets.assign(volume->seam_facets);
Expand All @@ -1091,7 +1094,10 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial
std::find(volume_idxs.begin(), volume_idxs.end(), vol_idx) != volume_idxs.end())) {
vol->scale_geometry_after_creation(versor);
vol->set_offset(versor.cwiseProduct(volume->get_offset()));
vol->source.is_converted_from_inches = from_imperial;
if (conv_type == ConversionType::CONV_FROM_INCH || conv_type == ConversionType::CONV_TO_INCH)
vol->source.is_converted_from_inches = conv_type == ConversionType::CONV_FROM_INCH;
if (conv_type == ConversionType::CONV_FROM_METER || conv_type == ConversionType::CONV_TO_METER)
vol->source.is_converted_from_meters = conv_type == ConversionType::CONV_FROM_METER;
}
else
vol->set_offset(volume->get_offset());
Expand Down Expand Up @@ -1841,6 +1847,14 @@ void ModelVolume::convert_from_imperial_units()
this->source.is_converted_from_inches = true;
}

void ModelVolume::convert_from_meters()
{
double m_to_mm = 1000;
this->scale_geometry_after_creation(Vec3d(m_to_mm, m_to_mm, m_to_mm));
this->set_offset(Vec3d(0, 0, 0));
this->source.is_converted_from_meters = true;
}

void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
{
mesh->transform(get_matrix(dont_translate));
Expand Down
14 changes: 12 additions & 2 deletions src/libslic3r/Model.hpp
Expand Up @@ -29,6 +29,7 @@ namespace cereal {
}

namespace Slic3r {
enum class ConversionType;

class Model;
class ModelInstance;
Expand Down Expand Up @@ -325,7 +326,7 @@ class ModelObject final : public ObjectBase

// This method could only be called before the meshes of this ModelVolumes are not shared!
void scale_mesh_after_creation(const Vec3d& versor);
void convert_units(ModelObjectPtrs&new_objects, bool from_imperial, std::vector<int> volume_idxs);
void convert_units(ModelObjectPtrs&new_objects, ConversionType conv_type, std::vector<int> volume_idxs);

size_t materials_count() const;
size_t facets_count() const;
Expand Down Expand Up @@ -495,6 +496,13 @@ enum class EnforcerBlockerType : int8_t {
BLOCKER = 2
};

enum class ConversionType : int {
CONV_TO_INCH,
CONV_FROM_INCH,
CONV_TO_METER,
CONV_FROM_METER,
};

class FacetsAnnotation final : public ObjectWithTimestamp {
public:
// Assign the content if the timestamp differs, don't assign an ObjectID.
Expand Down Expand Up @@ -553,11 +561,12 @@ class ModelVolume final : public ObjectBase
Vec3d mesh_offset{ Vec3d::Zero() };
Geometry::Transformation transform;
bool is_converted_from_inches = false;
bool is_converted_from_meters = false;

template<class Archive> void serialize(Archive& ar) {
//FIXME Vojtech: Serialize / deserialize only if the Source is set.
// likely testing input_file or object_idx would be sufficient.
ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches);
ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches, is_converted_from_meters);
}
};
Source source;
Expand Down Expand Up @@ -657,6 +666,7 @@ class ModelVolume final : public ObjectBase
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }
void convert_from_imperial_units();
void convert_from_meters();

const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }

Expand Down
65 changes: 34 additions & 31 deletions src/slic3r/GUI/GUI_ObjectList.cpp
Expand Up @@ -1023,7 +1023,7 @@ void ObjectList::show_context_menu(const bool evt_context_menu)
printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object;

if (type & (itObject | itVolume))
append_menu_item_convert_unit(menu);
append_menu_items_convert_unit(menu);
if (!(type & itInstance))
append_menu_item_settings(menu);
}
Expand Down Expand Up @@ -1906,56 +1906,59 @@ void ObjectList::append_menu_item_scale_selection_to_fit_print_volume(wxMenu* me
[](wxCommandEvent&) { wxGetApp().plater()->scale_selection_to_fit_print_volume(); }, "", menu);
}

void ObjectList::append_menu_item_convert_unit(wxMenu* menu, int insert_pos/* = 1*/)
void ObjectList::append_menu_items_convert_unit(wxMenu* menu, int insert_pos/* = 1*/)
{
std::vector<int> obj_idxs, vol_idxs;
get_selection_indexes(obj_idxs, vol_idxs);
if (obj_idxs.empty() && vol_idxs.empty())
return;

auto can_append = [this, obj_idxs, vol_idxs](bool from_imperial_unit) {
auto volume_respects_conversion = [](ModelVolume* volume, ConversionType conver_type)
{
return (conver_type == ConversionType::CONV_FROM_INCH && volume->source.is_converted_from_inches) ||
(conver_type == ConversionType::CONV_TO_INCH && !volume->source.is_converted_from_inches) ||
(conver_type == ConversionType::CONV_FROM_METER && volume->source.is_converted_from_meters) ||
(conver_type == ConversionType::CONV_TO_METER && !volume->source.is_converted_from_meters);
};

auto can_append = [this, obj_idxs, vol_idxs, volume_respects_conversion](ConversionType conver_type)
{
ModelObjectPtrs objects;
for (int obj_idx : obj_idxs) {
ModelObject* object = (*m_objects)[obj_idx];
if (vol_idxs.empty()) {
for (ModelVolume* volume : object->volumes)
if (volume->source.is_converted_from_inches == from_imperial_unit)
if (volume_respects_conversion(volume, conver_type))
return false;
}
else {
for (int vol_idx : vol_idxs)
if (object->volumes[vol_idx]->source.is_converted_from_inches == from_imperial_unit)
if (volume_respects_conversion(object->volumes[vol_idx], conver_type))
return false;
}
}
return true;
};

wxString convert_menu_name = _L("Convert from imperial units");
int convert_menu_id = menu->FindItem(convert_menu_name);
wxString revert_menu_name = _L("Revert conversion from imperial units");
int revert_menu_id = menu->FindItem(revert_menu_name);

if (can_append(true)) {
// Delete revert menu item
if (revert_menu_id != wxNOT_FOUND)
menu->Destroy(revert_menu_id);
// Add convert menu item if it doesn't exist
if (convert_menu_id == wxNOT_FOUND)
append_menu_item(menu, wxID_ANY, convert_menu_name, convert_menu_name,
[](wxCommandEvent&) { wxGetApp().plater()->convert_unit(true); }, "", menu,
[]() {return true;}, nullptr, insert_pos);
}

if (can_append(false)) {
// Delete convert menu item
if (convert_menu_id != wxNOT_FOUND)
menu->Destroy(convert_menu_id);
// Add convert menu item if it doesn't exist
if (revert_menu_id == wxNOT_FOUND)
append_menu_item(menu, wxID_ANY, revert_menu_name, revert_menu_name,
[](wxCommandEvent&) { wxGetApp().plater()->convert_unit(false); }, "", menu,
[]() {return true;}, nullptr, insert_pos);
std::vector<std::pair<ConversionType, wxString>> items = {
{ConversionType::CONV_FROM_INCH , _L("Convert from imperial units") },
{ConversionType::CONV_TO_INCH , _L("Revert conversion from imperial units") },
{ConversionType::CONV_FROM_METER, _L("Convert from meters") },
{ConversionType::CONV_TO_METER , _L("Revert conversion from meters") } };

for (auto item : items) {
int menu_id = menu->FindItem(item.second);
if (can_append(item.first)) {
// Add menu item if it doesn't exist
if (menu_id == wxNOT_FOUND)
append_menu_item(menu, wxID_ANY, item.second, item.second,
[item](wxCommandEvent&) { wxGetApp().plater()->convert_unit(item.first); }, "", menu,
[]() {return true; }, nullptr, insert_pos);
}
else if (menu_id != wxNOT_FOUND) {
// Delete menu item
menu->Destroy(menu_id);
}
}
}

Expand Down Expand Up @@ -4606,7 +4609,7 @@ void ObjectList::show_multi_selection_menu()
return wxGetApp().plater()->can_reload_from_disk();
}, wxGetApp().plater());

append_menu_item_convert_unit(menu);
append_menu_items_convert_unit(menu);
if (can_merge_to_multipart_object())
append_menu_item_merge_to_multipart_object(menu);

Expand Down
2 changes: 1 addition & 1 deletion src/slic3r/GUI/GUI_ObjectList.hpp
Expand Up @@ -284,7 +284,7 @@ class ObjectList : public wxDataViewCtrl
void append_menu_item_change_extruder(wxMenu* menu);
void append_menu_item_delete(wxMenu* menu);
void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu);
void append_menu_item_convert_unit(wxMenu* menu, int insert_pos = 1); // Add "Conver/Revert..." menu item after "Reload From Disk"
void append_menu_items_convert_unit(wxMenu* menu, int insert_pos = 1); // Add "Conver/Revert..." menu items (from/to inches/meters) after "Reload From Disk"
void append_menu_item_merge_to_multipart_object(wxMenu *menu);
void append_menu_item_merge_to_single_object(wxMenu *menu);
void create_object_popupmenu(wxMenu *menu);
Expand Down
12 changes: 8 additions & 4 deletions src/slic3r/GUI/Plater.cpp
Expand Up @@ -3329,6 +3329,8 @@ void Plater::priv::reload_from_disk()
new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
if (old_volume->source.is_converted_from_inches)
new_volume->convert_from_imperial_units();
if (old_volume->source.is_converted_from_meters)
new_volume->convert_from_meters();
new_volume->supported_facets.assign(old_volume->supported_facets);
new_volume->seam_facets.assign(old_volume->seam_facets);
std::swap(old_model_object->volumes[sel_v.volume_idx], old_model_object->volumes.back());
Expand Down Expand Up @@ -3871,7 +3873,7 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
menu_item_convert_unit_position = 2;
}

sidebar->obj_list()->append_menu_item_convert_unit(menu, menu_item_convert_unit_position);
sidebar->obj_list()->append_menu_items_convert_unit(menu, menu_item_convert_unit_position);
sidebar->obj_list()->append_menu_item_settings(menu);

if (printer_technology != ptSLA)
Expand Down Expand Up @@ -5246,20 +5248,22 @@ void Plater::scale_selection_to_fit_print_volume()
p->scale_selection_to_fit_print_volume();
}

void Plater::convert_unit(bool from_imperial_unit)
void Plater::convert_unit(ConversionType conv_type)
{
std::vector<int> obj_idxs, volume_idxs;
wxGetApp().obj_list()->get_selection_indexes(obj_idxs, volume_idxs);
if (obj_idxs.empty() && volume_idxs.empty())
return;

TakeSnapshot snapshot(this, from_imperial_unit ? _L("Convert from imperial units") : _L("Revert conversion from imperial units"));
TakeSnapshot snapshot(this, conv_type == ConversionType::CONV_FROM_INCH ? _L("Convert from imperial units") :
conv_type == ConversionType::CONV_TO_INCH ? _L("Revert conversion from imperial units") :
conv_type == ConversionType::CONV_FROM_METER ? _L("Convert from meters") : _L("Revert conversion from meters"));
wxBusyCursor wait;

ModelObjectPtrs objects;
for (int obj_idx : obj_idxs) {
ModelObject *object = p->model.objects[obj_idx];
object->convert_units(objects, from_imperial_unit, volume_idxs);
object->convert_units(objects, conv_type, volume_idxs);
remove(obj_idx);
}
p->load_model_objects(objects);
Expand Down
3 changes: 2 additions & 1 deletion src/slic3r/GUI/Plater.hpp
Expand Up @@ -28,6 +28,7 @@ class ModelInstance;
class Print;
class SLAPrint;
enum SLAPrintObjectStep : unsigned int;
enum class ConversionType : int;

using ModelInstancePtrs = std::vector<ModelInstance*>;

Expand Down Expand Up @@ -191,7 +192,7 @@ class Plater: public wxPanel
void fill_bed_with_instances();
bool is_selection_empty() const;
void scale_selection_to_fit_print_volume();
void convert_unit(bool from_imperial_unit);
void convert_unit(ConversionType conv_type);

void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);

Expand Down

0 comments on commit e664100

Please sign in to comment.