Remove usage of polygons_covered_by_width.

In SupportSpotsGenerator there is a need to compute integral over
extrusions.
The mentioned function is slow for this use case. As it solves a harder
problem.
It is better to iterate the extrusion lines directly.
This commit is contained in:
Martin Šach 2023-10-04 13:46:12 +02:00 committed by SachCZ
parent 9587394a18
commit 782fa47791
3 changed files with 79 additions and 11 deletions

View File

@ -174,6 +174,32 @@ Integrals::Integrals (const Polygons& polygons) {
}
}
Integrals::Integrals(const Polylines& polylines, const std::vector<float>& widths) {
assert(extrusion_lines.size() == widths.size());
for (size_t i = 0; i < polylines.size(); ++i) {
Lines polyline{polylines[i].lines()};
float width{widths[i]};
for (const Line& line : polyline) {
Vec2f line_direction = unscaled(line.vector()).cast<float>();
Vec2f normal{line_direction.y(), -line_direction.x()};
normal.normalize();
Vec2f line_a = unscaled(line.a).cast<float>();
Vec2f line_b = unscaled(line.b).cast<float>();
Vec2crd a = scaled(Vec2f{line_a + normal * width/2});
Vec2crd b = scaled(Vec2f{line_b + normal * width/2});
Vec2crd c = scaled(Vec2f{line_b - normal * width/2});
Vec2crd d = scaled(Vec2f{line_a - normal * width/2});
const Polygon ractangle({a, b, c, d});
Integrals integrals{{ractangle}};
this->area += integrals.area;
this->x_i += integrals.x_i;
this->x_i_squared += integrals.x_i_squared;
this->xy += integrals.xy;
}
}
}
SliceConnection estimate_slice_connection(size_t slice_idx, const Layer *layer)
{
@ -473,18 +499,43 @@ ObjectPart::ObjectPart(
continue;
}
const Polygons polygons{collection->polygons_covered_by_width()};
for (const ExtrusionEntity* entity: collection->flatten()) {
Polylines polylines;
std::vector<float> widths;
const Integrals integrals{polygons};
const float volume = integrals.area * layer_height;
this->volume += volume;
this->volume_centroid_accumulator += to_3d(integrals.x_i, center_z * integrals.area) / integrals.area * volume;
const auto* path = dynamic_cast<const ExtrusionPath*>(entity);
if (path !=nullptr) {
polylines.push_back(path->as_polyline());
widths.push_back(path->width());
}
if (this->connected_to_bed) {
this->sticking_area += integrals.area;
this->sticking_centroid_accumulator += to_3d(integrals.x_i, bottom_z * integrals.area);
this->sticking_second_moment_of_area_accumulator += integrals.x_i_squared;
this->sticking_second_moment_of_area_covariance_accumulator += integrals.xy;
const auto* loop = dynamic_cast<const ExtrusionLoop*>(entity);
if (loop !=nullptr) {
for (const ExtrusionPath& path : loop->paths) {
polylines.push_back(path.as_polyline());
widths.push_back(path.width());
}
}
const auto* multi_path = dynamic_cast<const ExtrusionMultiPath*>(entity);
if (multi_path !=nullptr) {
for (const ExtrusionPath& path : multi_path->paths) {
polylines.push_back(path.as_polyline());
widths.push_back(path.width());
}
}
const Integrals integrals{polylines, widths};
const float volume = integrals.area * layer_height;
this->volume += volume;
this->volume_centroid_accumulator += to_3d(integrals.x_i, center_z * integrals.area) / integrals.area * volume;
if (this->connected_to_bed) {
this->sticking_area += integrals.area;
this->sticking_centroid_accumulator += to_3d(integrals.x_i, bottom_z * integrals.area);
this->sticking_second_moment_of_area_accumulator += integrals.x_i_squared;
this->sticking_second_moment_of_area_covariance_accumulator += integrals.xy;
}
}
}

View File

@ -151,6 +151,7 @@ class Integrals{
* @param polygons List of polygons specifing the domain.
*/
explicit Integrals(const Polygons& polygons);
explicit Integrals(const Polylines& polylines, const std::vector<float>& widths);
// TODO refactor and delete the default constructor
Integrals() = default;
@ -159,6 +160,9 @@ class Integrals{
Vec2f x_i{Vec2f::Zero()};
Vec2f x_i_squared{Vec2f::Zero()};
float xy{};
private:
void add(const Integrals& other);
};
float compute_second_moment(

View File

@ -6,7 +6,7 @@ using namespace Slic3r;
using namespace SupportSpotsGenerator;
TEST_CASE("Numerical integral calculation compared with exact solution.", "[SupportSpotsGenerator]") {
TEST_CASE("Numerical integral over polygon calculation compared with exact solution.", "[SupportSpotsGenerator]") {
const float width = 10;
const float height = 20;
const Polygon polygon = {
@ -24,6 +24,19 @@ TEST_CASE("Numerical integral calculation compared with exact solution.", "[Supp
CHECK(integrals.x_i_squared.y() == Approx(width * std::pow(height, 3) / 12));
}
TEST_CASE("Numerical integral over line calculation compared with exact solution.", "[SupportSpotsGenerator]") {
const float length = 10;
const float width = 20;
const Polyline polyline{scaled(Vec2f{-length/2.0f, 0.0f}), scaled(Vec2f{length/2.0f, 0.0f})};
const Integrals integrals{{polyline}, {width}};
CHECK(integrals.area == Approx(length * width));
CHECK(integrals.x_i.x() == Approx(0));
CHECK(integrals.x_i.y() == Approx(0));
CHECK(integrals.x_i_squared.x() == Approx(std::pow(length, 3) * width / 12));
CHECK(integrals.x_i_squared.y() == Approx(length * std::pow(width, 3) / 12));
}
TEST_CASE("Moment values and ratio check.", "[SupportSpotsGenerator]") {
const float width = 40;
const float height = 2;