SeamPlacer - fix search radius estimation for visibility computation (use exp distribution)

slightly tune parameters
This commit is contained in:
PavelMikus 2022-06-13 10:05:35 +02:00
parent bd4b63e67d
commit 745c5ecd9b
2 changed files with 23 additions and 13 deletions

View File

@ -178,7 +178,7 @@ std::vector<float> 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<double>();
Vec3d ray_origin_d = (center + normal * 1.0f).cast<double>(); // start above surface.
Vec3d ray_origin_d = (center + normal * 0.01f).cast<double>(); // 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<float> 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<double>(); // start above surface.
Vec3d ray_origin_d = (center + normal * 0.01f).cast<double>(); // 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<double>();
ray_origin_d = (center - normal * 0.01f).cast<double>();
}
Vec3d final_ray_dir_d = final_ray_dir.cast<double>();
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<float> 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<float> 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<PerimeterDistancer> current_layer_distancer = std::make_unique<PerimeterDistancer>(po->layers()[layer_idx]);
for (SeamCandidate &perimeter_point : layers[layer_idx].points) {

View File

@ -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.