Better healing for Glyph shape - remove duplicit points + self intersections
Add search of intersecting points (compared with CGAL) Triangulation can [optionaly] accept multi points
This commit is contained in:
parent
94f735168c
commit
63121cee2e
18 changed files with 892 additions and 241 deletions
|
@ -6,7 +6,7 @@
|
|||
#include <optional>
|
||||
#include <libslic3r/AABBTreeIndirect.hpp>
|
||||
#include <libslic3r/Utils.hpp> // for next_highest_power_of_2()
|
||||
|
||||
#include <libslic3r/IntersectionPoints.hpp>
|
||||
using namespace Slic3r;
|
||||
|
||||
namespace Private{
|
||||
|
@ -157,6 +157,119 @@ TEST_CASE("Convert glyph % to model", "[Emboss]")
|
|||
CHECK(!its.indices.empty());
|
||||
}
|
||||
|
||||
//#define VISUALIZE
|
||||
#ifdef VISUALIZE
|
||||
TEST_CASE("Visualize glyph from font", "[Emboss]")
|
||||
{
|
||||
std::string font_path = "C:/data/ALIENATO.TTF";
|
||||
std::string text = "i";
|
||||
|
||||
Emboss::FontFileWithCache font(
|
||||
Emboss::create_font_file(font_path.c_str()));
|
||||
REQUIRE(font.has_value());
|
||||
FontProp fp;
|
||||
fp.size_in_mm = 8;
|
||||
fp.emboss = 4;
|
||||
ExPolygons shapes = Emboss::text2shapes(font, text.c_str(), fp);
|
||||
|
||||
// char letter = 'i';
|
||||
// unsigned int font_index = 0; // collection
|
||||
// float flatness = 5;
|
||||
// auto glyph = Emboss::letter2glyph(*font.font_file, font_index, letter,
|
||||
// flatness); ExPolygons shapes2 = glyph->shape; { SVG
|
||||
//svg("C:/data/temp/stored_letter.svg", get_extents(shapes2));
|
||||
//svg.draw(shapes2); } // debug shape
|
||||
|
||||
REQUIRE(!shapes.empty());
|
||||
//{ SVG svg("C:/data/temp/shapes.svg"); svg.draw(shapes); } // debug shape
|
||||
|
||||
float z_depth = 100.f;
|
||||
Emboss::ProjectZ projection(z_depth);
|
||||
indexed_triangle_set its = Emboss::polygons2model(shapes, projection);
|
||||
its_write_obj(its, "C:/data/temp/bad_glyph.obj");
|
||||
|
||||
CHECK(!its.indices.empty());
|
||||
TriangleMesh tm(its);
|
||||
auto s = tm.stats();
|
||||
}
|
||||
#endif // VISUALIZE
|
||||
|
||||
#include "test_utils.hpp"
|
||||
#include "nanosvg/nanosvg.h" // load SVG file
|
||||
#include "libslic3r/NSVGUtils.hpp"
|
||||
void heal_and_check(const Polygons &polygons)
|
||||
{
|
||||
Pointfs intersections_prev = intersection_points(polygons);
|
||||
Points polygons_points = to_points(polygons);
|
||||
Points duplicits_prev = collect_duplications(polygons_points);
|
||||
|
||||
ExPolygons shape = Emboss::heal_shape(polygons);
|
||||
|
||||
// Is default shape for unhealabled shape?
|
||||
bool is_default_shape =
|
||||
shape.size() == 1 &&
|
||||
shape.front().contour.points.size() == 4 &&
|
||||
shape.front().holes.size() == 1 &&
|
||||
shape.front().holes.front().points.size() == 4 ;
|
||||
CHECK(!is_default_shape);
|
||||
|
||||
Pointfs intersections = intersection_points(shape);
|
||||
Points shape_points = to_points(shape);
|
||||
Points duplicits = collect_duplications(shape_points);
|
||||
//{
|
||||
// BoundingBox bb(polygons_points);
|
||||
// // bb.scale(svg_scale);
|
||||
// SVG svg("C:/data/temp/test_visualization.svg", bb);
|
||||
// svg.draw(polygons, "gray"); // input
|
||||
// svg.draw(shape, "green"); // output
|
||||
|
||||
// Points pts;
|
||||
// pts.reserve(intersections.size());
|
||||
// for (const Vec2d &intersection : intersections)
|
||||
// pts.push_back(intersection.cast<int>());
|
||||
// svg.draw(pts, "red", 10);
|
||||
// svg.draw(duplicits, "orenge", 10);
|
||||
//}
|
||||
|
||||
CHECK(intersections.empty());
|
||||
CHECK(duplicits.empty());
|
||||
}
|
||||
|
||||
void scale(Polygons &polygons, double multiplicator) {
|
||||
for (Polygon &polygon : polygons)
|
||||
for (Point &p : polygon) p *= multiplicator;
|
||||
}
|
||||
|
||||
TEST_CASE("Heal of damaged polygons", "[Emboss]")
|
||||
{
|
||||
// Shape loaded from svg is letter 'i' from font 'ALIENATE.TTF'
|
||||
std::string file_name = "contour_ALIENATO.TTF_glyph_i.svg";
|
||||
std::string file_path = TEST_DATA_DIR PATH_SEPARATOR + file_name;
|
||||
NSVGimage *image = nsvgParseFromFile(file_path.c_str(), "px", 96.0f);
|
||||
Polygons polygons = NSVGUtils::to_polygons(image);
|
||||
nsvgDelete(image);
|
||||
|
||||
heal_and_check(polygons);
|
||||
|
||||
Polygons scaled_shape = polygons; // copy
|
||||
scale(scaled_shape, 1 / Emboss::SHAPE_SCALE);
|
||||
heal_and_check(scaled_shape);
|
||||
|
||||
// different scale
|
||||
scale(scaled_shape, 10.);
|
||||
heal_and_check(scaled_shape);
|
||||
|
||||
// check reverse order of points
|
||||
Polygons reverse_shape = polygons;
|
||||
for (Polygon &p : reverse_shape)
|
||||
std::reverse(p.points.begin(), p.points.end());
|
||||
heal_and_check(scaled_shape);
|
||||
|
||||
#ifdef VISUALIZE
|
||||
CHECK(false);
|
||||
#endif // VISUALIZE
|
||||
}
|
||||
|
||||
TEST_CASE("Convert text with glyph cache to model", "[Emboss]")
|
||||
{
|
||||
std::string font_path = get_font_filepath();
|
||||
|
|
|
@ -6,31 +6,21 @@
|
|||
using namespace Slic3r;
|
||||
|
||||
namespace Private{
|
||||
void store_trinagulation(const ExPolygons & shape,
|
||||
void store_trinagulation(const ExPolygons &shape,
|
||||
const std::vector<Vec3i> &triangles,
|
||||
const char* file_name = "Triangulation_visualization.svg",
|
||||
double scale = 1e5)
|
||||
const char* file_name = "C:/data/temp/triangulation.svg",
|
||||
double scale = 1e5)
|
||||
{
|
||||
BoundingBox bb;
|
||||
for (const auto &expoly : shape) bb.merge(expoly.contour.points);
|
||||
bb.scale(scale);
|
||||
SVG svg_vis(file_name, bb);
|
||||
svg_vis.draw(shape, "gray", .7f);
|
||||
Points pts = to_points(shape);
|
||||
svg_vis.draw(pts, "black", 4 * scale);
|
||||
|
||||
size_t count = count_points(shape);
|
||||
Points points;
|
||||
points.reserve(count);
|
||||
auto insert_point = [](const Slic3r::Polygon &polygon, Points &points) {
|
||||
for (const Point &p : polygon.points) points.emplace_back(p);
|
||||
};
|
||||
for (const ExPolygon &expolygon : shape) {
|
||||
insert_point(expolygon.contour, points);
|
||||
for (const Slic3r::Polygon &hole : expolygon.holes)
|
||||
insert_point(hole, points);
|
||||
}
|
||||
|
||||
for (const auto &t : triangles) {
|
||||
Polygon triangle({points[t[0]], points[t[1]], points[t[2]]});
|
||||
for (const Vec3i &t : triangles) {
|
||||
Slic3r::Polygon triangle({pts[t[0]], pts[t[1]], pts[t[2]]});
|
||||
triangle.scale(scale);
|
||||
svg_vis.draw(triangle, "green");
|
||||
}
|
||||
|
@ -119,18 +109,19 @@ TEST_CASE("Triangulation M shape polygon", "[triangulation]")
|
|||
}
|
||||
|
||||
// same point in triangulation are not Supported
|
||||
//TEST_CASE("Triangulation 2 polygons with same point", "[triangulation][not supported]")
|
||||
//{
|
||||
// Slic3r::Polygon polygon1 = {
|
||||
// Point(416, 346), Point(445, 362),
|
||||
// Point(463, 389), Point(469, 427) /* This point */,
|
||||
// Point(445, 491)
|
||||
// };
|
||||
// Slic3r::Polygon polygon2 = {
|
||||
// Point(495, 488), Point(469, 427) /* This point */,
|
||||
// Point(495, 364)
|
||||
// };
|
||||
// ExPolygons shape2d = {ExPolygon(polygon1), ExPolygon(polygon2)};
|
||||
// std::vector<Vec3i> shape_triangles = Triangulation::triangulate(shape2d);
|
||||
// store_trinagulation(shape2d, shape_triangles);
|
||||
//}
|
||||
TEST_CASE("Triangulation 2 polygons with same point", "[triangulation]")
|
||||
{
|
||||
Slic3r::Polygon polygon1 = {
|
||||
Point(416, 346), Point(445, 362),
|
||||
Point(463, 389), Point(469, 427) /* This point */,
|
||||
Point(445, 491)
|
||||
};
|
||||
Slic3r::Polygon polygon2 = {
|
||||
Point(495, 488), Point(469, 427) /* This point */,
|
||||
Point(495, 364)
|
||||
};
|
||||
ExPolygons shape2d = {ExPolygon(polygon1), ExPolygon(polygon2)};
|
||||
std::vector<Vec3i> shape_triangles = Triangulation::triangulate(shape2d);
|
||||
//Private::store_trinagulation(shape2d, shape_triangles);
|
||||
CHECK(shape_triangles.size() == 4);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue