Projection text for cut surface is made with double preccission

This commit is contained in:
Filip Sykala - NTB T15p 2022-10-12 16:17:38 +02:00
parent 8511b280bf
commit 3fa3ea0bb4
7 changed files with 439 additions and 416 deletions

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ SurfaceCut cut_surface(const ExPolygons &shapes,
/// <param name="projection">Way of emboss</param> /// <param name="projection">Way of emboss</param>
/// <returns>Mesh</returns> /// <returns>Mesh</returns>
indexed_triangle_set cut2model(const SurfaceCut &cut, indexed_triangle_set cut2model(const SurfaceCut &cut,
const Emboss::IProject3f &projection); const Emboss::IProject3d &projection);
/// <summary> /// <summary>
/// Separate (A)rea (o)f (I)nterest .. AoI from model /// Separate (A)rea (o)f (I)nterest .. AoI from model
@ -68,5 +68,7 @@ indexed_triangle_set its_cut_AoI(const indexed_triangle_set &its,
/// <returns>Copy of indices by mask(with their vertices)</returns> /// <returns>Copy of indices by mask(with their vertices)</returns>
indexed_triangle_set its_mask(const indexed_triangle_set &its, const std::vector<bool> &mask); indexed_triangle_set its_mask(const indexed_triangle_set &its, const std::vector<bool> &mask);
bool corefine_test(const std::string &model_path, const std::string &shape_path);
} // namespace Slic3r } // namespace Slic3r
#endif // slic3r_CutSurface_hpp_ #endif // slic3r_CutSurface_hpp_

View File

@ -303,6 +303,7 @@ ExPolygons Emboss::heal_shape(const Polygons &shape) {
return res; return res;
} }
#define HEAL_CLOSE_POINTS
bool Emboss::heal_shape(ExPolygons &shape, unsigned max_iteration) bool Emboss::heal_shape(ExPolygons &shape, unsigned max_iteration)
{ {
if (shape.empty()) return true; if (shape.empty()) return true;
@ -313,11 +314,11 @@ bool Emboss::heal_shape(ExPolygons &shape, unsigned max_iteration)
Pointfs intersections = intersection_points(shape); Pointfs intersections = intersection_points(shape);
Points duplicits = collect_duplications(to_points(shape)); Points duplicits = collect_duplications(to_points(shape));
Points close = priv::collect_close_points(shape); //Points close = priv::collect_close_points(shape, 1.);
if (intersections.empty() && duplicits.empty() && close.empty()) break; if (intersections.empty() && duplicits.empty() /* && close.empty() */) break;
holes.clear(); holes.clear();
holes.reserve(intersections.size() + duplicits.size() + close.size()); holes.reserve(intersections.size() + duplicits.size() /* + close.size()*/);
// Fix self intersection in result by subtracting hole 2x2 // Fix self intersection in result by subtracting hole 2x2
for (const Vec2d &p : intersections) { for (const Vec2d &p : intersections) {
@ -335,11 +336,11 @@ bool Emboss::heal_shape(ExPolygons &shape, unsigned max_iteration)
} }
// fix close points in simmilar way as duplicits // fix close points in simmilar way as duplicits
for (const Point &p : close) { //for (const Point &p : close) {
Slic3r::Polygon hole(priv::pts_3x3); // Slic3r::Polygon hole(priv::pts_3x3);
hole.translate(p); // hole.translate(p);
holes.push_back(hole); // holes.push_back(hole);
} //}
holes = Slic3r::union_(holes); holes = Slic3r::union_(holes);
shape = Slic3r::diff_ex(shape, holes, ApplySafetyOffset::Yes); shape = Slic3r::diff_ex(shape, holes, ApplySafetyOffset::Yes);
@ -1063,8 +1064,8 @@ indexed_triangle_set polygons2model_unique(
for (const Point &p : points) { for (const Point &p : points) {
auto p2 = projection.create_front_back(p); auto p2 = projection.create_front_back(p);
front_points.push_back(p2.first); front_points.push_back(p2.first.cast<float>());
back_points.push_back(p2.second); back_points.push_back(p2.second.cast<float>());
} }
// insert back points, front are already in // insert back points, front are already in
@ -1132,8 +1133,8 @@ indexed_triangle_set polygons2model_duplicit(
max_index = index; max_index = index;
const Point &p = points[i]; const Point &p = points[i];
auto p2 = projection.create_front_back(p); auto p2 = projection.create_front_back(p);
front_points.push_back(p2.first); front_points.push_back(p2.first.cast<float>());
back_points.push_back(p2.second); back_points.push_back(p2.second.cast<float>());
} }
assert(max_index+1 == count_point); assert(max_index+1 == count_point);
@ -1185,23 +1186,23 @@ indexed_triangle_set Emboss::polygons2model(const ExPolygons &shape2d,
priv::polygons2model_duplicit(shape2d, projection, points, duplicits); priv::polygons2model_duplicit(shape2d, projection, points, duplicits);
} }
std::pair<Vec3f, Vec3f> Emboss::ProjectZ::create_front_back(const Point &p) const std::pair<Vec3d, Vec3d> Emboss::ProjectZ::create_front_back(const Point &p) const
{ {
Vec3f front( Vec3d front(
static_cast<float>(p.x() * SHAPE_SCALE), p.x() * SHAPE_SCALE,
static_cast<float>(p.y() * SHAPE_SCALE), p.y() * SHAPE_SCALE,
0.f); 0.);
return std::make_pair(front, project(front)); return std::make_pair(front, project(front));
} }
Vec3f Emboss::ProjectZ::project(const Vec3f &point) const Vec3d Emboss::ProjectZ::project(const Vec3d &point) const
{ {
Vec3f res = point; // copy Vec3d res = point; // copy
res.z() = m_depth; res.z() = m_depth;
return res; return res;
} }
std::optional<Point> Emboss::ProjectZ::unproject(const Vec3f &p) const { std::optional<Point> Emboss::ProjectZ::unproject(const Vec3d &p) const {
return Point(p.x() / SHAPE_SCALE, p.y() / SHAPE_SCALE); return Point(p.x() / SHAPE_SCALE, p.y() / SHAPE_SCALE);
} }
@ -1267,18 +1268,18 @@ Transform3d Emboss::create_transformation_onto_surface(const Vec3f &position,
// OrthoProject // OrthoProject
std::pair<Vec3f, Vec3f> Emboss::OrthoProject::create_front_back(const Point &p) const { std::pair<Vec3d, Vec3d> Emboss::OrthoProject::create_front_back(const Point &p) const {
Vec3d front(p.x(), p.y(), 0.); Vec3d front(p.x(), p.y(), 0.);
Vec3f front_tr = (m_matrix * front).cast<float>(); Vec3d front_tr = m_matrix * front;
return std::make_pair(front_tr, project(front_tr)); return std::make_pair(front_tr, project(front_tr));
} }
Vec3f Emboss::OrthoProject::project(const Vec3f &point) const Vec3d Emboss::OrthoProject::project(const Vec3d &point) const
{ {
return point + m_direction; return point + m_direction;
} }
std::optional<Point> Emboss::OrthoProject::unproject(const Vec3f &p) const { std::optional<Point> Emboss::OrthoProject::unproject(const Vec3d &p) const {
Vec3d pp = m_matrix_inv * p.cast<double>(); Vec3d pp = m_matrix_inv * p;
return Point(pp.x(), pp.y()); return Point(pp.x(), pp.y());
} }

View File

@ -215,10 +215,10 @@ public:
/// <summary> /// <summary>
/// Project spatial point /// Project spatial point
/// </summary> /// </summary>
class IProject3f class IProject3d
{ {
public: public:
virtual ~IProject3f() = default; virtual ~IProject3d() = default;
/// <summary> /// <summary>
/// Move point with respect to projection direction /// Move point with respect to projection direction
/// e.g. Orthogonal projection will move with point by direction /// e.g. Orthogonal projection will move with point by direction
@ -226,14 +226,14 @@ public:
/// </summary> /// </summary>
/// <param name="point">Spatial point coordinate</param> /// <param name="point">Spatial point coordinate</param>
/// <returns>Projected spatial point</returns> /// <returns>Projected spatial point</returns>
virtual Vec3f project(const Vec3f &point) const = 0; virtual Vec3d project(const Vec3d &point) const = 0;
}; };
/// <summary> /// <summary>
/// Project 2d point into space /// Project 2d point into space
/// Could be plane, sphere, cylindric, ... /// Could be plane, sphere, cylindric, ...
/// </summary> /// </summary>
class IProjection : public IProject3f class IProjection : public IProject3d
{ {
public: public:
virtual ~IProjection() = default; virtual ~IProjection() = default;
@ -246,9 +246,9 @@ public:
/// first - front spatial point /// first - front spatial point
/// second - back spatial point /// second - back spatial point
/// </returns> /// </returns>
virtual std::pair<Vec3f, Vec3f> create_front_back(const Point &p) const = 0; virtual std::pair<Vec3d, Vec3d> create_front_back(const Point &p) const = 0;
virtual std::optional<Point> unproject(const Vec3f &p) const = 0; virtual std::optional<Point> unproject(const Vec3d &p) const = 0;
}; };
/// <summary> /// <summary>
@ -272,59 +272,59 @@ public:
class ProjectZ : public IProjection class ProjectZ : public IProjection
{ {
public: public:
ProjectZ(float depth) : m_depth(depth) {} ProjectZ(double depth) : m_depth(depth) {}
// Inherited via IProject // Inherited via IProject
std::pair<Vec3f, Vec3f> create_front_back(const Point &p) const override; std::pair<Vec3d, Vec3d> create_front_back(const Point &p) const override;
Vec3f project(const Vec3f &point) const override; Vec3d project(const Vec3d &point) const override;
std::optional<Point> unproject(const Vec3f &p) const override; std::optional<Point> unproject(const Vec3d &p) const override;
float m_depth; double m_depth;
}; };
class ProjectScale : public IProjection class ProjectScale : public IProjection
{ {
std::unique_ptr<IProjection> core; std::unique_ptr<IProjection> core;
float m_scale; double m_scale;
public: public:
ProjectScale(std::unique_ptr<IProjection> core, float scale) ProjectScale(std::unique_ptr<IProjection> core, double scale)
: core(std::move(core)), m_scale(scale) : core(std::move(core)), m_scale(scale)
{} {}
// Inherited via IProject // Inherited via IProject
std::pair<Vec3f, Vec3f> create_front_back(const Point &p) const override std::pair<Vec3d, Vec3d> create_front_back(const Point &p) const override
{ {
auto res = core->create_front_back(p); auto res = core->create_front_back(p);
return std::make_pair(res.first * m_scale, res.second * m_scale); return std::make_pair(res.first * m_scale, res.second * m_scale);
} }
Vec3f project(const Vec3f &point) const override{ Vec3d project(const Vec3d &point) const override{
return core->project(point); return core->project(point);
} }
std::optional<Point> unproject(const Vec3f &p) const override { std::optional<Point> unproject(const Vec3d &p) const override {
return core->unproject(p / m_scale); return core->unproject(p / m_scale);
} }
}; };
class OrthoProject3f : public Emboss::IProject3f class OrthoProject3d : public Emboss::IProject3d
{ {
// size and direction of emboss for ortho projection // size and direction of emboss for ortho projection
Vec3f m_direction; Vec3d m_direction;
public: public:
OrthoProject3f(Vec3f direction) : m_direction(direction) {} OrthoProject3d(Vec3d direction) : m_direction(direction) {}
Vec3f project(const Vec3f &point) const override{ return point + m_direction;} Vec3d project(const Vec3d &point) const override{ return point + m_direction;}
}; };
class OrthoProject: public Emboss::IProjection { class OrthoProject: public Emboss::IProjection {
Transform3d m_matrix; Transform3d m_matrix;
// size and direction of emboss for ortho projection // size and direction of emboss for ortho projection
Vec3f m_direction; Vec3d m_direction;
Transform3d m_matrix_inv; Transform3d m_matrix_inv;
public: public:
OrthoProject(Transform3d matrix, Vec3f direction) OrthoProject(Transform3d matrix, Vec3d direction)
: m_matrix(matrix), m_direction(direction), m_matrix_inv(matrix.inverse()) : m_matrix(matrix), m_direction(direction), m_matrix_inv(matrix.inverse())
{} {}
// Inherited via IProject // Inherited via IProject
std::pair<Vec3f, Vec3f> create_front_back(const Point &p) const override; std::pair<Vec3d, Vec3d> create_front_back(const Point &p) const override;
Vec3f project(const Vec3f &point) const override; Vec3d project(const Vec3d &point) const override;
std::optional<Point> unproject(const Vec3f &p) const override; std::optional<Point> unproject(const Vec3d &p) const override;
}; };
}; };

