Merge pull request #6 from Prusa-Development/pm_support_spots_generator
Pm support spots generator
This commit is contained in:
commit
36c951501e
14 changed files with 1611 additions and 8 deletions
|
@ -46,7 +46,7 @@ BreakConstructorInitializersBeforeComma: false
|
|||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 78
|
||||
ColumnLimit: 140
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/EdgeGrid.hpp"
|
||||
#include "libslic3r/AABBTreeIndirect.hpp"
|
||||
#include "libslic3r/Line.hpp"
|
||||
|
||||
|
|
|
@ -245,6 +245,8 @@ set(SLIC3R_SOURCES
|
|||
SlicingAdaptive.hpp
|
||||
Subdivide.cpp
|
||||
Subdivide.hpp
|
||||
SupportSpotsGenerator.cpp
|
||||
SupportSpotsGenerator.hpp
|
||||
SupportMaterial.cpp
|
||||
SupportMaterial.hpp
|
||||
Surface.cpp
|
||||
|
@ -277,6 +279,8 @@ set(SLIC3R_SOURCES
|
|||
TriangleSelector.hpp
|
||||
TriangleSetSampling.cpp
|
||||
TriangleSetSampling.hpp
|
||||
TriangleSelectorWrapper.cpp
|
||||
TriangleSelectorWrapper.hpp
|
||||
MTUtils.hpp
|
||||
Zipper.hpp
|
||||
Zipper.cpp
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "libslic3r/format.hpp"
|
||||
#include "GCodeProcessor.hpp"
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
|
|
@ -825,6 +825,8 @@ void Print::process()
|
|||
obj->infill();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->ironing();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->generate_support_spots();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->generate_support_material();
|
||||
if (this->set_started(psWipeTower)) {
|
||||
|
|
|
@ -61,7 +61,7 @@ enum PrintStep : unsigned int {
|
|||
|
||||
enum PrintObjectStep : unsigned int {
|
||||
posSlice, posPerimeters, posPrepareInfill,
|
||||
posInfill, posIroning, posSupportMaterial, posCount,
|
||||
posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posCount,
|
||||
};
|
||||
|
||||
// A PrintRegion object represents a group of volumes to print
|
||||
|
@ -381,6 +381,7 @@ private:
|
|||
void prepare_infill();
|
||||
void infill();
|
||||
void ironing();
|
||||
void generate_support_spots();
|
||||
void generate_support_material();
|
||||
|
||||
void slice_volumes();
|
||||
|
|
|
@ -1195,8 +1195,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
update_apply_status(false);
|
||||
}
|
||||
// Invalidate just the supports step.
|
||||
for (const PrintObjectStatus &print_object_status : print_objects_range)
|
||||
for (const PrintObjectStatus &print_object_status : print_objects_range) {
|
||||
update_apply_status(print_object_status.print_object->invalidate_step(posSupportSpotsSearch));
|
||||
update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
|
||||
}
|
||||
if (supports_differ) {
|
||||
// Copy just the support volumes.
|
||||
model_volume_list_update_supports(model_object, model_object_new);
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include "Fill/FillAdaptive.hpp"
|
||||
#include "Fill/FillLightning.hpp"
|
||||
#include "Format/STL.hpp"
|
||||
#include "SupportSpotsGenerator.hpp"
|
||||
#include "TriangleSelectorWrapper.hpp"
|
||||
#include "format.hpp"
|
||||
|
||||
#include <float.h>
|
||||
#include <string_view>
|
||||
|
@ -394,6 +397,65 @@ void PrintObject::ironing()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
std::vector<size_t> problematic_layers = SupportSpotsGenerator::quick_search(this);
|
||||
if (!problematic_layers.empty()) {
|
||||
std::cout << "Object needs supports" << std::endl;
|
||||
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||
L("Supportable issues found. Consider enabling supports for this object"));
|
||||
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||
L("Supportable issues found. Consider enabling supports for this object"));
|
||||
for (size_t index = 0; index < std::min(problematic_layers.size(), size_t(4)); ++index) {
|
||||
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||
format(L("Layer with issues: %1%"), problematic_layers[index] + 1));
|
||||
}
|
||||
}
|
||||
*/
|
||||
void PrintObject::generate_support_spots()
|
||||
{
|
||||
if (this->set_started(posSupportSpotsSearch)) {
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "Searching support spots - start";
|
||||
m_print->set_status(75, L("Searching support spots"));
|
||||
if (this->m_config.support_material && !this->m_config.support_material_auto &&
|
||||
std::all_of(this->model_object()->volumes.begin(), this->model_object()->volumes.end(),
|
||||
[](const ModelVolume* mv){return mv->supported_facets.empty();})
|
||||
) {
|
||||
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values};
|
||||
SupportSpotsGenerator::Issues issues = SupportSpotsGenerator::full_search(this, params);
|
||||
auto obj_transform = this->trafo_centered();
|
||||
for (ModelVolume *model_volume : this->model_object()->volumes) {
|
||||
if (model_volume->is_model_part()) {
|
||||
Transform3d mesh_transformation = obj_transform * model_volume->get_matrix();
|
||||
Transform3d inv_transform = mesh_transformation.inverse();
|
||||
TriangleSelectorWrapper selector { model_volume->mesh(), mesh_transformation};
|
||||
|
||||
for (const SupportSpotsGenerator::SupportPoint &support_point : issues.support_points) {
|
||||
Vec3f point = Vec3f(inv_transform.cast<float>() * support_point.position);
|
||||
Vec3f origin = Vec3f(
|
||||
inv_transform.cast<float>() * Vec3f(support_point.position.x(), support_point.position.y(), 0.0f));
|
||||
selector.enforce_spot(point, origin, support_point.spot_radius);
|
||||
}
|
||||
|
||||
model_volume->supported_facets.set(selector.selector);
|
||||
#if 0 //DEBUG export
|
||||
indexed_triangle_set copy = model_volume->mesh().its;
|
||||
its_transform(copy, obj_transform * model_transformation);
|
||||
its_write_obj(copy,
|
||||
debug_out_path(("model"+std::to_string(model_volume->id().id)+".obj").c_str()).c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "Searching support spots - end";
|
||||
this->set_done(posSupportSpotsSearch);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintObject::generate_support_material()
|
||||
{
|
||||
if (this->set_started(posSupportMaterial)) {
|
||||
|
|
1257
src/libslic3r/SupportSpotsGenerator.cpp
Normal file
1257
src/libslic3r/SupportSpotsGenerator.cpp
Normal file
File diff suppressed because it is too large
Load diff
82
src/libslic3r/SupportSpotsGenerator.hpp
Normal file
82
src/libslic3r/SupportSpotsGenerator.hpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#ifndef SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
||||
#define SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
||||
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace SupportSpotsGenerator {
|
||||
|
||||
struct Params {
|
||||
Params(const std::vector<std::string> &filament_types) {
|
||||
if (filament_types.size() > 1) {
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< "SupportSpotsGenerator does not currently handle different materials properly, only first will be used";
|
||||
}
|
||||
if (filament_types.empty() || filament_types[0].empty()) {
|
||||
BOOST_LOG_TRIVIAL(error)
|
||||
<< "SupportSpotsGenerator error: empty filament_type";
|
||||
filament_type = std::string("PLA");
|
||||
} else {
|
||||
filament_type = filament_types[0];
|
||||
}
|
||||
}
|
||||
|
||||
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
|
||||
const float bridge_distance = 12.0f; //mm
|
||||
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) )
|
||||
const float overhang_angle_deg = 80.0f;
|
||||
const std::pair<float,float> malformation_angle_span_deg = std::pair<float, float> { 45.0f, 80.0f };
|
||||
|
||||
const float min_distance_between_support_points = 3.0f; //mm
|
||||
const float support_points_interface_radius = 1.5f; // mm
|
||||
const float connections_min_considerable_area = 1.5f; //mm^2
|
||||
const float small_parts_threshold = 5.0f; //mm^3
|
||||
const float small_parts_support_points_interface_radius = 3.0f; // mm
|
||||
|
||||
std::string filament_type;
|
||||
const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position.
|
||||
const float max_acceleration = 9 * 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the jerk phase, so the usual machine limits are too low)
|
||||
const double filament_density = 1.25e-3f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important
|
||||
const double material_yield_strength = 33.0f * 1e6f; // (g*mm/s^2)/mm^2; 33 MPa is yield strength of ABS, which has the lowest yield strength from common materials.
|
||||
const float standard_extruder_conflict_force = 20.0f * gravity_constant; // force that can occasionally push the model due to various factors (filament leaks, small curling, ... );
|
||||
const float malformations_additive_conflict_extruder_force = 300.0f * gravity_constant; // for areas with possible high layered curled filaments
|
||||
|
||||
// MPa * 1e^6 = (g*mm/s^2)/mm^2 = g/(mm*s^2); yield strength of the bed surface
|
||||
double get_bed_adhesion_yield_strength() const {
|
||||
if (filament_type == "PLA") {
|
||||
return 0.018 * 1e6;
|
||||
} else if (filament_type == "PET" || filament_type == "PETG") {
|
||||
return 0.3 * 1e6;
|
||||
} else { //PLA default value - defensive approach, PLA has quite low adhesion
|
||||
return 0.018 * 1e6;
|
||||
}
|
||||
}
|
||||
|
||||
//just return PLA adhesion value as value for supports
|
||||
double get_support_spots_adhesion_strength() const {
|
||||
return 0.018f * 1e6;
|
||||
}
|
||||
};
|
||||
|
||||
struct SupportPoint {
|
||||
SupportPoint(const Vec3f &position, float force, float spot_radius, const Vec3f &direction);
|
||||
Vec3f position;
|
||||
float force;
|
||||
float spot_radius;
|
||||
Vec3f direction;
|
||||
};
|
||||
|
||||
struct Issues {
|
||||
std::vector<SupportPoint> support_points;
|
||||
};
|
||||
|
||||
// std::vector<size_t> quick_search(const PrintObject *po, const Params ¶ms);
|
||||
Issues full_search(const PrintObject *po, const Params ¶ms);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_ */
|
46
src/libslic3r/TriangleSelectorWrapper.cpp
Normal file
46
src/libslic3r/TriangleSelectorWrapper.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include "TriangleSelectorWrapper.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
TriangleSelectorWrapper::TriangleSelectorWrapper(const TriangleMesh &mesh, const Transform3d& mesh_transform) :
|
||||
mesh(mesh), mesh_transform(mesh_transform), selector(mesh), triangles_tree(
|
||||
AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(mesh.its.vertices, mesh.its.indices)) {
|
||||
|
||||
}
|
||||
|
||||
void TriangleSelectorWrapper::enforce_spot(const Vec3f &point, const Vec3f &origin, float radius) {
|
||||
std::vector<igl::Hit> hits;
|
||||
Vec3f dir = (point - origin).normalized();
|
||||
if (AABBTreeIndirect::intersect_ray_all_hits(mesh.its.vertices, mesh.its.indices, triangles_tree,
|
||||
Vec3d(origin.cast<double>()),
|
||||
Vec3d(dir.cast<double>()),
|
||||
hits)) {
|
||||
for (int hit_idx = hits.size() - 1; hit_idx >= 0; --hit_idx) {
|
||||
const igl::Hit &hit = hits[hit_idx];
|
||||
Vec3f pos = origin + dir * hit.t;
|
||||
Vec3f face_normal = its_face_normal(mesh.its, hit.id);
|
||||
if ((point - pos).norm() < radius && face_normal.dot(dir) < 0) {
|
||||
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
|
||||
pos, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
|
||||
selector.select_patch(hit.id, std::move(cursor), EnforcerBlockerType::ENFORCER, Transform3d::Identity(),
|
||||
true, 0.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
size_t hit_idx_out;
|
||||
Vec3f hit_point_out;
|
||||
float dist = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(mesh.its.vertices, mesh.its.indices,
|
||||
triangles_tree, point, hit_idx_out, hit_point_out);
|
||||
if (dist < radius) {
|
||||
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
|
||||
point, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
|
||||
selector.select_patch(hit_idx_out, std::move(cursor), EnforcerBlockerType::ENFORCER,
|
||||
Transform3d::Identity(),
|
||||
true, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
31
src/libslic3r/TriangleSelectorWrapper.hpp
Normal file
31
src/libslic3r/TriangleSelectorWrapper.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_
|
||||
#define SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_
|
||||
|
||||
#include "TriangleSelector.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "AABBTreeIndirect.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
//NOTE: We need to replace the FacetsAnnotation struct for support storage (or extend/add another)
|
||||
// Problems: Does not support negative volumes, strange usage for supports computed from extrusion -
|
||||
// expensively converted back to triangles and then sliced again.
|
||||
// Another problem is weird and very limited interface when painting supports via algorithms
|
||||
|
||||
|
||||
class TriangleSelectorWrapper {
|
||||
public:
|
||||
const TriangleMesh &mesh;
|
||||
const Transform3d& mesh_transform;
|
||||
TriangleSelector selector;
|
||||
AABBTreeIndirect::Tree<3, float> triangles_tree;
|
||||
|
||||
TriangleSelectorWrapper(const TriangleMesh &mesh, const Transform3d& mesh_transform);
|
||||
|
||||
void enforce_spot(const Vec3f &point, const Vec3f& origin, float radius);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_ */
|
|
@ -10,6 +10,8 @@
|
|||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/format.hpp"
|
||||
#include "slic3r/Utils/UndoRedo.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
@ -39,6 +41,8 @@ bool GLGizmoFdmSupports::on_init()
|
|||
{
|
||||
m_shortcut_key = WXK_CONTROL_L;
|
||||
|
||||
m_desc["auto_generate"] = _L("Auto-generate supports");
|
||||
m_desc["generating"] = _L("Generating supports...");
|
||||
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
|
||||
m_desc["reset_direction"] = _L("Reset direction");
|
||||
m_desc["cursor_size"] = _L("Brush size") + ": ";
|
||||
|
@ -91,7 +95,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
|||
if (! m_c->selection_info()->model_object())
|
||||
return;
|
||||
|
||||
const float approx_height = m_imgui->scaled(23.f);
|
||||
const float approx_height = m_imgui->scaled(25.f);
|
||||
y = std::min(y, bottom_limit - approx_height);
|
||||
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||
|
||||
|
@ -153,6 +157,15 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
|||
|
||||
ImGui::Separator();
|
||||
|
||||
if (waiting_for_autogenerated_supports) {
|
||||
m_imgui->text(m_desc.at("generating"));
|
||||
} else {
|
||||
bool generate = m_imgui->button(m_desc.at("auto_generate"));
|
||||
if (generate)
|
||||
auto_generate();
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
float position_before_text_y = ImGui::GetCursorPos().y;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text_wrapped(m_desc["highlight_by_angle"] + ":", autoset_slider_label_max_width);
|
||||
|
@ -319,6 +332,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
|||
}
|
||||
|
||||
update_model_object();
|
||||
this->waiting_for_autogenerated_supports = false;
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
|
||||
|
@ -366,9 +380,54 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
|
|||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
||||
: _L("Add supports by angle"));
|
||||
update_model_object();
|
||||
this->waiting_for_autogenerated_supports = false;
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
|
||||
void GLGizmoFdmSupports::data_changed()
|
||||
{
|
||||
GLGizmoPainterBase::data_changed();
|
||||
if (! m_c->selection_info())
|
||||
return;
|
||||
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
if (mo && this->waiting_for_autogenerated_supports) {
|
||||
get_data_from_backend();
|
||||
} else {
|
||||
this->waiting_for_autogenerated_supports = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoFdmSupports::get_data_from_backend()
|
||||
{
|
||||
if (! has_backend_supports())
|
||||
return;
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
|
||||
// find the respective PrintObject, we need a pointer to it
|
||||
for (const PrintObject* po : m_parent.fff_print()->objects()) {
|
||||
if (po->model_object()->id() == mo->id()) {
|
||||
std::unordered_map<size_t, const ModelVolume*> mvs;
|
||||
for (const ModelVolume* mv : po->model_object()->volumes) {
|
||||
if (mv->is_model_part()) {
|
||||
mvs.emplace(mv->id().id, mv);
|
||||
}
|
||||
}
|
||||
int mesh_id = -1.0f;
|
||||
for (ModelVolume* mv : mo->volumes){
|
||||
if (mv->is_model_part()){
|
||||
mesh_id++;
|
||||
mv->supported_facets.assign(mvs[mv->id().id]->supported_facets);
|
||||
m_triangle_selectors[mesh_id]->deserialize(mv->supported_facets.get_data(), true);
|
||||
m_triangle_selectors[mesh_id]->request_update_render_data();
|
||||
}
|
||||
}
|
||||
this->waiting_for_autogenerated_supports = false;
|
||||
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLGizmoFdmSupports::update_model_object() const
|
||||
|
@ -391,8 +450,6 @@ void GLGizmoFdmSupports::update_model_object() const
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoFdmSupports::update_from_model_object()
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
|
@ -417,6 +474,58 @@ void GLGizmoFdmSupports::update_from_model_object()
|
|||
}
|
||||
}
|
||||
|
||||
bool GLGizmoFdmSupports::has_backend_supports() const
|
||||
{
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
if (! mo)
|
||||
return false;
|
||||
|
||||
// find PrintObject with this ID
|
||||
for (const PrintObject* po : m_parent.fff_print()->objects()) {
|
||||
if (po->model_object()->id() == mo->id())
|
||||
return po->is_step_done(posSupportSpotsSearch);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLGizmoFdmSupports::reslice_FDM_supports(bool postpone_error_messages) const {
|
||||
wxGetApp().CallAfter(
|
||||
[this, postpone_error_messages]() {
|
||||
wxGetApp().plater()->reslice_FFF_until_step(posSupportSpotsSearch,
|
||||
*m_c->selection_info()->model_object(), postpone_error_messages);
|
||||
});
|
||||
}
|
||||
|
||||
void GLGizmoFdmSupports::auto_generate()
|
||||
{
|
||||
ModelObject *mo = m_c->selection_info()->model_object();
|
||||
bool not_painted = std::all_of(mo->volumes.begin(), mo->volumes.end(), [](const ModelVolume* vol){
|
||||
return vol->type() != ModelVolumeType::MODEL_PART || vol->supported_facets.empty();
|
||||
});
|
||||
|
||||
MessageDialog dlg(GUI::wxGetApp().plater(),
|
||||
_L("Autogeneration will erase all currently painted areas.") + "\n\n" +
|
||||
_L("Are you sure you want to do it?") + "\n",
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
|
||||
if (not_painted || dlg.ShowModal() == wxID_YES) {
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points"));
|
||||
int mesh_id = -1.0f;
|
||||
for (ModelVolume *mv : mo->volumes) {
|
||||
if (mv->is_model_part()) {
|
||||
mesh_id++;
|
||||
mv->supported_facets.reset();
|
||||
m_triangle_selectors[mesh_id]->reset();
|
||||
m_triangle_selectors[mesh_id]->request_update_render_data();
|
||||
}
|
||||
}
|
||||
|
||||
mo->config.set("support_material", true);
|
||||
mo->config.set("support_material_auto", false);
|
||||
this->waiting_for_autogenerated_supports = true;
|
||||
wxGetApp().CallAfter([this]() { reslice_FDM_supports(); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PainterGizmoType GLGizmoFdmSupports::get_painter_type() const
|
||||
|
|
|
@ -26,6 +26,7 @@ protected:
|
|||
|
||||
private:
|
||||
bool on_init() override;
|
||||
void data_changed() override;
|
||||
|
||||
void update_model_object() const override;
|
||||
void update_from_model_object() override;
|
||||
|
@ -39,6 +40,13 @@ private:
|
|||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||
std::map<std::string, wxString> m_desc;
|
||||
|
||||
|
||||
bool waiting_for_autogenerated_supports = false;
|
||||
bool has_backend_supports() const;
|
||||
void reslice_FDM_supports(bool postpone_error_messages = false) const;
|
||||
void auto_generate();
|
||||
void get_data_from_backend();
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue