Ported remove_collinear(Polygon) and test_polygon from upstream slic3r.

This commit is contained in:
bubnikv 2019-10-15 18:08:32 +02:00
parent de45be5f29
commit abe856f9fe
5 changed files with 90 additions and 2 deletions

View File

@ -1,7 +1,7 @@
#ifndef slic3r_CoolingBuffer_hpp_
#define slic3r_CoolingBuffer_hpp_
#include "libslic3r.h"
#include "../libslic3r.h"
#include <map>
#include <string>

View File

@ -15,7 +15,7 @@ Polyline Polygon::split_at_vertex(const Point &point) const
// find index of point
for (const Point &pt : this->points)
if (pt == point)
return this->split_at_index(&pt - &this->points.front());
return this->split_at_index(int(&pt - &this->points.front()));
throw std::invalid_argument("Point not found");
return Polyline();
}
@ -394,4 +394,45 @@ bool remove_small(Polygons &polys, double min_area)
return modified;
}
void remove_collinear(Polygon &poly)
{
if (poly.points.size() > 2) {
// copy points and append both 1 and last point in place to cover the boundaries
Points pp;
pp.reserve(poly.points.size()+2);
pp.push_back(poly.points.back());
pp.insert(pp.begin()+1, poly.points.begin(), poly.points.end());
pp.push_back(poly.points.front());
// delete old points vector. Will be re-filled in the loop
poly.points.clear();
size_t i = 0;
size_t k = 0;
while (i < pp.size()-2) {
k = i+1;
const Point &p1 = pp[i];
while (k < pp.size()-1) {
const Point &p2 = pp[k];
const Point &p3 = pp[k+1];
Line l(p1, p3);
if(l.distance_to(p2) < SCALED_EPSILON) {
k++;
} else {
if(i > 0) poly.points.push_back(p1); // implicitly removes the first point we appended above
i = k;
break;
}
}
if(k > pp.size()-2) break; // all remaining points are collinear and can be skipped
}
poly.points.push_back(pp[i]);
}
}
void remove_collinear(Polygons &polys)
{
for (Polygon &poly : polys)
remove_collinear(poly);
}
}

View File

@ -86,6 +86,8 @@ extern bool remove_sticks(Polygons &polys);
// Remove polygons with less than 3 edges.
extern bool remove_degenerate(Polygons &polys);
extern bool remove_small(Polygons &polys, double min_area);
extern void remove_collinear(Polygon &poly);
extern void remove_collinear(Polygons &polys);
// Append a vector of polygons at the end of another vector of polygons.
inline void polygons_append(Polygons &dst, const Polygons &src) { dst.insert(dst.end(), src.begin(), src.end()); }

View File

@ -2,6 +2,7 @@ get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
add_executable(${_TEST_NAME}_tests
${_TEST_NAME}_tests.cpp
test_geometry.cpp
test_polygon.cpp
)
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")

View File

@ -0,0 +1,44 @@
#include <catch2/catch.hpp>
#include "libslic3r/Point.hpp"
#include "libslic3r/Polygon.hpp"
using namespace Slic3r;
// This test currently only covers remove_collinear_points.
// All remaining tests are to be ported from xs/t/06_polygon.t
Slic3r::Points collinear_circle({
Slic3r::Point::new_scale(0, 0), // 3 collinear points at beginning
Slic3r::Point::new_scale(10, 0),
Slic3r::Point::new_scale(20, 0),
Slic3r::Point::new_scale(30, 10),
Slic3r::Point::new_scale(40, 20), // 2 collinear points
Slic3r::Point::new_scale(40, 30),
Slic3r::Point::new_scale(30, 40), // 3 collinear points
Slic3r::Point::new_scale(20, 40),
Slic3r::Point::new_scale(10, 40),
Slic3r::Point::new_scale(-10, 20),
Slic3r::Point::new_scale(-20, 10),
Slic3r::Point::new_scale(-20, 0), // 3 collinear points at end
Slic3r::Point::new_scale(-10, 0),
Slic3r::Point::new_scale(-5, 0)
});
SCENARIO("Remove collinear points from Polygon") {
GIVEN("Polygon with collinear points"){
Slic3r::Polygon p(collinear_circle);
WHEN("collinear points are removed") {
remove_collinear(p);
THEN("Leading collinear points are removed") {
REQUIRE(p.points.front() == Slic3r::Point::new_scale(20, 0));
}
THEN("Trailing collinear points are removed") {
REQUIRE(p.points.back() == Slic3r::Point::new_scale(-20, 0));
}
THEN("Number of remaining points is correct") {
REQUIRE(p.points.size() == 7);
}
}
}
}