View File

@ -97,7 +97,7 @@ static Emboss::OrthoProject create_projection_for_cut(
/// <param name="tr">Text voliume transformation inside object</param> /// <param name="tr">Text voliume transformation inside object</param>
/// <param name="cut">Cutted surface from model</param> /// <param name="cut">Cutted surface from model</param>
/// <returns>Projection</returns> /// <returns>Projection</returns>
static Emboss::OrthoProject3f create_emboss_projection( static Emboss::OrthoProject3d create_emboss_projection(
bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut); bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut);
static void create_message(const std::string &message); // only in finalize static void create_message(const std::string &message); // only in finalize
@ -428,7 +428,7 @@ void UseSurfaceJob::process(Ctl &ctl) {
if (was_canceled()) return; if (was_canceled()) return;
// !! Projection needs to transform cut // !! Projection needs to transform cut
Emboss::OrthoProject3f projection = priv::create_emboss_projection( Emboss::OrthoProject3d projection = priv::create_emboss_projection(
m_input.is_outside, fp.emboss, emboss_tr, cut); m_input.is_outside, fp.emboss, emboss_tr, cut);
indexed_triangle_set new_its = cut2model(cut, projection); indexed_triangle_set new_its = cut2model(cut, projection);
@ -664,8 +664,8 @@ Emboss::OrthoProject priv::create_projection_for_cut(
double shape_scale, double shape_scale,
const std::pair<float, float> &z_range) const std::pair<float, float> &z_range)
{ {
float min_z = z_range.first - priv::safe_extension; double min_z = z_range.first - priv::safe_extension;
float max_z = z_range.second + priv::safe_extension; double max_z = z_range.second + priv::safe_extension;
assert(min_z < max_z); assert(min_z < max_z);
// range between min and max value // range between min and max value
double projection_size = max_z - min_z; double projection_size = max_z - min_z;
@ -676,8 +676,7 @@ Emboss::OrthoProject priv::create_projection_for_cut(
// Y .. from bottom to top // Y .. from bottom to top
// Z .. from text to eye // Z .. from text to eye
Vec3d untransformed_direction(0., 0., projection_size); Vec3d untransformed_direction(0., 0., projection_size);
Vec3f project_direction = Vec3d project_direction = transformation_for_vector * untransformed_direction;
(transformation_for_vector * untransformed_direction).cast<float>();
// Projection is in direction from far plane // Projection is in direction from far plane
tr.translate(Vec3d(0., 0., min_z)); tr.translate(Vec3d(0., 0., min_z));
@ -685,7 +684,7 @@ Emboss::OrthoProject priv::create_projection_for_cut(
return Emboss::OrthoProject(tr, project_direction); return Emboss::OrthoProject(tr, project_direction);
} }
Emboss::OrthoProject3f priv::create_emboss_projection( Emboss::OrthoProject3d priv::create_emboss_projection(
bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut) bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut)
{ {
// Offset of clossed side to model // Offset of clossed side to model
@ -694,8 +693,8 @@ Emboss::OrthoProject3f priv::create_emboss_projection(
front_move = (is_outside) ? emboss : surface_offset, front_move = (is_outside) ? emboss : surface_offset,
back_move = -((is_outside) ? surface_offset : emboss); back_move = -((is_outside) ? surface_offset : emboss);
its_transform(cut, tr.pretranslate(Vec3d(0., 0., front_move))); its_transform(cut, tr.pretranslate(Vec3d(0., 0., front_move)));
Vec3f from_front_to_back(0.f, 0.f, back_move - front_move); Vec3d from_front_to_back(0., 0., back_move - front_move);
return Emboss::OrthoProject3f(from_front_to_back); return Emboss::OrthoProject3d(from_front_to_back);
} }
bool priv::process(std::exception_ptr &eptr) { bool priv::process(std::exception_ptr &eptr) {

View File

@ -11,7 +11,7 @@ TEST_CASE("Cut character from surface", "[]")
char letter = '%'; char letter = '%';
float flatness = 2.; float flatness = 2.;
unsigned int font_index = 0; // collection unsigned int font_index = 0; // collection
float z_depth = 50.f; // projection size double z_depth = 50.f; // projection size
auto font = Emboss::create_font_file(font_path.c_str()); auto font = Emboss::create_font_file(font_path.c_str());
REQUIRE(font != nullptr); REQUIRE(font != nullptr);
@ -24,7 +24,7 @@ TEST_CASE("Cut character from surface", "[]")
Transform3d tr = Transform3d::Identity(); Transform3d tr = Transform3d::Identity();
tr.translate(Vec3d(0., 0., -z_depth)); tr.translate(Vec3d(0., 0., -z_depth));
tr.scale(Emboss::SHAPE_SCALE); tr.scale(Emboss::SHAPE_SCALE);
Emboss::OrthoProject cut_projection(tr, Vec3f(0.f, 0.f, z_depth)); Emboss::OrthoProject cut_projection(tr, Vec3d(0., 0., z_depth));
auto object = its_make_cube(782 - 49 + 50, 724 + 10 + 50, 5); auto object = its_make_cube(782 - 49 + 50, 724 + 10 + 50, 5);
its_translate(object, Vec3f(49 - 25, -10 - 25, -40)); its_translate(object, Vec3f(49 - 25, -10 - 25, -40));
@ -38,7 +38,7 @@ TEST_CASE("Cut character from surface", "[]")
CHECK(!surfaces.empty()); CHECK(!surfaces.empty());
Emboss::OrthoProject projection(Transform3d::Identity(), Emboss::OrthoProject projection(Transform3d::Identity(),
Vec3f(0.f, 0.f, 10.f)); Vec3d(0.f, 0.f, 10.f));
its_translate(surfaces, Vec3f(0.f, 0.f, 10)); its_translate(surfaces, Vec3f(0.f, 0.f, 10));
indexed_triangle_set its = cut2model(surfaces, projection); indexed_triangle_set its = cut2model(surfaces, projection);
@ -81,8 +81,8 @@ static Emboss::OrthoProject create_projection_for_cut(
{ {
// create sure that emboss object is bigger than source object // create sure that emboss object is bigger than source object
const float safe_extension = 1.0f; const float safe_extension = 1.0f;
float min_z = z_range.first - safe_extension; double min_z = z_range.first - safe_extension;
float max_z = z_range.second + safe_extension; double max_z = z_range.second + safe_extension;
assert(min_z < max_z); assert(min_z < max_z);
// range between min and max value // range between min and max value
double projection_size = max_z - min_z; double projection_size = max_z - min_z;
@ -93,8 +93,7 @@ static Emboss::OrthoProject create_projection_for_cut(
// Y .. from bottom to top // Y .. from bottom to top
// Z .. from text to eye // Z .. from text to eye
Vec3d untransformed_direction(0., 0., projection_size); Vec3d untransformed_direction(0., 0., projection_size);
Vec3f project_direction = Vec3d project_direction = transformation_for_vector * untransformed_direction;
(transformation_for_vector * untransformed_direction).cast<float>();
// Projection is in direction from far plane // Projection is in direction from far plane
tr.translate(Vec3d(0., 0., min_z)); tr.translate(Vec3d(0., 0., min_z));

View File

@ -433,8 +433,8 @@ TEST_CASE("Cut surface", "[]")
std::string font_path = get_font_filepath(); std::string font_path = get_font_filepath();
char letter = '%'; char letter = '%';
float flatness = 2.; float flatness = 2.;
unsigned int font_index = 0; // collection unsigned int font_index = 0; // collection
float z_depth = 50.f; // projection size double z_depth = 50.; // projection size
auto font = Emboss::create_font_file(font_path.c_str()); auto font = Emboss::create_font_file(font_path.c_str());
REQUIRE(font != nullptr); REQUIRE(font != nullptr);
@ -451,7 +451,7 @@ TEST_CASE("Cut surface", "[]")
Transform3d tr = Transform3d::Identity(); Transform3d tr = Transform3d::Identity();
tr.translate(Vec3d(0., 0., -z_depth)); tr.translate(Vec3d(0., 0., -z_depth));
tr.scale(Emboss::SHAPE_SCALE); tr.scale(Emboss::SHAPE_SCALE);
Emboss::OrthoProject cut_projection(tr, Vec3f(0.f, 0.f, z_depth)); Emboss::OrthoProject cut_projection(tr, Vec3d(0., 0., z_depth));
auto object = its_make_cube(782 - 49 + 50, 724 + 10 + 50, 5); auto object = its_make_cube(782 - 49 + 50, 724 + 10 + 50, 5);
its_translate(object, Vec3f(49 - 25, -10 - 25, -40)); its_translate(object, Vec3f(49 - 25, -10 - 25, -40));
@ -462,8 +462,8 @@ TEST_CASE("Cut surface", "[]")
auto surfaces = cut_surface(shape, {object}, cut_projection, 0); auto surfaces = cut_surface(shape, {object}, cut_projection, 0);
CHECK(!surfaces.empty()); CHECK(!surfaces.empty());
Emboss::OrthoProject projection(Transform3d::Identity(), Vec3f(0.f, 0.f, 10.f)); Emboss::OrthoProject projection(Transform3d::Identity(), Vec3d(0., 0., 10.));
its_translate(surfaces, Vec3f(0.f, 0.f, 10)); its_translate(surfaces, Vec3f(0., 0., 10.));
indexed_triangle_set its = cut2model(surfaces, projection); indexed_triangle_set its = cut2model(surfaces, projection);
CHECK(!its.empty()); CHECK(!its.empty());