mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 11:05:58 +08:00
Another bulk of bug fixes. Some problems however persist, support points are still placed on weird spots
This commit is contained in:
parent
6caec6926c
commit
6f6a0e7efd
@ -58,11 +58,12 @@ struct Cell {
|
|||||||
struct CentroidAccumulator {
|
struct CentroidAccumulator {
|
||||||
Polygon convex_hull { };
|
Polygon convex_hull { };
|
||||||
Points points { };
|
Points points { };
|
||||||
Vec3d accumulated_value = Vec3d::Zero();
|
Vec3f accumulated_value = Vec3f::Zero();
|
||||||
float accumulated_volume { };
|
float accumulated_volume { };
|
||||||
const double base_height { };
|
float base_area { };
|
||||||
|
const float base_height { };
|
||||||
|
|
||||||
explicit CentroidAccumulator(double base_height) :
|
explicit CentroidAccumulator(float base_height) :
|
||||||
base_height(base_height) {
|
base_height(base_height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ struct CentroidAccumulators {
|
|||||||
acccumulators.reserve(reserve_count);
|
acccumulators.reserve(reserve_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
CentroidAccumulator& create_accumulator(int id, double base_height) {
|
CentroidAccumulator& create_accumulator(int id, float base_height) {
|
||||||
mapping[id] = acccumulators.size();
|
mapping[id] = acccumulators.size();
|
||||||
acccumulators.push_back(CentroidAccumulator { base_height });
|
acccumulators.push_back(CentroidAccumulator { base_height });
|
||||||
return this->access(id);
|
return this->access(id);
|
||||||
@ -100,6 +101,7 @@ struct CentroidAccumulators {
|
|||||||
to_acc.accumulated_volume += from_acc.accumulated_volume;
|
to_acc.accumulated_volume += from_acc.accumulated_volume;
|
||||||
to_acc.points.insert(to_acc.points.end(), from_acc.points.begin(), from_acc.points.end());
|
to_acc.points.insert(to_acc.points.end(), from_acc.points.begin(), from_acc.points.end());
|
||||||
to_acc.calculate_base_hull();
|
to_acc.calculate_base_hull();
|
||||||
|
to_acc.base_area += from_acc.base_area;
|
||||||
mapping[from_id] = mapping[to_id];
|
mapping[from_id] = mapping[to_id];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -265,7 +267,7 @@ struct BalanceDistributionGrid {
|
|||||||
Vec3crd cell_center = this->get_cell_center(
|
Vec3crd cell_center = this->get_cell_center(
|
||||||
Vec3i(current_coords.x(), current_coords.y(), local_z_index_offset));
|
Vec3i(current_coords.x(), current_coords.y(), local_z_index_offset));
|
||||||
acc.points.push_back(Point(cell_center.head<2>()));
|
acc.points.push_back(Point(cell_center.head<2>()));
|
||||||
acc.accumulated_value += cell_center.cast<double>() * cell.volume;
|
acc.accumulated_value += unscale(cell_center).cast<float>() * cell.volume;
|
||||||
acc.accumulated_volume += cell.volume;
|
acc.accumulated_volume += cell.volume;
|
||||||
|
|
||||||
for (int y_offset = -1; y_offset <= 1; ++y_offset) {
|
for (int y_offset = -1; y_offset <= 1; ++y_offset) {
|
||||||
@ -279,6 +281,7 @@ struct BalanceDistributionGrid {
|
|||||||
}
|
}
|
||||||
next_island_id--;
|
next_island_id--;
|
||||||
acc.calculate_base_hull();
|
acc.calculate_base_hull();
|
||||||
|
acc.base_area = unscale<float>(unscale<float>(acc.convex_hull.area())); //apply unscale 2x, it has units of area
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,6 +298,7 @@ struct BalanceDistributionGrid {
|
|||||||
issues.supports_nedded[index].position.z());
|
issues.supports_nedded[index].position.z());
|
||||||
acc.points.push_back(Point(scaled(Vec2f(issues.supports_nedded[index].position.head<2>()))));
|
acc.points.push_back(Point(scaled(Vec2f(issues.supports_nedded[index].position.head<2>()))));
|
||||||
acc.calculate_base_hull();
|
acc.calculate_base_hull();
|
||||||
|
acc.base_area = params.support_points_inteface_area;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const CurledFilament &curling : issues.curling_up) {
|
for (const CurledFilament &curling : issues.curling_up) {
|
||||||
@ -343,9 +347,10 @@ struct BalanceDistributionGrid {
|
|||||||
accumulators.merge_to(id, min_island_id_found);
|
accumulators.merge_to(id, min_island_id_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
CentroidAccumulator &acc = accumulators.access(current.island_id);
|
CentroidAccumulator &acc = accumulators.access(min_island_id_found);
|
||||||
acc.accumulated_value += current.volume
|
acc.accumulated_value += current.volume
|
||||||
* this->get_cell_center(this->to_global_cell_coords(Vec3i(x, y, z))).cast<double>();
|
* unscale(this->get_cell_center(this->to_global_cell_coords(Vec3i(x, y, z)))).cast<
|
||||||
|
float>();
|
||||||
acc.accumulated_volume += current.volume;
|
acc.accumulated_volume += current.volume;
|
||||||
modified_acc_ids.insert(min_island_id_found);
|
modified_acc_ids.insert(min_island_id_found);
|
||||||
}
|
}
|
||||||
@ -353,109 +358,107 @@ struct BalanceDistributionGrid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check stability of modified centroid accumulators.
|
|
||||||
// Stability is the amount of work needed to push the object from stable position into unstable.
|
|
||||||
// This amount of work is proportional to the increase of height of the centroid during toppling.
|
|
||||||
// image here: https://hgphysics.com/gph/c-forces/2-force-effects/1-moment/stability/
|
|
||||||
// better image in Czech here in the first question: https://www.priklady.eu/cs/fyzika/mechanika-tuheho-telesa/stabilita-teles.alej
|
|
||||||
for (int acc_id : modified_acc_ids) {
|
for (int acc_id : modified_acc_ids) {
|
||||||
|
|
||||||
std::cout << "controlling acc id: " << acc_id << std::endl;
|
std::cout << "Z: " << z << " controlling acc id: " << acc_id << std::endl;
|
||||||
|
|
||||||
CentroidAccumulator &acc = accumulators.access(acc_id);
|
CentroidAccumulator &acc = accumulators.access(acc_id);
|
||||||
Vec3d centroid = acc.accumulated_value / acc.accumulated_volume;
|
Vec3f centroid = acc.accumulated_value / acc.accumulated_volume;
|
||||||
|
|
||||||
std::cout << "acc.accumulated_value : " << acc.accumulated_value.x() << " "
|
std::cout << "acc.accumulated_value : " << acc.accumulated_value.x() << " "
|
||||||
<< acc.accumulated_value.y() << " " << acc.accumulated_value.z() << std::endl;
|
<< acc.accumulated_value.y() << " " << acc.accumulated_value.z() << std::endl;
|
||||||
std::cout << "acc.accumulated_volume : " << acc.accumulated_volume << std::endl;
|
std::cout << "acc.accumulated_volume : " << acc.accumulated_volume << std::endl;
|
||||||
std::cout << "centorid: " << centroid.x() << " " << centroid.y() << " " << centroid.z() << std::endl;
|
std::cout << "centroid: " << centroid.x() << " " << centroid.y() << " " << centroid.z() << std::endl;
|
||||||
|
|
||||||
//determine signed shortest distance to the convex hull
|
//determine signed shortest distance to the convex hull
|
||||||
Point centroid_base_projection = Point(centroid.head<2>().cast<coord_t>());
|
Point centroid_base_projection = Point(scaled(Vec2f(centroid.head<2>())));
|
||||||
|
|
||||||
Point pivot;
|
Point pivot;
|
||||||
double distance_sq = std::numeric_limits<double>::max();
|
double distance_scaled_sq = std::numeric_limits<double>::max();
|
||||||
bool inside = true;
|
bool inside = true;
|
||||||
if (acc.convex_hull.points.size() == 1) {
|
if (acc.convex_hull.points.size() == 1) {
|
||||||
pivot = acc.convex_hull.points[0];
|
pivot = acc.convex_hull.points[0];
|
||||||
distance_sq = (pivot - centroid_base_projection).squaredNorm();
|
distance_scaled_sq = (pivot - centroid_base_projection).squaredNorm();
|
||||||
inside = true;
|
inside = true;
|
||||||
} else {
|
} else {
|
||||||
for (Line line : acc.convex_hull.lines()) {
|
for (Line line : acc.convex_hull.lines()) {
|
||||||
Point closest_point;
|
Point closest_point;
|
||||||
double dist_sq = line.distance_to_squared(centroid_base_projection, &closest_point);
|
double dist_sq = line.distance_to_squared(centroid_base_projection, &closest_point);
|
||||||
if (dist_sq < distance_sq) {
|
if (dist_sq < distance_scaled_sq) {
|
||||||
pivot = closest_point;
|
pivot = closest_point;
|
||||||
distance_sq = dist_sq;
|
distance_scaled_sq = dist_sq;
|
||||||
}
|
}
|
||||||
if (float(angle(line.b - line.a, centroid_base_projection - line.b)) < 0) {
|
if ((centroid_base_projection - closest_point).cast<double>().dot(line.normal().cast<double>())
|
||||||
|
> 0) {
|
||||||
inside = false;
|
inside = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "centoroid inside ? " << inside << " and distance is: " << distance_sq << std::endl;
|
float centroid_pivot_distance = unscaled(sqrt(distance_scaled_sq));
|
||||||
|
float base_center_pivot_distance = float(unscale(Vec2crd(acc.convex_hull.centroid() - pivot)).norm());
|
||||||
|
|
||||||
|
std::cout << "centroid inside ? " << inside << " and distance is: " << centroid_pivot_distance
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
bool additional_supports_needed = false;
|
bool additional_supports_needed = false;
|
||||||
double base_area = std::max(acc.convex_hull.area(), scale_(5.0)); // assume 5 mm^2 area for support points and other degenerate bases
|
float sticking_force = acc.base_area
|
||||||
double sticking_force = base_area
|
* (acc.base_height == 0 ? params.base_adhesion : params.support_adhesion);
|
||||||
* (acc.base_height == 0 ? scale_(params.base_adhesion) : scale_(params.support_adhesion));
|
float sticking_torque = base_center_pivot_distance * sticking_force;
|
||||||
|
|
||||||
std::cout << "stcking force: " << sticking_force << std::endl;
|
std::cout << "sticking force: " << sticking_force << " sticking torque: " << sticking_torque
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
if (inside) {
|
float xy_movement_force = acc.accumulated_volume * params.filament_density * params.max_acceleration;
|
||||||
double toppling_force = (Vec2d(sqrt(distance_sq), centroid.z() - acc.base_height).norm()
|
float xy_movement_torque = xy_movement_force * centroid_pivot_distance;
|
||||||
- centroid.z())
|
|
||||||
* acc.accumulated_volume;
|
|
||||||
sticking_force += toppling_force;
|
|
||||||
std::cout << "toppling force: " << toppling_force << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
double y_movement_force = 0.5f * acc.accumulated_volume * scale_(params.top_object_movement_speed)
|
std::cout << "xy_movement_force: " << xy_movement_force << " xy_movement_torque: "
|
||||||
* scale_(params.top_object_movement_speed);
|
<< xy_movement_torque << std::endl;
|
||||||
|
|
||||||
std::cout << "y_movement_force: " << y_movement_force << std::endl;
|
|
||||||
|
|
||||||
if (sticking_force < y_movement_force) {
|
|
||||||
additional_supports_needed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
float weight_torque = 0;
|
||||||
if (!inside) {
|
if (!inside) {
|
||||||
double torque = sqrt(distance_sq) * scale_(scale_(scale_(acc.accumulated_volume))); // if sticking force is computed with scaled adhesion, than torque needs scaled volume as well
|
float weight = acc.accumulated_volume * params.filament_density * 10000.0f;
|
||||||
|
weight_torque = centroid_pivot_distance * weight;
|
||||||
|
|
||||||
std::cout << "torque: " << torque << std::endl;
|
std::cout << "weight: " << weight << " weight_torque: " << weight_torque << std::endl;
|
||||||
|
|
||||||
if (torque > sticking_force) { //comparing apples and oranges; but we are far beyond physical simulation
|
|
||||||
additional_supports_needed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float total_momentum = sticking_torque - xy_movement_torque - weight_torque;
|
||||||
|
additional_supports_needed = total_momentum < 0;
|
||||||
|
|
||||||
|
std::cout << "total_momentum: " << total_momentum << std::endl;
|
||||||
std::cout << "additional supports needed: " << additional_supports_needed << std::endl;
|
std::cout << "additional supports needed: " << additional_supports_needed << std::endl;
|
||||||
|
|
||||||
if (additional_supports_needed) {
|
if (additional_supports_needed) {
|
||||||
Vec2crd attractor_dir =
|
Vec2f attractor_dir =
|
||||||
inside ? pivot - centroid_base_projection : centroid_base_projection - pivot;
|
unscale(Vec2crd(inside ?
|
||||||
Vec2d attractor = centroid_base_projection.cast<double>()
|
pivot - centroid_base_projection :
|
||||||
+ (1e9 * attractor_dir.cast<double>().normalized());
|
centroid_base_projection - pivot)).cast<float>().normalized();
|
||||||
|
Vec2f attractor = unscale(centroid_base_projection).cast<float>() + 10000 * attractor_dir;
|
||||||
|
|
||||||
|
std::cout << " attractor: " << attractor.x() << " | " << attractor.y() << std::endl;
|
||||||
|
|
||||||
double min_dist = std::numeric_limits<double>::max();
|
double min_dist = std::numeric_limits<double>::max();
|
||||||
Vec3d support_point = centroid;
|
Vec3f support_point = centroid;
|
||||||
for (int y = 0; y < global_cell_count.y(); ++y) {
|
for (int y = 0; y < global_cell_count.y(); ++y) {
|
||||||
for (int x = 0; x < global_cell_count.x(); ++x) {
|
for (int x = 0; x < global_cell_count.x(); ++x) {
|
||||||
Cell &cell = this->access_cell(Vec3i(x, y, 0));
|
Cell &cell = this->access_cell(Vec3i(x, y, z));
|
||||||
if (cell.island_id == acc_id) {
|
if (&accumulators.access(cell.island_id) == &acc) {
|
||||||
Vec3d cell_center =
|
Vec3f cell_center =
|
||||||
this->get_cell_center(this->to_global_cell_coords(Vec3i(x, y, z))).cast<
|
unscale(this->get_cell_center(this->to_global_cell_coords(Vec3i(x, y, z)))).cast<
|
||||||
double>();
|
float>();
|
||||||
double dist_sq = (cell_center.head<2>() - attractor).squaredNorm();
|
float dist_sq = (cell_center.head<2>() - attractor).squaredNorm();
|
||||||
if (dist_sq < min_dist) {
|
if (dist_sq < min_dist) {
|
||||||
min_dist = dist_sq;
|
min_dist = dist_sq;
|
||||||
support_point = cell_center;
|
support_point = cell_center;
|
||||||
|
std::cout << " new support point: " << support_point.x() << " | " << support_point.y() << " | " << support_point.z() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
issues.supports_nedded.emplace_back(unscale(support_point).cast<float>());
|
issues.supports_nedded.emplace_back(support_point);
|
||||||
acc.points.push_back(Point(support_point.head<2>().cast<coord_t>()));
|
acc.points.push_back(Point::new_scale(Vec2f(support_point.head<2>())));
|
||||||
acc.calculate_base_hull();
|
acc.calculate_base_hull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +562,7 @@ void debug_export(Issues issues, std::string file_name) {
|
|||||||
for (size_t i = 0; i < issues.supports_nedded.size(); ++i) {
|
for (size_t i = 0; i < issues.supports_nedded.size(); ++i) {
|
||||||
fprintf(fp, "v %f %f %f %f %f %f\n", issues.supports_nedded[i].position(0),
|
fprintf(fp, "v %f %f %f %f %f %f\n", issues.supports_nedded[i].position(0),
|
||||||
issues.supports_nedded[i].position(1),
|
issues.supports_nedded[i].position(1),
|
||||||
issues.supports_nedded[i].position(2), 1.0, 0.0, 0.0);
|
issues.supports_nedded[i].position(2), 1.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -721,9 +724,8 @@ Issues check_extrusion_entity_stability(const ExtrusionEntity *entity, float pri
|
|||||||
|
|
||||||
if (supports_acc.distance // if unsupported distance is larger than bridge distance linearly decreased by curvature, enforce supports.
|
if (supports_acc.distance // if unsupported distance is larger than bridge distance linearly decreased by curvature, enforce supports.
|
||||||
> params.bridge_distance
|
> params.bridge_distance
|
||||||
/ (1.0f
|
/ (1.0f + (supports_acc.max_curvature
|
||||||
+ (supports_acc.max_curvature
|
* params.bridge_distance_decrease_by_curvature_factor / PI))) {
|
||||||
* params.bridge_distance_decrease_by_curvature_factor / PI))) {
|
|
||||||
issues.supports_nedded.push_back(SupportPoint(fpoint));
|
issues.supports_nedded.push_back(SupportPoint(fpoint));
|
||||||
supports_acc.reset();
|
supports_acc.reset();
|
||||||
}
|
}
|
||||||
@ -899,6 +901,9 @@ Issues full_search(const PrintObject *po, const Params ¶ms) {
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
#ifdef DEBUG_FILES
|
||||||
|
Impl::debug_export(found_issues, "pre_issues");
|
||||||
|
#endif
|
||||||
|
|
||||||
grid.analyze(found_issues, params);
|
grid.analyze(found_issues, params);
|
||||||
|
|
||||||
|
@ -15,9 +15,12 @@ struct Params {
|
|||||||
float max_unsupported_distance_factor = 1.0f; // For internal perimeters, infill, bridges etc, allow gap of [extrusion width] size, these extrusions have usually something to stick to.
|
float max_unsupported_distance_factor = 1.0f; // For internal perimeters, infill, bridges etc, allow gap of [extrusion width] size, these extrusions have usually something to stick to.
|
||||||
float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / ( 1 + this factor * (curvature / PI) )
|
float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / ( 1 + this factor * (curvature / PI) )
|
||||||
|
|
||||||
float base_adhesion = 60.0f; // adhesion per mm^2 of first layer; the value should say how much *volume* it can hold per one square millimiter
|
float base_adhesion = 100.0f; // adhesion per mm^2 of first layer; Force needed to remove the object from the bed, divided by the adhesion area, so in Pascal units N/mm^2
|
||||||
float support_adhesion = 300.0f; // adhesion per mm^2 of support interface layer
|
float support_adhesion = 300.0f; // adhesion per mm^2 of support interface layer
|
||||||
float top_object_movement_speed = 200.0f; // movement speed of 200 mm/s in Y
|
float support_points_inteface_area = 5.0f; // mm^2
|
||||||
|
float max_acceleration = 1000.0f; // mm/s^2 ; max acceleration in XY
|
||||||
|
float filament_density = 1.25f * 0.001f; // g/mm^3
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SupportPoint {
|
struct SupportPoint {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user