diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index f0e435dea..40f740b91 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -423,27 +423,29 @@ void PrintObject::find_supportable_issues() SupportableIssues::Issues issues = SupportableIssues::full_search(this); //TODO fix // if (!issues.supports_nedded.empty()) { - auto obj_transform = this->trafo_centered(); - for (ModelVolume *model_volume : this->model_object()->volumes) { - if (model_volume->type() == ModelVolumeType::MODEL_PART) { - Transform3d model_transformation = model_volume->get_matrix(); - Transform3d inv_transform = (obj_transform * model_transformation).inverse(); - TriangleSelectorWrapper selector { model_volume->mesh() }; + auto obj_transform = this->trafo_centered(); + for (ModelVolume *model_volume : this->model_object()->volumes) { + if (model_volume->type() == ModelVolumeType::MODEL_PART) { + Transform3d model_transformation = model_volume->get_matrix(); + Transform3f inv_transform = (obj_transform * model_transformation).inverse().cast(); + TriangleSelectorWrapper selector { model_volume->mesh() }; - for (const SupportableIssues::SupportPoint &support_point : issues.supports_nedded) { - selector.enforce_spot(Vec3f(inv_transform.cast() * support_point.position), 0.5f); - } - - model_volume->supported_facets.set(selector.selector); - -#if 1 - indexed_triangle_set copy = model_volume->mesh().its; - its_transform(copy, obj_transform * model_transformation); - its_write_obj(copy, - debug_out_path("model.obj").c_str()); -#endif + for (const SupportableIssues::SupportPoint &support_point : issues.supports_nedded) { + Vec3f point = Vec3f(inv_transform * support_point.position); + Vec3f origin = Vec3f( + inv_transform * Vec3f(support_point.position.x(), support_point.position.y(), 0.0f)); + selector.enforce_spot(point, origin, 0.5f); } + + model_volume->supported_facets.set(selector.selector); +#if 1 + indexed_triangle_set copy = model_volume->mesh().its; + its_transform(copy, obj_transform * model_transformation); + its_write_obj(copy, + debug_out_path("model.obj").c_str()); +#endif } + } // } } diff --git a/src/libslic3r/SupportableIssuesSearch.cpp b/src/libslic3r/SupportableIssuesSearch.cpp index 73f89e0d6..ce17020ed 100644 --- a/src/libslic3r/SupportableIssuesSearch.cpp +++ b/src/libslic3r/SupportableIssuesSearch.cpp @@ -191,7 +191,7 @@ struct StabilityAccumulators { private: size_t next_id = 0; std::unordered_map mapping; - std::vector acccumulators; + std::vector accumulators; void merge_to(size_t from_id, size_t to_id) { StabilityAccumulator &from_acc = this->access(from_id); @@ -211,13 +211,13 @@ public: int create_accumulator(float base_height) { size_t id = next_id; next_id++; - mapping[id] = acccumulators.size(); - acccumulators.push_back(StabilityAccumulator { base_height }); + mapping[id] = accumulators.size(); + accumulators.push_back(StabilityAccumulator { base_height }); return id; } StabilityAccumulator& access(size_t id) { - return acccumulators[mapping[id]]; + return accumulators[mapping[id]]; } void merge_accumulators(size_t from_id, size_t to_id) { @@ -235,24 +235,14 @@ public: } #ifdef DEBUG_FILES - Vec3f get_emerging_color(size_t id) { + Vec3f get_accumulator_color(size_t id) { if (mapping.find(id) == mapping.end()) { std::cerr << " ERROR: uknown accumulator ID: " << id << std::endl; return Vec3f(1.0f, 1.0f, 1.0f); } - size_t pseudornd = ((id + 127) * 33331 + 6907) % 13; - return value_to_rgbf(0.0f, 13.0f, float(pseudornd)); - } - - Vec3f get_final_color(size_t id) { - if (mapping.find(id) == mapping.end()) { - std::cerr << " ERROR: uknown accumulator ID: " << id << std::endl; - return Vec3f(1.0f, 1.0f, 1.0f); - } - - size_t pseudornd = ((mapping[id] + 127) * 33331 + 6907) % 13; - return value_to_rgbf(0.0f, 13.0f, float(pseudornd)); + size_t pseudornd = ((mapping[id] + 127) * 33331 + 6907) % 987; + return value_to_rgbf(0.0f, float(987), float(pseudornd)); } #endif }; @@ -345,10 +335,12 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity, // -> it prevents extruding perimeter start and short loops into air. const float flow_width = get_flow_width(layer_region, entity->role()); const float max_allowed_dist_from_prev_layer = flow_width; + float distance_from_last_support_point = params.min_distance_between_support_points * 2.0f; for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) { ExtrusionLine ¤t_line = lines[line_idx]; Point current = Point::new_scale(current_line.b); + distance_from_last_support_point += current_line.len; float mm3_per_mm = float(entity->min_mm3_per_mm()); float curr_angle = 0; @@ -381,13 +373,15 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity, StabilityAccumulator ¤t_segment = stability_accs.access(current_stability_acc); current_line.stability_accumulator_id = current_stability_acc; current_segment.add_extrusion(current_line, print_z, mm3_per_mm); - if (bridging_acc.distance // if unsupported distance is larger than bridge distance linearly decreased by curvature, enforce supports. - > params.bridge_distance - / (1.0f + (bridging_acc.max_curvature - * params.bridge_distance_decrease_by_curvature_factor / PI))) { - current_segment.add_support_point(current, params.support_points_interface_area); + if (distance_from_last_support_point > params.min_distance_between_support_points && + bridging_acc.distance // if unsupported distance is larger than bridge distance linearly decreased by curvature, enforce supports. + > params.bridge_distance + / (1.0f + (bridging_acc.max_curvature + * params.bridge_distance_decrease_by_curvature_factor / PI))) { + current_segment.add_support_point(current, params.extrusion_support_points_area); issues.supports_nedded.emplace_back(to_vec3f(current), 1.0); bridging_acc.reset(); + distance_from_last_support_point = 0.0f; } } } @@ -430,10 +424,13 @@ void check_layer_global_stability(StabilityAccumulators &stability_accs, float sticking_force = acc->get_base_area() * (acc->get_base_height() == 0 ? params.base_adhesion : params.support_adhesion); - float weight = acc->get_accumulated_volume() * params.filament_density * params.gravity_constant; + float mass = acc->get_accumulated_volume() * params.filament_density; + float weight = mass * params.gravity_constant; + float distance_from_last_support_point = params.min_distance_between_support_points * 2.0f; for (size_t line_idx : acc_lines.second) { const ExtrusionLine &line = checked_lines[line_idx]; + distance_from_last_support_point += line.len; Vec3f extruder_pressure_direction = to_3d(Vec2f(line.b - line.a), 0.0f).normalized(); Vec2f pivot_site_search = line.b + extruder_pressure_direction.head<2>() * 1000.0f; @@ -457,7 +454,7 @@ void check_layer_global_stability(StabilityAccumulators &stability_accs, std::cout << "weight_torque: " << weight_torque << std::endl; float bed_movement_arm = centroid.z() - acc->get_base_height(); - float bed_movement_force = params.max_acceleration * weight; + float bed_movement_force = params.max_acceleration * mass; float bed_movement_torque = bed_movement_force * bed_movement_arm; std::cout << "bed_movement_arm: " << bed_movement_arm << std::endl; @@ -475,8 +472,9 @@ void check_layer_global_stability(StabilityAccumulators &stability_accs, std::cout << "total_torque: " << total_torque << " printz: " << print_z << std::endl; if (total_torque > 0) { - acc->add_support_point(Point::new_scale(line.b), params.support_points_interface_area); + acc->add_support_point(Point::new_scale(line.b), std::min(params.support_points_interface_area, (pivot - line.b).squaredNorm())); issues.supports_nedded.emplace_back(to_3d(line.b, print_z), extruder_conflict_torque - sticking_torque); + distance_from_last_support_point = 0.0f; } } @@ -485,8 +483,7 @@ void check_layer_global_stability(StabilityAccumulators &stability_accs, Issues check_object_stability(const PrintObject *po, const Params ¶ms) { #ifdef DEBUG_FILES - FILE *eacc = boost::nowide::fopen(debug_out_path("emerging_accumulators.obj").c_str(), "w"); - FILE *facc = boost::nowide::fopen(debug_out_path("final_accumulators.obj").c_str(), "w"); + FILE *debug_acc = boost::nowide::fopen(debug_out_path("accumulators.obj").c_str(), "w"); #endif StabilityAccumulators stability_accs; LayerLinesDistancer prev_layer_lines { { } }; @@ -548,15 +545,11 @@ Issues check_object_stability(const PrintObject *po, const Params ¶ms) { #ifdef DEBUG_FILES for (const auto &line : checked_lines) { - Vec3f ecolor = stability_accs.get_emerging_color(line.stability_accumulator_id); - fprintf(eacc, "v %f %f %f %f %f %f\n", line.b[0], - line.b[1], base_print_z, ecolor[0], ecolor[1], ecolor[2]); - - Vec3f fcolor = stability_accs.get_final_color(line.stability_accumulator_id); - fprintf(facc, "v %f %f %f %f %f %f\n", line.b[0], - line.b[1], base_print_z, fcolor[0], fcolor[1], fcolor[2]); + Vec3f color = stability_accs.get_accumulator_color(line.stability_accumulator_id); + fprintf(debug_acc, "v %f %f %f %f %f %f\n", line.b[0], + line.b[1], base_print_z, color[0], color[1], color[2]); } -#endif DEBUG_FILES +#endif //MERGE BASE LAYER STABILITY ACCS prev_layer_lines = LayerLinesDistancer { std::move(checked_lines) }; @@ -564,7 +557,7 @@ Issues check_object_stability(const PrintObject *po, const Params ¶ms) { size_t nearest_line_idx; Vec2f nearest_pt; float dist = prev_layer_lines.signed_distance_from_lines(l.a, nearest_line_idx, nearest_pt); - if (std::abs(dist) < max_flow_width) { + if (std::abs(dist) < max_flow_width*1.1f) { size_t other_line_acc_id = prev_layer_lines.get_line(nearest_line_idx).stability_accumulator_id; size_t from_id = std::max(other_line_acc_id, l.stability_accumulator_id); size_t to_id = std::min(other_line_acc_id, l.stability_accumulator_id); @@ -646,20 +639,15 @@ Issues check_object_stability(const PrintObject *po, const Params ¶ms) { #ifdef DEBUG_FILES for (const auto &line : prev_layer_lines.get_lines()) { - Vec3f ecolor = stability_accs.get_emerging_color(line.stability_accumulator_id); - fprintf(eacc, "v %f %f %f %f %f %f\n", line.b[0], - line.b[1], print_z, ecolor[0], ecolor[1], ecolor[2]); - - Vec3f fcolor = stability_accs.get_final_color(line.stability_accumulator_id); - fprintf(facc, "v %f %f %f %f %f %f\n", line.b[0], - line.b[1], print_z, fcolor[0], fcolor[1], fcolor[2]); + Vec3f color = stability_accs.get_accumulator_color(line.stability_accumulator_id); + fprintf(debug_acc, "v %f %f %f %f %f %f\n", line.b[0], + line.b[1], print_z, color[0], color[1], color[2]); } #endif } #ifdef DEBUG_FILES - fclose(eacc); - fclose(facc); + fclose(debug_acc); #endif std::cout << " SUPP: " << issues.supports_nedded.size() << std::endl; diff --git a/src/libslic3r/SupportableIssuesSearch.hpp b/src/libslic3r/SupportableIssuesSearch.hpp index e8a9f0e0c..ccda2d77a 100644 --- a/src/libslic3r/SupportableIssuesSearch.hpp +++ b/src/libslic3r/SupportableIssuesSearch.hpp @@ -10,14 +10,18 @@ namespace SupportableIssues { struct Params { const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position. - float bridge_distance = 10.0f; //mm float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / ( 1 + this factor * (curvature / PI) ) + float min_distance_between_support_points = 0.5f; + // Adhesion computation : from experiment, PLA holds about 3g per mm^2 of base area (with reserve); So it can withstand about 3*gravity_constant force per mm^2 float base_adhesion = 3.0f * gravity_constant; // adhesion per mm^2 of first layer - float support_adhesion = 1.0f * gravity_constant; // adhesion per mm^2 of support interface layer - float support_points_interface_area = 2.0f; // mm^2 + float support_adhesion = 3.0f * gravity_constant; // adhesion per mm^2 of support interface layer + float support_points_interface_area = 5.0f; // mm^2 + float extrusion_support_points_area = 0.5f; // much lower value, because these support points appear due to unsupported extrusion, + // not stability - they can be very densely placed, making the sticking estimation incorrect + float max_acceleration = 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY float filament_density = 1.25f * 0.001f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important diff --git a/src/libslic3r/TriangleSelectorWrapper.cpp b/src/libslic3r/TriangleSelectorWrapper.cpp index 02a3b8a1a..ec716ebca 100644 --- a/src/libslic3r/TriangleSelectorWrapper.cpp +++ b/src/libslic3r/TriangleSelectorWrapper.cpp @@ -10,22 +10,26 @@ TriangleSelectorWrapper::TriangleSelectorWrapper(const TriangleMesh &mesh) : } -void TriangleSelectorWrapper::enforce_spot(const Vec3f &point, float radius) { - size_t hit_face_index; - Vec3f hit_point; - auto dist = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(mesh.its.vertices, mesh.its.indices, - triangles_tree, - point, hit_face_index, hit_point); - if (dist < 0 || dist > radius * radius) { - return; +void TriangleSelectorWrapper::enforce_spot(const Vec3f &point, const Vec3f &origin, float radius) { + std::vector hits; + Vec3f dir = (point - origin).normalized(); + if (AABBTreeIndirect::intersect_ray_all_hits(mesh.its.vertices, mesh.its.indices, triangles_tree, + Vec3d(origin.cast()), + Vec3d(dir.cast()), + 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.z() + radius > pos.z() && face_normal.dot(dir) < 0) { + std::unique_ptr cursor = std::make_unique( + pos, origin, radius, Transform3d::Identity(), TriangleSelector::ClippingPlane { }); + selector.select_patch(hit.id, std::move(cursor), EnforcerBlockerType::ENFORCER, Transform3d::Identity(), + true, 0.0f); + break; + } + } } - - std::unique_ptr cursor = std::make_unique(hit_point, point, - radius, Transform3d::Identity(), TriangleSelector::ClippingPlane { }); - - selector.select_patch(hit_face_index, std::move(cursor), EnforcerBlockerType::ENFORCER, Transform3d::Identity(), - true, - 0.0f); } } diff --git a/src/libslic3r/TriangleSelectorWrapper.hpp b/src/libslic3r/TriangleSelectorWrapper.hpp index f3b56205f..10707cc25 100644 --- a/src/libslic3r/TriangleSelectorWrapper.hpp +++ b/src/libslic3r/TriangleSelectorWrapper.hpp @@ -20,7 +20,7 @@ public: TriangleSelectorWrapper(const TriangleMesh &mesh); - void enforce_spot(const Vec3f &point, float radius); + void enforce_spot(const Vec3f &point, const Vec3f& origin, float radius); };