Export to STL of SLA supports and pad

This commit is contained in:
Enrico Turri 2019-05-02 13:46:39 +02:00
parent 4a5992ba6e
commit a3385278e5
5 changed files with 95 additions and 15 deletions

View file

@ -1147,7 +1147,7 @@ void ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu)
void ObjectList::append_menu_item_export_stl(wxMenu* menu) const void ObjectList::append_menu_item_export_stl(wxMenu* menu) const
{ {
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, "", append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, "",
[](wxCommandEvent&) { wxGetApp().plater()->export_stl(true); }, "", menu); [](wxCommandEvent&) { wxGetApp().plater()->export_stl(false, true); }, "", menu);
menu->AppendSeparator(); menu->AppendSeparator();
} }

View file

@ -14,6 +14,7 @@
#include "libslic3r/Print.hpp" #include "libslic3r/Print.hpp"
#include "libslic3r/Polygon.hpp" #include "libslic3r/Polygon.hpp"
#include "libslic3r/SLAPrint.hpp"
#include "Tab.hpp" #include "Tab.hpp"
#include "PresetBundle.hpp" #include "PresetBundle.hpp"
@ -205,12 +206,30 @@ void MainFrame::add_created_tab(Tab* panel)
bool MainFrame::can_save() const bool MainFrame::can_save() const
{ {
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false; return (m_plater != nullptr) && !m_plater->model().objects.empty();
} }
bool MainFrame::can_export_model() const bool MainFrame::can_export_model() const
{ {
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false; return (m_plater != nullptr) && !m_plater->model().objects.empty();
}
bool MainFrame::can_export_supports() const
{
if ((m_plater == nullptr) || (m_plater->printer_technology() != ptSLA) || m_plater->model().objects.empty())
return false;
bool can_export = false;
const PrintObjects& objects = m_plater->sla_print().objects();
for (const SLAPrintObject* object : objects)
{
if (object->has_mesh(slaposBasePool) || object->has_mesh(slaposSupportTree))
{
can_export = true;
break;
}
}
return can_export;
} }
bool MainFrame::can_export_gcode() const bool MainFrame::can_export_gcode() const
@ -243,17 +262,17 @@ bool MainFrame::can_change_view() const
bool MainFrame::can_select() const bool MainFrame::can_select() const
{ {
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false; return (m_plater != nullptr) && !m_plater->model().objects.empty();
} }
bool MainFrame::can_delete() const bool MainFrame::can_delete() const
{ {
return (m_plater != nullptr) ? !m_plater->is_selection_empty() : false; return (m_plater != nullptr) && !m_plater->is_selection_empty();
} }
bool MainFrame::can_delete_all() const bool MainFrame::can_delete_all() const
{ {
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false; return (m_plater != nullptr) && !m_plater->model().objects.empty();
} }
void MainFrame::on_dpi_changed(const wxRect &suggested_rect) void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
@ -346,6 +365,8 @@ void MainFrame::init_menubar()
export_menu->AppendSeparator(); export_menu->AppendSeparator();
wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")), wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, menu_icon("export_plater")); [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, menu_icon("export_plater"));
wxMenuItem* item_export_stl_sla = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as STL including supports")) + dots, _(L("Export current plate as STL including supports")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(true); }, menu_icon("export_plater"));
wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")), wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, menu_icon("export_plater")); [this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, menu_icon("export_plater"));
export_menu->AppendSeparator(); export_menu->AppendSeparator();
@ -389,13 +410,14 @@ void MainFrame::init_menubar()
[this](wxCommandEvent&) { Close(false); }); [this](wxCommandEvent&) { Close(false); });
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_save()); }, item_save->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_save()); }, item_save->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_save()); }, item_save_as->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_save()); }, item_save_as->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_import_model->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_import_model->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_gcode()); }, item_export_gcode->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_gcode()); }, item_export_gcode->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_model()); }, item_export_stl->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_model()); }, item_export_stl->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_model()); }, item_export_amf->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_supports()); }, item_export_stl_sla->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_slice()); }, m_menu_item_reslice_now->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_model()); }, item_export_amf->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_slice()); }, m_menu_item_reslice_now->GetId());
} }
#ifdef _MSC_VER #ifdef _MSC_VER

