From 745c5ecd9bde877d72c29155811854b21a490a78 Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Mon, 13 Jun 2022 10:05:35 +0200 Subject: [PATCH] SeamPlacer - fix search radius estimation for visibility computation (use exp distribution) slightly tune parameters --- src/libslic3r/GCode/SeamPlacer.cpp | 30 ++++++++++++++++++++---------- src/libslic3r/GCode/SeamPlacer.hpp | 6 +++--- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 5ca34573a..2f67db534 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -178,7 +178,7 @@ std::vector raycast_visibility(const AABBTreeIndirect::Tree<3, float> &ra // FIXME: This AABBTTreeIndirect query will not compile for float ray origin and // direction. Vec3d final_ray_dir_d = final_ray_dir.cast(); - Vec3d ray_origin_d = (center + normal * 1.0f).cast(); // start above surface. + Vec3d ray_origin_d = (center + normal * 0.01f).cast(); // start above surface. bool hit = AABBTreeIndirect::intersect_ray_first_hit(triangles.vertices, triangles.indices, raycasting_tree, ray_origin_d, final_ray_dir_d, hitpoint); if (hit && its_face_normal(triangles, hitpoint.id).dot(final_ray_dir) <= 0) { @@ -188,10 +188,10 @@ std::vector raycast_visibility(const AABBTreeIndirect::Tree<3, float> &ra bool casting_from_negative_volume = samples.triangle_indices[s_idx] >= negative_volumes_start_index; - Vec3d ray_origin_d = (center + normal * 1.0f).cast(); // start above surface. + Vec3d ray_origin_d = (center + normal * 0.01f).cast(); // start above surface. if (casting_from_negative_volume) { // if casting from negative volume face, invert direction, change start pos final_ray_dir = -1.0 * final_ray_dir; - ray_origin_d = (center - normal * 1.0f).cast(); + ray_origin_d = (center - normal * 0.01f).cast(); } Vec3d final_ray_dir_d = final_ray_dir.cast(); bool some_hit = AABBTreeIndirect::intersect_ray_all_hits(triangles.vertices, @@ -455,14 +455,13 @@ void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, const } Polygon polygon = orig_polygon; - bool was_clockwise = polygon.make_counter_clockwise(); - std::vector lengths { }; for (size_t point_idx = 0; point_idx < polygon.size() - 1; ++point_idx) { - lengths.push_back(std::max((unscale(polygon[point_idx]) - unscale(polygon[point_idx + 1])).norm(), 0.001)); + lengths.push_back((unscale(polygon[point_idx]) - unscale(polygon[point_idx + 1])).norm()); } - lengths.push_back(std::max((unscale(polygon[0]) - unscale(polygon[polygon.size() - 1])).norm(), 0.001)); + lengths.push_back(std::max((unscale(polygon[0]) - unscale(polygon[polygon.size() - 1])).norm(), 0.1)); + bool was_clockwise = polygon.make_counter_clockwise(); std::vector local_angles = calculate_polygon_angles_at_vertices(polygon, lengths, SeamPlacer::polygon_local_angles_arm_distance); @@ -640,8 +639,20 @@ void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po, result.mesh_samples_coordinate_functor = CoordinateFunctor(&result.mesh_samples.positions); result.mesh_samples_tree = KDTreeIndirect<3, float, CoordinateFunctor>(result.mesh_samples_coordinate_functor, result.mesh_samples.positions.size()); - result.mesh_samples_radius = sqrt( - 10.0f * (result.mesh_samples.total_area / SeamPlacer::raycasting_visibility_samples_count) / PI); + + // The following code determines search area for random visibility samples on the mesh when calculating visibility of each perimeter point + // number of random samples in the given radius (area) is approximately poisson distribution + // to compute ideal search radius (area), we use exponential distribution (complementary distr to poisson) + // parameters of exponential distribution to compute area that will have with probability="probability" more than given number of samples="samples" + float probability = 0.9f; + float samples = 3; + float density = SeamPlacer::raycasting_visibility_samples_count / result.mesh_samples.total_area; + // exponential probability distrubtion function is : f(x) = P(X > x) = e^(l*x) where l is the rate parameter (computed as 1/u where u is mean value) + // probability that sampled area A with S samples contains more than samples count: + // P(S > samples in A) = e^-(samples/(density*A)); express A: + float search_area = samples / (-logf(probability) * density); + float search_radius = sqrt(search_area / PI); + result.mesh_samples_radius = search_radius; BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: Compute visiblity sample points: end"; @@ -1090,7 +1101,6 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) } }; bool should_compute_layer_embedding = regions_with_perimeter > 1; - layers[layer_idx].points[0].perimeter.end_index < layers[layer_idx].points.size() - 1; std::unique_ptr current_layer_distancer = std::make_unique(po->layers()[layer_idx]); for (SeamCandidate &perimeter_point : layers[layer_idx].points) { diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index fdd46dd12..6b211b176 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -133,8 +133,8 @@ public: static constexpr float overhang_distance_tolerance_factor = 0.5f; // determines angle importance compared to visibility ( neutral value is 1.0f. ) - static constexpr float angle_importance_aligned = 1.0f; - static constexpr float angle_importance_nearest = 2.0f; // use much higher angle importance for nearest mode, to combat the visiblity info noise + static constexpr float angle_importance_aligned = 0.5f; + static constexpr float angle_importance_nearest = 1.0f; // use much higher angle importance for nearest mode, to combat the visiblity info noise // If enforcer or blocker is closer to the seam candidate than this limit, the seam candidate is set to Blocker or Enforcer static constexpr float enforcer_blocker_distance_tolerance = 0.35f; @@ -143,7 +143,7 @@ public: // When searching for seam clusters for alignment: // following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer - static constexpr float seam_align_score_tolerance = 0.45f; + static constexpr float seam_align_score_tolerance = 0.27f; // seam_align_tolerable_dist - if next layer closest point is too far away, skip layer static constexpr float seam_align_tolerable_dist = 1.0f; // if the seam of the current layer is too far away, and the closest seam candidate is not very good, layer is skipped.