mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 00:36:25 +08:00
Removed visualization of clearance contours and the test for horizontal and vertical clearance
This commit is contained in:
parent
c6cee75ee3
commit
e43ff45dac
@ -432,89 +432,6 @@ bool Print::has_brim() const
|
||||
return std::any_of(m_objects.begin(), m_objects.end(), [](PrintObject *object) { return object->has_brim(); });
|
||||
}
|
||||
|
||||
bool Print::sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons)
|
||||
{
|
||||
Polygons convex_hulls_other;
|
||||
if (polygons != nullptr)
|
||||
polygons->clear();
|
||||
std::vector<size_t> intersecting_idxs;
|
||||
|
||||
std::map<ObjectID, Polygon> map_model_object_to_convex_hull;
|
||||
for (const PrintObject *print_object : print.objects()) {
|
||||
assert(! print_object->model_object()->instances.empty());
|
||||
assert(! print_object->instances().empty());
|
||||
ObjectID model_object_id = print_object->model_object()->id();
|
||||
auto it_convex_hull = map_model_object_to_convex_hull.find(model_object_id);
|
||||
// Get convex hull of all printable volumes assigned to this print object.
|
||||
ModelInstance *model_instance0 = print_object->model_object()->instances.front();
|
||||
if (it_convex_hull == map_model_object_to_convex_hull.end()) {
|
||||
// Calculate the convex hull of a printable object.
|
||||
// Grow convex hull with the clearance margin.
|
||||
// FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2)
|
||||
// which causes that the warning will be showed after arrangement with the
|
||||
// appropriate object distance. Even if I set this to jtMiter the warning still shows up.
|
||||
Geometry::Transformation trafo = model_instance0->get_transformation();
|
||||
trafo.set_offset({ 0.0, 0.0, model_instance0->get_offset().z() });
|
||||
Polygon ch2d = print_object->model_object()->convex_hull_2d(trafo.get_matrix());
|
||||
Polygons offs_ch2d = offset(ch2d,
|
||||
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
|
||||
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
|
||||
float(scale_(0.5 * print.config().extruder_clearance_radius.value - BuildVolume::BedEpsilon)), jtRound, scale_(0.1));
|
||||
// for invalid geometries the vector returned by offset() may be empty
|
||||
if (!offs_ch2d.empty())
|
||||
it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id, offs_ch2d.front());
|
||||
}
|
||||
if (it_convex_hull != map_model_object_to_convex_hull.end()) {
|
||||
// Make a copy, so it may be rotated for instances.
|
||||
Polygon convex_hull0 = it_convex_hull->second;
|
||||
const double z_diff = Geometry::rotation_diff_z(model_instance0->get_matrix(), print_object->instances().front().model_instance->get_matrix());
|
||||
if (std::abs(z_diff) > EPSILON)
|
||||
convex_hull0.rotate(z_diff);
|
||||
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
||||
for (const PrintInstance& instance : print_object->instances()) {
|
||||
Polygon convex_hull = convex_hull0;
|
||||
// instance.shift is a position of a centered object, while model object may not be centered.
|
||||
// Convert the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset.
|
||||
convex_hull.translate(instance.shift - print_object->center_offset());
|
||||
// if output needed, collect indices (inside convex_hulls_other) of intersecting hulls
|
||||
for (size_t i = 0; i < convex_hulls_other.size(); ++i) {
|
||||
if (!intersection(convex_hulls_other[i], convex_hull).empty()) {
|
||||
if (polygons == nullptr)
|
||||
return false;
|
||||
else {
|
||||
intersecting_idxs.emplace_back(i);
|
||||
intersecting_idxs.emplace_back(convex_hulls_other.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
convex_hulls_other.emplace_back(std::move(convex_hull));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!intersecting_idxs.empty()) {
|
||||
// use collected indices (inside convex_hulls_other) to update output
|
||||
std::sort(intersecting_idxs.begin(), intersecting_idxs.end());
|
||||
intersecting_idxs.erase(std::unique(intersecting_idxs.begin(), intersecting_idxs.end()), intersecting_idxs.end());
|
||||
for (size_t i : intersecting_idxs) {
|
||||
polygons->emplace_back(std::move(convex_hulls_other[i]));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sequential_print_vertical_clearance_valid(const Print &print)
|
||||
{
|
||||
std::vector<const PrintInstance*> print_instances_ordered = sort_object_instances_by_model_order(print);
|
||||
// Ignore the last instance printed.
|
||||
print_instances_ordered.pop_back();
|
||||
// Find the other highest instance.
|
||||
auto it = std::max_element(print_instances_ordered.begin(), print_instances_ordered.end(), [](auto l, auto r) {
|
||||
return l->print_object->height() < r->print_object->height();
|
||||
});
|
||||
return it == print_instances_ordered.end() || (*it)->print_object->height() <= scale_(print.config().extruder_clearance_height.value);
|
||||
}
|
||||
|
||||
// Matches "G92 E0" with various forms of writing the zero and with an optional comment.
|
||||
boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" };
|
||||
@ -545,13 +462,9 @@ std::string Print::validate(std::vector<std::string>* warnings) const
|
||||
return _u8L("The supplied settings will cause an empty print.");
|
||||
|
||||
if (m_config.complete_objects) {
|
||||
if (!sequential_print_horizontal_clearance_valid(*this, const_cast<Polygons*>(&m_sequential_print_clearance_contours)))
|
||||
if (false) // LUKAS: To be fixed in the next commit.
|
||||
return _u8L("Some objects are too close; your extruder will collide with them.");
|
||||
if (!sequential_print_vertical_clearance_valid(*this))
|
||||
return _u8L("Some objects are too tall and cannot be printed without extruder collisions.");
|
||||
}
|
||||
else
|
||||
const_cast<Polygons*>(&m_sequential_print_clearance_contours)->clear();
|
||||
|
||||
if (m_config.avoid_crossing_perimeters && m_config.avoid_crossing_curled_overhangs) {
|
||||
return _u8L("Avoid crossing perimeters option and avoid crossing curled overhangs option cannot be both enabled together.");
|
||||
|
@ -688,9 +688,6 @@ public:
|
||||
const PrintRegion& get_print_region(size_t idx) const { return *m_print_regions[idx]; }
|
||||
const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; }
|
||||
|
||||
const Polygons& get_sequential_print_clearance_contours() const { return m_sequential_print_clearance_contours; }
|
||||
static bool sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons = nullptr);
|
||||
|
||||
// Returns if all used filaments have same shrinkage compensations.
|
||||
bool has_same_shrinkage_compensations() const;
|
||||
|
||||
@ -744,9 +741,6 @@ private:
|
||||
// Estimated print time, filament consumed.
|
||||
PrintStatistics m_print_statistics;
|
||||
|
||||
// Cache to store sequential print clearance contours
|
||||
Polygons m_sequential_print_clearance_contours;
|
||||
|
||||
// To allow GCode to set the Print's GCodeExport step status.
|
||||
friend class GCodeGenerator;
|
||||
// To allow GCodeProcessor to emit warnings.
|
||||
|
@ -124,8 +124,6 @@ void GLCanvas3D::select_bed(int i, bool triggered_by_user)
|
||||
}
|
||||
}
|
||||
wxGetApp().plater()->canvas3D()->m_process->stop();
|
||||
m_sequential_print_clearance.m_evaluating = true;
|
||||
reset_sequential_print_clearance();
|
||||
|
||||
post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, is_sliceable(s_print_statuses[i])));
|
||||
|
||||
@ -987,141 +985,6 @@ void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
void GLCanvas3D::SequentialPrintClearance::set_contours(const ContoursList& contours, bool generate_fill)
|
||||
{
|
||||
m_contours.clear();
|
||||
m_instances.clear();
|
||||
m_fill.reset();
|
||||
|
||||
if (contours.empty())
|
||||
return;
|
||||
|
||||
const Vec3d bed_offset = generate_fill ? s_multiple_beds.get_bed_translation(s_multiple_beds.get_active_bed()) : Vec3d::Zero();
|
||||
|
||||
if (generate_fill) {
|
||||
GLModel::Geometry fill_data;
|
||||
fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
|
||||
fill_data.color = { 0.3333f, 0.0f, 0.0f, 0.5f };
|
||||
|
||||
// vertices + indices
|
||||
const ExPolygons polygons_union = union_ex(contours.contours);
|
||||
unsigned int vertices_counter = 0;
|
||||
for (const ExPolygon& poly : polygons_union) {
|
||||
const std::vector<Vec3d> triangulation = triangulate_expolygon_3d(poly);
|
||||
fill_data.reserve_vertices(fill_data.vertices_count() + triangulation.size());
|
||||
fill_data.reserve_indices(fill_data.indices_count() + triangulation.size());
|
||||
for (const Vec3d& v : triangulation) {
|
||||
fill_data.add_vertex((Vec3f)((bed_offset + v).cast<float>() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting
|
||||
++vertices_counter;
|
||||
if (vertices_counter % 3 == 0)
|
||||
fill_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
|
||||
}
|
||||
}
|
||||
m_fill.init_from(std::move(fill_data));
|
||||
}
|
||||
|
||||
const Transform3d bed_transform = Geometry::translation_transform(bed_offset);
|
||||
|
||||
for (size_t i = 0; i < contours.contours.size(); ++i) {
|
||||
GLModel& model = m_contours.emplace_back(GLModel());
|
||||
model.init_from(contours.contours[i], 0.025f); // add a small positive z to avoid z-fighting
|
||||
}
|
||||
|
||||
if (contours.trafos.has_value()) {
|
||||
// create the requested instances
|
||||
for (const auto& instance : *contours.trafos) {
|
||||
m_instances.emplace_back(instance.first, bed_transform * instance.second);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no instances have been specified
|
||||
// create one instance for every polygon
|
||||
for (size_t i = 0; i < contours.contours.size(); ++i) {
|
||||
m_instances.emplace_back(i, bed_transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::SequentialPrintClearance::update_instances_trafos(const std::vector<Transform3d>& trafos)
|
||||
{
|
||||
if (trafos.size() == m_instances.size()) {
|
||||
for (size_t i = 0; i < trafos.size(); ++i) {
|
||||
m_instances[i].second = trafos[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void GLCanvas3D::SequentialPrintClearance::render()
|
||||
{
|
||||
static const ColorRGBA FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f };
|
||||
static const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f };
|
||||
static const ColorRGBA NO_FILL_EVALUATING_COLOR = { 1.0f, 1.0f, 0.0f, 1.0f };
|
||||
|
||||
if (m_contours.empty() || m_instances.empty())
|
||||
return;
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
if (!m_evaluating && !m_dragging)
|
||||
m_fill.render();
|
||||
|
||||
#if !SLIC3R_OPENGL_ES
|
||||
if (OpenGLManager::get_gl_info().is_core_profile()) {
|
||||
#endif // !SLIC3R_OPENGL_ES
|
||||
shader->stop_using();
|
||||
|
||||
#if SLIC3R_OPENGL_ES
|
||||
shader = wxGetApp().get_shader("dashed_lines");
|
||||
#else
|
||||
shader = wxGetApp().get_shader("dashed_thick_lines");
|
||||
#endif // SLIC3R_OPENGL_ES
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
const std::array<int, 4>& viewport = camera.get_viewport();
|
||||
shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3])));
|
||||
shader->set_uniform("width", 1.0f);
|
||||
shader->set_uniform("gap_size", 0.0f);
|
||||
#if !SLIC3R_OPENGL_ES
|
||||
}
|
||||
else
|
||||
glsafe(::glLineWidth(2.0f));
|
||||
#endif // !SLIC3R_OPENGL_ES
|
||||
|
||||
const ColorRGBA color = (!m_evaluating && !m_dragging && m_fill.is_initialized()) ? FILL_COLOR :
|
||||
m_evaluating ? NO_FILL_EVALUATING_COLOR : NO_FILL_COLOR;
|
||||
|
||||
for (const auto& [id, trafo] : m_instances) {
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * trafo);
|
||||
assert(id < m_contours.size());
|
||||
m_contours[id].set_color(color);
|
||||
m_contours[id].render();
|
||||
}
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent);
|
||||
@ -2324,7 +2187,6 @@ void GLCanvas3D::render()
|
||||
_render_gcode();
|
||||
_render_objects(GLVolumeCollection::ERenderType::Transparent);
|
||||
|
||||
_render_sequential_clearance();
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
_render_selection_center();
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
@ -3975,8 +3837,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
c == GLGizmosManager::EType::Scale ||
|
||||
c == GLGizmosManager::EType::Rotate) {
|
||||
show_sinking_contours();
|
||||
if (_is_sequential_print_enabled())
|
||||
update_sequential_clearance(true);
|
||||
}
|
||||
}
|
||||
else if (evt.LeftUp() &&
|
||||
@ -4135,10 +3995,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_selection.setup_cache();
|
||||
if (!evt.CmdDown())
|
||||
m_mouse.drag.start_position_3D = m_mouse.scene_position;
|
||||
m_sequential_print_clearance.m_first_displacement = true;
|
||||
if (_is_sequential_print_enabled())
|
||||
update_sequential_clearance(true);
|
||||
m_sequential_print_clearance.start_dragging();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4187,8 +4043,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
TransformationType trafo_type;
|
||||
trafo_type.set_relative();
|
||||
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D, trafo_type);
|
||||
if (_is_sequential_print_enabled())
|
||||
update_sequential_clearance(false);
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
m_dirty = true;
|
||||
|
||||
@ -4266,8 +4120,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) {
|
||||
m_mouse.position = pos.cast<double>();
|
||||
|
||||
if (evt.LeftUp() && m_sequential_print_clearance.is_dragging())
|
||||
m_sequential_print_clearance.stop_dragging();
|
||||
if (evt.RightUp() && m_mouse.is_start_position_2D_defined()) {
|
||||
// forces camera target to be on the plane z = 0
|
||||
Camera& camera = wxGetApp().plater()->get_camera();
|
||||
@ -4547,11 +4399,6 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_WIPETOWER_TOUCHED));
|
||||
}
|
||||
|
||||
if (_is_sequential_print_enabled()) {
|
||||
update_sequential_clearance(true);
|
||||
m_sequential_print_clearance.m_evaluating = true;
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@ -4645,11 +4492,6 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||
if (!done.empty())
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED));
|
||||
|
||||
if (_is_sequential_print_enabled()) {
|
||||
update_sequential_clearance(true);
|
||||
m_sequential_print_clearance.m_evaluating = true;
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@ -4722,11 +4564,6 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
||||
if (!done.empty())
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_SCALED));
|
||||
|
||||
if (_is_sequential_print_enabled()) {
|
||||
update_sequential_clearance(true);
|
||||
m_sequential_print_clearance.m_evaluating = true;
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@ -4980,137 +4817,6 @@ void GLCanvas3D::mouse_up_cleanup()
|
||||
m_canvas->ReleaseMouse();
|
||||
}
|
||||
|
||||
void GLCanvas3D::update_sequential_clearance(bool force_contours_generation)
|
||||
{
|
||||
if (!_is_sequential_print_enabled())
|
||||
return;
|
||||
|
||||
if (m_layers_editing.is_enabled())
|
||||
return;
|
||||
|
||||
auto instance_transform_from_volumes = [this](int object_idx, int instance_idx) {
|
||||
for (const GLVolume* v : m_volumes.volumes) {
|
||||
if (v->object_idx() == object_idx && v->instance_idx() == instance_idx)
|
||||
return v->get_instance_transformation();
|
||||
}
|
||||
assert(false);
|
||||
return Geometry::Transformation();
|
||||
};
|
||||
|
||||
auto is_object_outside_printbed = [this](int object_idx) {
|
||||
for (const GLVolume* v : m_volumes.volumes) {
|
||||
if (v->object_idx() == object_idx && v->is_outside)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// collects instance transformations from volumes
|
||||
// first: define temporary cache
|
||||
unsigned int instances_count = 0;
|
||||
std::vector<std::vector<std::optional<Geometry::Transformation>>> instance_transforms;
|
||||
for (size_t obj = 0; obj < m_model->objects.size(); ++obj) {
|
||||
instance_transforms.emplace_back(std::vector<std::optional<Geometry::Transformation>>());
|
||||
const ModelObject* model_object = m_model->objects[obj];
|
||||
for (size_t i = 0; i < model_object->instances.size(); ++i) {
|
||||
instance_transforms[obj].emplace_back(std::optional<Geometry::Transformation>());
|
||||
++instances_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (instances_count == 1)
|
||||
return;
|
||||
|
||||
// second: fill temporary cache with data from volumes
|
||||
for (const GLVolume* v : m_volumes.volumes) {
|
||||
if (v->is_wipe_tower())
|
||||
continue;
|
||||
|
||||
const int object_idx = v->object_idx();
|
||||
const int instance_idx = v->instance_idx();
|
||||
auto& transform = instance_transforms[object_idx][instance_idx];
|
||||
if (!transform.has_value())
|
||||
transform = instance_transform_from_volumes(object_idx, instance_idx);
|
||||
}
|
||||
|
||||
// helper function to calculate the transformation to be applied to the sequential print clearance contours
|
||||
auto instance_trafo = [](const Transform3d& hull_trafo, const Geometry::Transformation& inst_trafo) {
|
||||
Vec3d offset = inst_trafo.get_offset() - hull_trafo.translation();
|
||||
offset.z() = 0.0;
|
||||
return Geometry::translation_transform(offset) *
|
||||
Geometry::rotation_transform(Geometry::rotation_diff_z(hull_trafo, inst_trafo.get_matrix()) * Vec3d::UnitZ());
|
||||
};
|
||||
|
||||
// calculates objects 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid())
|
||||
// this is done only the first time this method is called while moving the mouse,
|
||||
// the results are then cached for following displacements
|
||||
if (force_contours_generation || m_sequential_print_clearance.m_first_displacement) {
|
||||
m_sequential_print_clearance.m_evaluating = false;
|
||||
m_sequential_print_clearance.m_hulls_2d_cache.clear();
|
||||
const float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON));
|
||||
const double mitter_limit = scale_(0.1);
|
||||
m_sequential_print_clearance.m_hulls_2d_cache.reserve(m_model->objects.size());
|
||||
for (size_t i = 0; i < m_model->objects.size(); ++i) {
|
||||
ModelObject* model_object = m_model->objects[i];
|
||||
Geometry::Transformation trafo = instance_transform_from_volumes((int)i, 0);
|
||||
trafo.set_offset({ 0.0, 0.0, trafo.get_offset().z() });
|
||||
Pointf3s& new_hull_2d = m_sequential_print_clearance.m_hulls_2d_cache.emplace_back(std::make_pair(Pointf3s(), trafo.get_matrix())).first;
|
||||
if (is_object_outside_printbed((int)i))
|
||||
continue;
|
||||
|
||||
Polygon hull_2d = model_object->convex_hull_2d(trafo.get_matrix());
|
||||
if (!hull_2d.empty()) {
|
||||
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
|
||||
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
|
||||
const Polygons offset_res = offset(hull_2d, shrink_factor, jtRound, mitter_limit);
|
||||
if (!offset_res.empty())
|
||||
hull_2d = offset_res.front();
|
||||
}
|
||||
|
||||
new_hull_2d.reserve(hull_2d.points.size());
|
||||
for (const Point& p : hull_2d.points) {
|
||||
new_hull_2d.emplace_back(Vec3d(unscale<double>(p.x()), unscale<double>(p.y()), 0.0));
|
||||
}
|
||||
}
|
||||
|
||||
ContoursList contours;
|
||||
contours.contours.reserve(instance_transforms.size());
|
||||
contours.trafos = std::vector<std::pair<size_t, Transform3d>>();
|
||||
(*contours.trafos).reserve(instances_count);
|
||||
for (size_t i = 0; i < instance_transforms.size(); ++i) {
|
||||
const auto& [hull, hull_trafo] = m_sequential_print_clearance.m_hulls_2d_cache[i];
|
||||
Points hull_pts;
|
||||
hull_pts.reserve(hull.size());
|
||||
for (size_t j = 0; j < hull.size(); ++j) {
|
||||
hull_pts.emplace_back(scaled<double>(hull[j].x()), scaled<double>(hull[j].y()));
|
||||
}
|
||||
contours.contours.emplace_back(Geometry::convex_hull(std::move(hull_pts)));
|
||||
|
||||
const auto& instances = instance_transforms[i];
|
||||
for (const auto& instance : instances) {
|
||||
(*contours.trafos).emplace_back(i, instance_trafo(hull_trafo, *instance));
|
||||
}
|
||||
}
|
||||
|
||||
set_sequential_print_clearance_contours(contours, false);
|
||||
m_sequential_print_clearance.m_first_displacement = false;
|
||||
}
|
||||
else {
|
||||
if (!m_sequential_print_clearance.empty()) {
|
||||
std::vector<Transform3d> trafos;
|
||||
trafos.reserve(instances_count);
|
||||
for (size_t i = 0; i < instance_transforms.size(); ++i) {
|
||||
const auto& [hull, hull_trafo] = m_sequential_print_clearance.m_hulls_2d_cache[i];
|
||||
const auto& instances = instance_transforms[i];
|
||||
for (const auto& instance : instances) {
|
||||
trafos.emplace_back(instance_trafo(hull_trafo, *instance));
|
||||
}
|
||||
}
|
||||
m_sequential_print_clearance.update_instances_trafos(trafos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_object_sinking(int object_idx) const
|
||||
{
|
||||
for (const GLVolume* v : m_volumes.volumes) {
|
||||
@ -6592,32 +6298,6 @@ void GLCanvas3D::_render_selection()
|
||||
#endif // ENABLE_MATRICES_DEBUG
|
||||
}
|
||||
|
||||
void GLCanvas3D::_render_sequential_clearance()
|
||||
{
|
||||
if (!_is_sequential_print_enabled())
|
||||
return;
|
||||
|
||||
if (m_layers_editing.is_enabled())
|
||||
return;
|
||||
|
||||
switch (m_gizmos.get_current_type())
|
||||
{
|
||||
case GLGizmosManager::EType::Flatten:
|
||||
case GLGizmosManager::EType::Cut:
|
||||
case GLGizmosManager::EType::MmSegmentation:
|
||||
case GLGizmosManager::EType::Measure:
|
||||
case GLGizmosManager::EType::Emboss:
|
||||
case GLGizmosManager::EType::Simplify:
|
||||
case GLGizmosManager::EType::FdmSupports:
|
||||
case GLGizmosManager::EType::Seam:
|
||||
case GLGizmosManager::EType::FuzzySkin: { return; }
|
||||
default: { break; }
|
||||
}
|
||||
|
||||
m_sequential_print_clearance.render();
|
||||
}
|
||||
|
||||
|
||||
bool GLCanvas3D::check_toolbar_icon_size(float init_scale, float& new_scale_to_save, bool is_custom, int counter/* = 3*/)
|
||||
{
|
||||
const Size cnv_size = get_canvas_size();
|
||||
|
@ -624,34 +624,6 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
class SequentialPrintClearance
|
||||
{
|
||||
GLModel m_fill;
|
||||
// list of unique contours
|
||||
std::vector<GLModel> m_contours;
|
||||
// list of transforms used to render the contours
|
||||
std::vector<std::pair<size_t, Transform3d>> m_instances;
|
||||
bool m_evaluating{ false };
|
||||
bool m_dragging{ false };
|
||||
bool m_first_displacement{ true };
|
||||
|
||||
std::vector<std::pair<Pointf3s, Transform3d>> m_hulls_2d_cache;
|
||||
|
||||
public:
|
||||
void set_contours(const ContoursList& contours, bool generate_fill);
|
||||
void update_instances_trafos(const std::vector<Transform3d>& trafos);
|
||||
void render();
|
||||
bool empty() const { return m_contours.empty(); }
|
||||
|
||||
void start_dragging() { m_dragging = true; }
|
||||
bool is_dragging() const { return m_dragging; }
|
||||
void stop_dragging() { m_dragging = false; }
|
||||
|
||||
friend class GLCanvas3D;
|
||||
};
|
||||
|
||||
SequentialPrintClearance m_sequential_print_clearance;
|
||||
|
||||
struct ToolbarHighlighter
|
||||
{
|
||||
void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY) { m_timer.SetOwner(owner, timerid); }
|
||||
@ -991,39 +963,6 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
void reset_sequential_print_clearance() {
|
||||
m_sequential_print_clearance.m_evaluating = false;
|
||||
if (m_sequential_print_clearance.is_dragging())
|
||||
m_sequential_print_clearance.m_first_displacement = true;
|
||||
else
|
||||
m_sequential_print_clearance.set_contours(ContoursList(), false);
|
||||
set_as_dirty();
|
||||
request_extra_frame();
|
||||
}
|
||||
|
||||
void set_sequential_print_clearance_contours(const ContoursList& contours, bool generate_fill) {
|
||||
m_sequential_print_clearance.set_contours(contours, generate_fill);
|
||||
if (generate_fill)
|
||||
m_sequential_print_clearance.m_evaluating = false;
|
||||
set_as_dirty();
|
||||
request_extra_frame();
|
||||
}
|
||||
|
||||
bool is_sequential_print_clearance_empty() const {
|
||||
return m_sequential_print_clearance.empty();
|
||||
}
|
||||
|
||||
bool is_sequential_print_clearance_evaluating() const {
|
||||
return m_sequential_print_clearance.m_evaluating;
|
||||
}
|
||||
|
||||
void update_sequential_clearance(bool force_contours_generation);
|
||||
void set_sequential_clearance_as_evaluating() {
|
||||
m_sequential_print_clearance.m_evaluating = true;
|
||||
set_as_dirty();
|
||||
request_extra_frame();
|
||||
}
|
||||
|
||||
const Print* fff_print() const;
|
||||
const SLAPrint* sla_print() const;
|
||||
|
||||
@ -1069,7 +1008,6 @@ private:
|
||||
void _render_gcode() { m_gcode_viewer.render(); }
|
||||
void _render_gcode_cog() { m_gcode_viewer.render_cog(); }
|
||||
void _render_selection();
|
||||
void _render_sequential_clearance();
|
||||
bool check_toolbar_icon_size(float init_scale, float& new_scale_to_save, bool is_custom, int counter = 3);
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
void _render_selection_center() { m_selection.render_center(m_gizmos.is_dragging()); }
|
||||
|
@ -1967,7 +1967,6 @@ void Plater::priv::delete_all_objects_from_model()
|
||||
reset_gcode_toolpaths();
|
||||
std::for_each(gcode_results.begin(), gcode_results.end(), [](auto& g) { g.reset(); });
|
||||
|
||||
view3D->get_canvas3d()->reset_sequential_print_clearance();
|
||||
view3D->get_canvas3d()->reset_all_gizmos();
|
||||
|
||||
m_worker.cancel_all();
|
||||
@ -2001,8 +2000,6 @@ void Plater::priv::reset()
|
||||
reset_gcode_toolpaths();
|
||||
std::for_each(gcode_results.begin(), gcode_results.end(), [](auto& g) { g.reset(); });
|
||||
|
||||
view3D->get_canvas3d()->reset_sequential_print_clearance();
|
||||
|
||||
m_worker.cancel_all();
|
||||
|
||||
// Stop and reset the Print content.
|
||||
@ -2357,9 +2354,6 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
if (view3D->is_layers_editing_enabled())
|
||||
view3D->get_wxglcanvas()->Refresh();
|
||||
|
||||
if (invalidated == Print::APPLY_STATUS_CHANGED || background_process.empty())
|
||||
view3D->get_canvas3d()->reset_sequential_print_clearance();
|
||||
|
||||
if (invalidated == Print::APPLY_STATUS_INVALIDATED) {
|
||||
// Some previously calculated data on the Print was invalidated.
|
||||
// Hide the slicing results, as the current slicing status is no more valid.
|
||||
@ -2397,7 +2391,6 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
process_validation_warning(warnings);
|
||||
if (printer_technology == ptFFF) {
|
||||
GLCanvas3D* canvas = view3D->get_canvas3d();
|
||||
canvas->reset_sequential_print_clearance();
|
||||
canvas->set_as_dirty();
|
||||
canvas->request_extra_frame();
|
||||
}
|
||||
@ -2407,41 +2400,14 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
// Show error as notification.
|
||||
notification_manager->push_validate_error_notification(err);
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
||||
if (printer_technology == ptFFF) {
|
||||
GLCanvas3D* canvas = view3D->get_canvas3d();
|
||||
if (canvas->is_sequential_print_clearance_empty() || canvas->is_sequential_print_clearance_evaluating()) {
|
||||
GLCanvas3D::ContoursList contours;
|
||||
contours.contours = background_process.fff_print()->get_sequential_print_clearance_contours();
|
||||
canvas->set_sequential_print_clearance_contours(contours, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (invalidated == Print::APPLY_STATUS_UNCHANGED && !background_process.empty()) {
|
||||
if (printer_technology == ptFFF) {
|
||||
// Object manipulation with gizmos may end up in a null transformation.
|
||||
// In this case, we need to trigger the completion of the sequential print clearance contours evaluation
|
||||
GLCanvas3D* canvas = view3D->get_canvas3d();
|
||||
if (canvas->is_sequential_print_clearance_evaluating()) {
|
||||
GLCanvas3D::ContoursList contours;
|
||||
contours.contours = background_process.fff_print()->get_sequential_print_clearance_contours();
|
||||
canvas->set_sequential_print_clearance_contours(contours, true);
|
||||
}
|
||||
}
|
||||
std::vector<std::string> warnings;
|
||||
std::string err = background_process.validate(&warnings);
|
||||
if (!err.empty()) {
|
||||
if (s_multiple_beds.get_number_of_beds() > 1 && printer_technology == ptFFF) {
|
||||
// user changed bed seletion,
|
||||
// sequential print clearance contours were changed too
|
||||
GLCanvas3D* canvas = view3D->get_canvas3d();
|
||||
GLCanvas3D::ContoursList contours;
|
||||
contours.contours = background_process.fff_print()->get_sequential_print_clearance_contours();
|
||||
canvas->set_sequential_print_clearance_contours(contours, true);
|
||||
}
|
||||
if (!err.empty())
|
||||
return return_state;
|
||||
}
|
||||
}
|
||||
|
||||
if (! this->delayed_error_message.empty())
|
||||
@ -6899,7 +6865,6 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
|
||||
this->set_printer_technology(printer_technology);
|
||||
p->sidebar->show_sliced_info_sizer(false);
|
||||
p->reset_gcode_toolpaths();
|
||||
p->view3D->get_canvas3d()->reset_sequential_print_clearance();
|
||||
p->view3D->get_canvas3d()->set_sla_view_type(GLCanvas3D::ESLAViewType::Original);
|
||||
p->preview->get_canvas3d()->reset_volumes();
|
||||
}
|
||||
|
@ -1625,8 +1625,6 @@ void Selection::erase()
|
||||
wxGetApp().obj_list()->delete_from_model_and_list(items);
|
||||
ensure_not_below_bed();
|
||||
}
|
||||
|
||||
wxGetApp().plater()->canvas3D()->set_sequential_clearance_as_evaluating();
|
||||
}
|
||||
|
||||
void Selection::render(float scale_factor)
|
||||
|
Loading…
x
Reference in New Issue
Block a user