View file

@ -63,6 +63,7 @@ class MainFrame : public DPIFrame
bool can_save() const; bool can_save() const;
bool can_export_model() const; bool can_export_model() const;
bool can_export_supports() const;
bool can_export_gcode() const; bool can_export_gcode() const;
bool can_slice() const; bool can_slice() const;
bool can_change_view() const; bool can_change_view() const;

View file

@ -2925,7 +2925,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
[this](wxCommandEvent&) { reload_from_disk(); }); [this](wxCommandEvent&) { reload_from_disk(); });
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, _(L("Export the selected object as STL file")), append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, _(L("Export the selected object as STL file")),
[this](wxCommandEvent&) { q->export_stl(true); }); [this](wxCommandEvent&) { q->export_stl(false, true); });
menu->AppendSeparator(); menu->AppendSeparator();
} }
@ -3431,7 +3431,7 @@ void Plater::export_gcode()
p->export_gcode(std::move(output_path), PrintHostJob()); p->export_gcode(std::move(output_path), PrintHostJob());
} }
void Plater::export_stl(bool selection_only) void Plater::export_stl(bool extended, bool selection_only)
{ {
if (p->model.objects.empty()) { return; } if (p->model.objects.empty()) { return; }
@ -3466,8 +3466,65 @@ void Plater::export_stl(bool selection_only)
} }
} }
else else
{
mesh = p->model.mesh(); mesh = p->model.mesh();
if (extended && (p->printer_technology == ptSLA))
{
const PrintObjects& objects = p->sla_print.objects();
for (const SLAPrintObject* object : objects)
{
const ModelObject* model_object = object->model_object();
Transform3d mesh_trafo_inv = object->trafo().inverse();
bool is_left_handed = object->is_left_handed();
TriangleMesh pad_mesh;
bool has_pad_mesh = object->has_mesh(slaposBasePool);
if (has_pad_mesh)
{
pad_mesh = object->get_mesh(slaposBasePool);
pad_mesh.transform(mesh_trafo_inv);
}
TriangleMesh supports_mesh;
bool has_supports_mesh = object->has_mesh(slaposSupportTree);
if (has_supports_mesh)
{
supports_mesh = object->get_mesh(slaposSupportTree);
supports_mesh.transform(mesh_trafo_inv);
}
const std::vector<SLAPrintObject::Instance>& obj_instances = object->instances();
for (const SLAPrintObject::Instance& obj_instance : obj_instances)
{
auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
[&obj_instance](const ModelInstance *mi) { return mi->id() == obj_instance.instance_id; });
assert(it != model_object->instances.end());
if (it != model_object->instances.end())
{
int instance_idx = it - model_object->instances.begin();
const Transform3d& inst_transform = object->model_object()->instances[instance_idx]->get_transformation().get_matrix();
if (has_pad_mesh)
{
TriangleMesh inst_pad_mesh = pad_mesh;
inst_pad_mesh.transform(inst_transform, is_left_handed);
mesh.merge(inst_pad_mesh);
}
if (has_supports_mesh)
{
TriangleMesh inst_supports_mesh = supports_mesh;
inst_supports_mesh.transform(inst_transform, is_left_handed);
mesh.merge(inst_supports_mesh);
}
}
}
}
}
}
Slic3r::store_stl(path_u8.c_str(), &mesh, true); Slic3r::store_stl(path_u8.c_str(), &mesh, true);
p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path)); p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path));
} }

View file

@ -163,7 +163,7 @@ public:
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); 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);
void export_gcode(); void export_gcode();
void export_stl(bool selection_only = false); void export_stl(bool extended = false, bool selection_only = false);
void export_amf(); void export_amf();
void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path()); void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
void reslice(); void reslice();