mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 23:35:59 +08:00
Unify behavior of union for import and add volume
Add cache for final ExPolygons
This commit is contained in:
parent
e043a04207
commit
fa09f03c6a
@ -448,7 +448,10 @@ HealedExPolygons Emboss::heal_polygons(const Polygons &shape, bool is_non_zero,
|
||||
Polygons polygons = to_polygons(paths);
|
||||
polygons.erase(std::remove_if(polygons.begin(), polygons.end(),
|
||||
[](const Polygon &p) { return p.size() < 3; }), polygons.end());
|
||||
|
||||
|
||||
if (polygons.empty())
|
||||
return {{}, false};
|
||||
|
||||
// Do not remove all duplicates but do it better way
|
||||
// Overlap all duplicit points by rectangle 3x3
|
||||
Points duplicits = collect_duplicates(to_points(polygons));
|
||||
@ -1280,23 +1283,8 @@ ExPolygons letter2shapes(
|
||||
const int CANCEL_CHECK = 10;
|
||||
} // namespace
|
||||
|
||||
/// Union shape defined by glyphs
|
||||
HealedExPolygons Slic3r::union_ex(const ExPolygonsWithIds &shapes, unsigned max_heal_iteration)
|
||||
{
|
||||
// unify to one expolygon
|
||||
ExPolygons result;
|
||||
for (const ExPolygonsWithId &shape : shapes) {
|
||||
if (shape.expoly.empty())
|
||||
continue;
|
||||
expolygons_append(result, shape.expoly);
|
||||
}
|
||||
result = union_ex(result);
|
||||
|
||||
bool is_healed = heal_expolygons(result, max_heal_iteration);
|
||||
return {result, is_healed};
|
||||
}
|
||||
|
||||
HealedExPolygons Slic3r::union_with_delta(const ExPolygonsWithIds &shapes, float delta, unsigned max_heal_iteration)
|
||||
namespace {
|
||||
HealedExPolygons union_with_delta(const ExPolygonsWithIds &shapes, float delta, unsigned max_heal_iteration)
|
||||
{
|
||||
// unify to one expolygons
|
||||
ExPolygons expolygons;
|
||||
@ -1306,10 +1294,26 @@ HealedExPolygons Slic3r::union_with_delta(const ExPolygonsWithIds &shapes, float
|
||||
expolygons_append(expolygons, offset_ex(shape.expoly, delta));
|
||||
}
|
||||
ExPolygons result = union_ex(expolygons);
|
||||
result = offset_ex(result, -delta);
|
||||
bool is_healed = heal_expolygons(result, max_heal_iteration);
|
||||
result = offset_ex(result, -delta);
|
||||
bool is_healed = heal_expolygons(result, max_heal_iteration);
|
||||
return {result, is_healed};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ExPolygons Slic3r::union_with_delta(EmbossShape &shape, float delta, unsigned max_heal_iteration)
|
||||
{
|
||||
if (!shape.final_shape.empty())
|
||||
return shape.final_shape;
|
||||
|
||||
HealedExPolygons result = ::union_with_delta(shape.shapes_with_ids, delta, max_heal_iteration);
|
||||
shape.is_healed = result.is_healed;
|
||||
for (const ExPolygonsWithId &e : shape.shapes_with_ids)
|
||||
if (!e.is_healed)
|
||||
shape.is_healed = false;
|
||||
shape.final_shape = std::move(result.expolygons); // cached
|
||||
|
||||
return shape.final_shape;
|
||||
}
|
||||
|
||||
void Slic3r::translate(ExPolygonsWithIds &expolygons_with_ids, const Point &p)
|
||||
{
|
||||
@ -1337,7 +1341,7 @@ HealedExPolygons Emboss::text2shapes(FontFileWithCache &font_with_cache, const c
|
||||
ExPolygonsWithIds vshapes = text2vshapes(font_with_cache, text_w, font_prop, was_canceled);
|
||||
|
||||
float delta = static_cast<float>(1. / SHAPE_SCALE);
|
||||
return union_with_delta(vshapes, delta, MAX_HEAL_ITERATION_OF_TEXT);
|
||||
return ::union_with_delta(vshapes, delta, MAX_HEAL_ITERATION_OF_TEXT);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -31,6 +31,9 @@ struct HealedExPolygons{
|
||||
/// </summary>
|
||||
namespace Emboss
|
||||
{
|
||||
static const float UNION_DELTA = 50.0f; // [approx in nano meters depends on volume scale]
|
||||
static const unsigned UNION_MAX_ITERATIN = 10; // [count]
|
||||
|
||||
/// <summary>
|
||||
/// Collect fonts registred inside OS
|
||||
/// </summary>
|
||||
@ -474,9 +477,8 @@ namespace Emboss
|
||||
void translate(ExPolygonsWithIds &e, const Point &p);
|
||||
BoundingBox get_extents(const ExPolygonsWithIds &e);
|
||||
void center(ExPolygonsWithIds &e);
|
||||
HealedExPolygons union_ex(const ExPolygonsWithIds &shapes, unsigned max_heal_iteration);
|
||||
// delta .. safe offset before union (use as boolean close)
|
||||
// NOTE: remove unprintable spaces between neighbor curves (made by linearization of curve)
|
||||
HealedExPolygons union_with_delta(const ExPolygonsWithIds &shapes, float delta, unsigned max_heal_iteration);
|
||||
ExPolygons union_with_delta(EmbossShape &shape, float delta, unsigned max_heal_iteration);
|
||||
} // namespace Slic3r
|
||||
#endif // slic3r_Emboss_hpp_
|
||||
|
@ -74,6 +74,7 @@ struct EmbossShape
|
||||
{
|
||||
// shapes to to emboss separately over surface
|
||||
ExPolygonsWithIds shapes_with_ids;
|
||||
ExPolygons final_shape; // When not set it is calculated from ExPolygonsWithIds
|
||||
|
||||
// scale of shape, multiplier to get 3d point in mm from integer shape
|
||||
double scale = SCALING_FACTOR;
|
||||
|
@ -3899,7 +3899,7 @@ std::optional<EmbossShape> read_emboss_shape(const char **attributes, unsigned i
|
||||
ExPolygonsWithIds shapes; // TODO: need to implement
|
||||
|
||||
EmbossShape::SvgFile svg{file_path, file_path_3mf};
|
||||
return EmbossShape{shapes, scale, std::move(projection), std::move(fix_tr_mat), std::move(svg), is_healed};
|
||||
return EmbossShape{shapes, {}, scale, std::move(projection), std::move(fix_tr_mat), std::move(svg), is_healed};
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,11 +70,8 @@ bool load_svg(const std::string &input_file, Model &output_model)
|
||||
emboss_shape.svg_file = std::move(svg_file);
|
||||
|
||||
// unify to one expolygons
|
||||
double delta = 1e-3; // in mm
|
||||
unsigned max_heal_iteration = 10;
|
||||
HealedExPolygons union_shape = union_with_delta(emboss_shape.shapes_with_ids, delta, max_heal_iteration);
|
||||
if (!union_shape.is_healed)
|
||||
BOOST_LOG_TRIVIAL(warning) << "SVG file(\"" << input_file << "\") couldn't be fully healed.";
|
||||
// EmbossJob.cpp --> ExPolygons create_shape(DataBase &input, Fnc was_canceled) {
|
||||
ExPolygons union_shape = union_with_delta(emboss_shape, Emboss::UNION_DELTA, Emboss::UNION_MAX_ITERATIN);
|
||||
|
||||
// create projection
|
||||
double scale = emboss_shape.scale;
|
||||
@ -84,7 +81,7 @@ bool load_svg(const std::string &input_file, Model &output_model)
|
||||
Emboss::ProjectTransform project(std::move(projectZ), tr);
|
||||
|
||||
// convert 2d shape to 3d triangles
|
||||
indexed_triangle_set its = Emboss::polygons2model(union_shape.expolygons, project);
|
||||
indexed_triangle_set its = Emboss::polygons2model(union_shape, project);
|
||||
TriangleMesh triangl_mesh(std::move(its));
|
||||
|
||||
// add mesh to model
|
||||
|
@ -907,6 +907,19 @@ void draw_filled(const ExPolygons &shape, const std::array<unsigned char, N>& co
|
||||
}
|
||||
}
|
||||
|
||||
/// Union shape defined by glyphs
|
||||
ExPolygons union_ex(const ExPolygonsWithIds &shapes)
|
||||
{
|
||||
// unify to one expolygon
|
||||
ExPolygons result;
|
||||
for (const ExPolygonsWithId &shape : shapes) {
|
||||
if (shape.expoly.empty())
|
||||
continue;
|
||||
expolygons_append(result, shape.expoly);
|
||||
}
|
||||
return union_ex(result);
|
||||
}
|
||||
|
||||
// init texture by draw expolygons into texture
|
||||
bool init_texture(Texture &texture, const ExPolygonsWithIds& shapes_with_ids, unsigned max_size_px, const std::vector<std::string>& shape_warnings){
|
||||
BoundingBox bb = get_extents(shapes_with_ids);
|
||||
@ -933,10 +946,7 @@ bool init_texture(Texture &texture, const ExPolygonsWithIds& shapes_with_ids, un
|
||||
std::vector<unsigned char> data(n_pixels * channels_count, {0});
|
||||
|
||||
// Union All shapes
|
||||
ExPolygons shape;
|
||||
for (const ExPolygonsWithId &shapes_with_id : shapes_with_ids)
|
||||
expolygons_append(shape, shapes_with_id.expoly);
|
||||
shape = union_ex(shape);
|
||||
ExPolygons shape = union_ex(shapes_with_ids);
|
||||
|
||||
// align to texture
|
||||
translate(shape, -bb.min);
|
||||
|
@ -793,14 +793,10 @@ bool check(const UpdateSurfaceVolumeData &input, bool is_main_thread)
|
||||
template<typename Fnc>
|
||||
ExPolygons create_shape(DataBase &input, Fnc was_canceled) {
|
||||
EmbossShape &es = input.create_shape();
|
||||
float delta = 50.f;
|
||||
unsigned max_heal_iteration = 10;
|
||||
HealedExPolygons result = union_with_delta(es.shapes_with_ids, delta, max_heal_iteration);
|
||||
es.is_healed = result.is_healed;
|
||||
for (const ExPolygonsWithId &e : es.shapes_with_ids)
|
||||
if (!e.is_healed)
|
||||
es.is_healed = false;
|
||||
return result.expolygons;
|
||||
// TODO: improve to use real size of volume
|
||||
// ... need world matrix for volume
|
||||
// ... printer resolution will be fine too
|
||||
return union_with_delta(es, UNION_DELTA, UNION_MAX_ITERATIN);
|
||||
}
|
||||
|
||||
//#define STORE_SAMPLING
|
||||
|
Loading…
x
Reference in New Issue
Block a user