OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
anonymous_namespace{Emboss.cpp} Namespace Reference

Classes

struct  SpikeDesc
struct  Duplicate

Typedefs

using Polygon = Slic3r::Polygon
using Duplicates = std::vector<Duplicate>
using Coord2 = double
using P2 = Eigen::Matrix<Coord2, 2, 1, Eigen::DontAlign>

Functions

bool is_valid (const FontFile &font, unsigned int index)
fontinfo_opt load_font_info (const unsigned char *data, unsigned int index=0)
std::optional< Glyph > get_glyph (const stbtt_fontinfo &font_info, int unicode_letter, float flatness)
const Glyph * get_glyph (int unicode, const FontFile &font, const FontProp &font_prop, Glyphs &cache, fontinfo_opt &font_info_opt)
Point to_point (const stbtt__point &point)
void remove_bad (Polygons &polygons)
void remove_bad (ExPolygons &expolygons)
ExPolygon create_bounding_rect (const ExPolygons &shape)
bool heal_dupl_inter (ExPolygons &shape, unsigned max_iteration)
const Points pts_2x2 ({Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)})
const Points pts_3x3 ({Point(-1, -1), Point(1, -1), Point(1, 1), Point(-1, 1)})
bool remove_when_spike (Polygon &polygon, size_t index, const SpikeDesc &spike_desc)
void remove_spikes_in_duplicates (ExPolygons &expolygons, const Points &duplicates)
Points get_unique_intersections (const Slic3r::IntersectionsLines &intersections)
Polygons get_holes_with_points (const Polygons &holes, const Points &points)
bool fill_trouble_holes (const Polygons &holes, const Points &duplicates, const Points &intersections, ExPolygons &shape)
 Fill holes which create duplicits or intersections When healing hole creates trouble in shape again try to heal by an union instead of diff_ex.
Duplicates collect_duplicit_indices (const ExPolygons &expoly)
Points get_points (const Duplicates &duplicate_indices)
ExPolygons letter2shapes (wchar_t letter, Point &cursor, FontFileWithCache &font_with_cache, const FontProp &font_prop, fontinfo_opt &font_info_cache)
HealedExPolygons union_with_delta (const ExPolygonsWithIds &shapes, float delta, unsigned max_heal_iteration)
void align_shape (ExPolygonsWithIds &shapes, const std::wstring &text, const FontProp &prop, const FontFile &font)
 Align shape against pivot.
void add_quad (uint32_t i1, uint32_t i2, indexed_triangle_set &result, uint32_t count_point)
indexed_triangle_set polygons2model_unique (const ExPolygons &shape2d, const IProjection &projection, const Points &points)
indexed_triangle_set polygons2model_duplicit (const ExPolygons &shape2d, const IProjection &projection, const Points &points, const Points &duplicits)
bool point_in_distance (const Coord2 &distance_sq, PolygonPoint &polygon_point, const size_t &i, const Slic3r::Polygon &polygon, bool is_first, bool is_reverse=false)
void point_in_distance (int32_t distance, PolygonPoint &p, const Slic3r::Polygon &polygon)
void point_in_reverse_distance (int32_t distance, PolygonPoint &p, const Slic3r::Polygon &polygon)
float get_align_y_offset (FontProp::VerticalAlign align, unsigned count_lines, const FontFile &ff, const FontProp &fp)
int32_t get_align_x_offset (FontProp::HorizontalAlign align, const BoundingBox &shape_bb, const BoundingBox &line_bb)

Variables

const int CANCEL_CHECK = 10

Class Documentation

◆ anonymous_namespace{Emboss.cpp}::Duplicate

struct anonymous_namespace{Emboss.cpp}::Duplicate
Collaboration diagram for anonymous_namespace{Emboss.cpp}::Duplicate:
Class Members
vector< uint32_t > indices
Point point

Typedef Documentation

◆ Coord2

using anonymous_namespace{Emboss.cpp}::Coord2 = double

◆ Duplicates

using anonymous_namespace{Emboss.cpp}::Duplicates = std::vector<Duplicate>

◆ P2

using anonymous_namespace{Emboss.cpp}::P2 = Eigen::Matrix<Coord2, 2, 1, Eigen::DontAlign>

◆ Polygon

using anonymous_namespace{Emboss.cpp}::Polygon = Slic3r::Polygon

Function Documentation

◆ add_quad()

void anonymous_namespace{Emboss.cpp}::add_quad ( uint32_t i1,
uint32_t i2,
indexed_triangle_set & result,
uint32_t count_point )
1584{
1585 // bottom indices
1586 uint32_t i1_ = i1 + count_point;
1587 uint32_t i2_ = i2 + count_point;
1588 result.indices.emplace_back(i2, i2_, i1);
1589 result.indices.emplace_back(i1_, i1, i2_);
1590};

Referenced by polygons2model_duplicit(), and polygons2model_unique().

Here is the caller graph for this function:

◆ align_shape()

void anonymous_namespace{Emboss.cpp}::align_shape ( ExPolygonsWithIds & shapes,
const std::wstring & text,
const FontProp & prop,
const FontFile & font )

Align shape against pivot.

Parameters
shapesShapes to align Prerequisities: shapes are aligned left top
textTo detect end of lines - to be able horizontal center the line
propContaine Horizontal and vertical alignment
fontNeeded for scale and font size
2071{
2072 // Shapes have to match letters in text
2073 assert(shapes.size() == text.length());
2074
2075 unsigned count_lines = get_count_lines(text);
2076 int y_offset = get_align_y_offset(prop.align.second, count_lines, font, prop);
2077
2078 // Speed up for left aligned text
2079 if (prop.align.first == FontProp::HorizontalAlign::left){
2080 // already horizontaly aligned
2081 for (ExPolygonsWithId& shape : shapes)
2082 for (ExPolygon &s : shape.expoly)
2083 s.translate(Point(0, y_offset));
2084 return;
2085 }
2086
2087 BoundingBox shape_bb;
2088 for (const ExPolygonsWithId& shape: shapes)
2089 shape_bb.merge(get_extents(shape.expoly));
2090
2091 auto get_line_bb = [&](size_t j) {
2092 BoundingBox line_bb;
2093 for (; j < text.length() && text[j] != '\n'; ++j)
2094 line_bb.merge(get_extents(shapes[j].expoly));
2095 return line_bb;
2096 };
2097
2098 // Align x line by line
2099 Point offset(
2100 get_align_x_offset(prop.align.first, shape_bb, get_line_bb(0)),
2101 y_offset);
2102 for (size_t i = 0; i < shapes.size(); ++i) {
2103 wchar_t letter = text[i];
2104 if (letter == '\n'){
2105 offset.x() = get_align_x_offset(prop.align.first, shape_bb, get_line_bb(i + 1));
2106 continue;
2107 }
2108 ExPolygons &shape = shapes[i].expoly;
2109 for (ExPolygon &s : shape)
2110 s.translate(offset);
2111 }
2112}
void merge(const PointType &point)
Definition BoundingBox.cpp:75
Definition BoundingBox.hpp:212
Definition ExPolygon.hpp:23
void translate(double x, double y)
Definition ExPolygon.hpp:48
Definition Point.hpp:199
unsigned get_count_lines(const std::wstring &ws)
Sum of character ' '.
Definition Emboss.cpp:1437
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20
BoundingBox get_extents(const ExPolygonsWithIds &e)
Definition Emboss.cpp:1374
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
Definition EmbossShape.hpp:47
int32_t get_align_x_offset(FontProp::HorizontalAlign align, const BoundingBox &shape_bb, const BoundingBox &line_bb)
Definition Emboss.cpp:2059
float get_align_y_offset(FontProp::VerticalAlign align, unsigned count_lines, const FontFile &ff, const FontProp &fp)
Definition Emboss.cpp:2041
Align align
Definition TextConfiguration.hpp:54

References Slic3r::FontProp::align, align_shape(), get_align_x_offset(), get_align_y_offset(), Slic3r::Emboss::get_count_lines(), Slic3r::get_extents(), Slic3r::FontProp::left, Slic3r::BoundingBoxBase< PointType, APointsType >::merge(), Slic3r::offset(), and Slic3r::ExPolygon::translate().

Referenced by align_shape(), and Slic3r::Emboss::text2vshapes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ collect_duplicit_indices()

Duplicates anonymous_namespace{Emboss.cpp}::collect_duplicit_indices ( const ExPolygons & expoly)
609{
610 Points pts = to_points(expoly);
611
612 // initialize original index locations
613 std::vector<uint32_t> idx(pts.size());
614 std::iota(idx.begin(), idx.end(), 0);
615 std::sort(idx.begin(), idx.end(),
616 [&pts](uint32_t i1, uint32_t i2) { return pts[i1] < pts[i2]; });
617
618 Duplicates result;
619 const Point *prev = &pts[idx.front()];
620 for (size_t i = 1; i < idx.size(); ++i) {
621 uint32_t index = idx[i];
622 const Point *act = &pts[index];
623 if (*prev == *act) {
624 // duplicit point
625 if (!result.empty() && result.back().point == *act) {
626 // more than 2 points with same coordinate
627 result.back().indices.push_back(index);
628 } else {
629 uint32_t prev_index = idx[i-1];
630 result.push_back({*act, {prev_index, index}});
631 }
632 continue;
633 }
634 prev = act;
635 }
636 return result;
637}
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
Points to_points(const ExPolygons &src)
Definition ExPolygon.hpp:222
std::vector< Duplicate > Duplicates
Definition Emboss.cpp:607

References Slic3r::to_points().

Referenced by heal_dupl_inter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_bounding_rect()

ExPolygon anonymous_namespace{Emboss.cpp}::create_bounding_rect ( const ExPolygons & shape)
735 {
736 BoundingBox bb = get_extents(shape);
737 Point size = bb.size();
738 if (size.x() < 10)
739 bb.max.x() += 10;
740 if (size.y() < 10)
741 bb.max.y() += 10;
742
743 Polygon rect({// CCW
744 bb.min,
745 {bb.max.x(), bb.min.y()},
746 bb.max,
747 {bb.min.x(), bb.max.y()}});
748
749 Point offset = bb.size() * 0.1;
750 Polygon hole({// CW
751 bb.min + offset,
752 {bb.min.x() + offset.x(), bb.max.y() - offset.y()},
753 bb.max - offset,
754 {bb.max.x() - offset.x(), bb.min.y() + offset.y()}});
755
756 return ExPolygon(rect, hole);
757}
PointType max
Definition BoundingBox.hpp:21
PointType size() const
Definition BoundingBox.cpp:178
PointType min
Definition BoundingBox.hpp:20
Slic3r::Polygon Polygon
Definition Emboss.cpp:101

References Slic3r::get_extents(), Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::offset(), and Slic3r::BoundingBoxBase< PointType, APointsType >::size().

Referenced by heal_dupl_inter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_trouble_holes()

bool anonymous_namespace{Emboss.cpp}::fill_trouble_holes ( const Polygons & holes,
const Points & duplicates,
const Points & intersections,
ExPolygons & shape )

Fill holes which create duplicits or intersections When healing hole creates trouble in shape again try to heal by an union instead of diff_ex.

Parameters
holesHoles which was substracted from shape previous
duplicatesCurrent duplicates in shape
intersectionsCurrent intersections in shape
shapePartialy healed shape[could be modified]
Returns
True when modify shape otherwise False
586{
587 if (holes.empty())
588 return false;
589 if (duplicates.empty() && intersections.empty())
590 return false;
591
592 Polygons fill = get_holes_with_points(holes, duplicates);
593 append(fill, get_holes_with_points(holes, intersections));
594 if (fill.empty())
595 return false;
596
597 shape = union_ex(shape, fill);
598 return true;
599}
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, PolyFillType fill_type)
Definition ClipperUtils.cpp:1011
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157
const Polygons & holes(const ExPolygon &p)
Definition AGGRaster.hpp:31
Polygons get_holes_with_points(const Polygons &holes, const Points &points)
Definition Emboss.cpp:563

References Slic3r::append(), get_holes_with_points(), Slic3r::holes(), and Slic3r::union_ex().

Referenced by heal_dupl_inter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_align_x_offset()

int32_t anonymous_namespace{Emboss.cpp}::get_align_x_offset ( FontProp::HorizontalAlign align,
const BoundingBox & shape_bb,
const BoundingBox & line_bb )
2060{
2061 switch (align) {
2062 case FontProp::HorizontalAlign::right: return -shape_bb.max.x() + (shape_bb.size().x() - line_bb.size().x());
2063 case FontProp::HorizontalAlign::center: return -shape_bb.center().x() + (shape_bb.size().x() - line_bb.size().x()) / 2;
2064 case FontProp::HorizontalAlign::left: // no change
2065 default: break;
2066 }
2067 return 0;
2068}
PointType center() const
Definition BoundingBox.cpp:228

References Slic3r::BoundingBoxBase< PointType, APointsType >::center(), Slic3r::FontProp::center, get_align_x_offset(), Slic3r::FontProp::left, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::FontProp::right, and Slic3r::BoundingBoxBase< PointType, APointsType >::size().

Referenced by align_shape(), and get_align_x_offset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_align_y_offset()

float anonymous_namespace{Emboss.cpp}::get_align_y_offset ( FontProp::VerticalAlign align,
unsigned count_lines,
const FontFile & ff,
const FontProp & fp )
2042{
2043 assert(count_lines != 0);
2044 int line_height = get_line_height(ff, fp);
2045 int ascent = get_font_info(ff, fp).ascent / SHAPE_SCALE;
2046 float line_center = static_cast<float>(std::round(ascent * ASCENT_CENTER));
2047
2048 // direction of Y in 2d is from top to bottom
2049 // zero is on base line of first line
2050 switch (align) {
2051 case FontProp::VerticalAlign::bottom: return line_height * (count_lines - 1);
2052 case FontProp::VerticalAlign::top: return -ascent;
2053 case FontProp::VerticalAlign::center:
2054 default:
2055 return -line_center + line_height * (count_lines - 1) / 2.;
2056 }
2057}
const double ASCENT_CENTER
Definition Emboss.cpp:49
static constexpr double SHAPE_SCALE
Definition Emboss.cpp:53
int get_line_height(const FontFile &font, const FontProp &prop)
Read from font file and properties height of line with spacing.
Definition Emboss.cpp:1280
const FontFile::Info & get_font_info(const FontFile &font, const FontProp &prop)
getter of font info by collection defined in prop
Definition Emboss.cpp:1273
int ascent
Definition Emboss.hpp:81

References Slic3r::Emboss::FontFile::Info::ascent, ASCENT_CENTER, Slic3r::FontProp::bottom, Slic3r::FontProp::center, get_align_y_offset(), Slic3r::Emboss::get_font_info(), Slic3r::Emboss::get_line_height(), SHAPE_SCALE, and Slic3r::FontProp::top.

Referenced by align_shape(), and get_align_y_offset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_glyph() [1/2]

std::optional< Glyph > anonymous_namespace{Emboss.cpp}::get_glyph ( const stbtt_fontinfo & font_info,
int unicode_letter,
float flatness )
780{
781 int glyph_index = stbtt_FindGlyphIndex(&font_info, unicode_letter);
782 if (glyph_index == 0) {
783 //wchar_t wchar = static_cast<wchar_t>(unicode_letter);
784 //<< "Character unicode letter ("
785 //<< "decimal value = " << std::dec << unicode_letter << ", "
786 //<< "hexadecimal value = U+" << std::hex << unicode_letter << std::dec << ", "
787 //<< "wchar value = " << wchar
788 //<< ") is NOT defined inside of the font. \n";
789 return {};
790 }
791
792 Glyph glyph;
793 stbtt_GetGlyphHMetrics(&font_info, glyph_index, &glyph.advance_width, &glyph.left_side_bearing);
794
795 stbtt_vertex *vertices;
796 int num_verts = stbtt_GetGlyphShape(&font_info, glyph_index, &vertices);
797 if (num_verts <= 0) return glyph; // no shape
798 ScopeGuard sg1([&vertices]() { free(vertices); });
799
800 int *contour_lengths = NULL;
801 int num_countour_int = 0;
802 stbtt__point *points = stbtt_FlattenCurves(vertices, num_verts,
803 flatness, &contour_lengths, &num_countour_int, font_info.userdata);
804 if (!points) return glyph; // no valid flattening
805 ScopeGuard sg2([&contour_lengths, &points]() {
806 free(contour_lengths);
807 free(points);
808 });
809
810 size_t num_contour = static_cast<size_t>(num_countour_int);
811 Polygons glyph_polygons;
812 glyph_polygons.reserve(num_contour);
813 size_t pi = 0; // point index
814 for (size_t ci = 0; ci < num_contour; ++ci) {
815 int length = contour_lengths[ci];
816 // check minimal length for triangle
817 if (length < 4) {
818 // weird font
819 pi+=length;
820 continue;
821 }
822 // last point is first point
823 --length;
824 Points pts;
825 pts.reserve(length);
826 for (int i = 0; i < length; ++i)
827 pts.emplace_back(to_point(points[pi++]));
828
829 // last point is first point --> closed contour
830 assert(pts.front() == to_point(points[pi]));
831 ++pi;
832
833 // change outer cw to ccw and inner ccw to cw order
834 std::reverse(pts.begin(), pts.end());
835 glyph_polygons.emplace_back(pts);
836 }
837 if (!glyph_polygons.empty()) {
838 unsigned max_iteration = 10;
839 // TrueTypeFonts use non zero winding number
840 // https://docs.microsoft.com/en-us/typography/opentype/spec/ttch01
841 // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
842 bool is_non_zero = true;
843 glyph.shape = Emboss::heal_polygons(glyph_polygons, is_non_zero, max_iteration);
844 }
845 return glyph;
846}
int advance_width
Definition Emboss.hpp:60
HealedExPolygons heal_polygons(const Polygons &shape, bool is_non_zero=true, unsigned max_iteration=10)
Fix duplicit points and self intersections in polygons. Also try to reduce amount of points and remov...
ExPolygons shape
Definition Emboss.hpp:57
int left_side_bearing
Definition Emboss.hpp:60
double length(const Points &pts)
Definition MultiPoint.hpp:181
Point to_point(const stbtt__point &point)
Definition Emboss.cpp:911

References Slic3r::Emboss::Glyph::advance_width, Slic3r::Emboss::heal_polygons(), Slic3r::Emboss::Glyph::left_side_bearing, Slic3r::length(), Slic3r::Emboss::Glyph::shape, and to_point().

Referenced by get_glyph(), Slic3r::Emboss::letter2glyph(), and letter2shapes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_glyph() [2/2]

const Glyph * anonymous_namespace{Emboss.cpp}::get_glyph ( int unicode,
const FontFile & font,
const FontProp & font_prop,
Glyphs & cache,
fontinfo_opt & font_info_opt )
854{
855 // TODO: Use resolution by printer configuration, or add it into FontProp
856 const float RESOLUTION = 0.0125f; // [in mm]
857 auto glyph_item = cache.find(unicode);
858 if (glyph_item != cache.end()) return &glyph_item->second;
859
860 unsigned int font_index = font_prop.collection_number.value_or(0);
861 if (!is_valid(font, font_index)) return nullptr;
862
863 if (!font_info_opt.has_value()) {
864
865 font_info_opt = load_font_info(font.data->data(), font_index);
866 // can load font info?
867 if (!font_info_opt.has_value()) return nullptr;
868 }
869
870 float flatness = font.infos[font_index].ascent * RESOLUTION / font_prop.size_in_mm;
871
872 // Fix for very small flatness because it create huge amount of points from curve
873 if (flatness < RESOLUTION) flatness = RESOLUTION;
874
875 std::optional<Glyph> glyph_opt = get_glyph(*font_info_opt, unicode, flatness);
876
877 // IMPROVE: multiple loadig glyph without data
878 // has definition inside of font?
879 if (!glyph_opt.has_value()) return nullptr;
880
881 Glyph &glyph = *glyph_opt;
882 if (font_prop.char_gap.has_value())
883 glyph.advance_width += *font_prop.char_gap;
884
885 // scale glyph size
886 glyph.advance_width = static_cast<int>(glyph.advance_width / SHAPE_SCALE);
887 glyph.left_side_bearing = static_cast<int>(glyph.left_side_bearing / SHAPE_SCALE);
888
889 if (!glyph.shape.empty()) {
890 if (font_prop.boldness.has_value()) {
891 float delta = static_cast<float>(*font_prop.boldness / SHAPE_SCALE / font_prop.size_in_mm);
892 glyph.shape = Slic3r::union_ex(offset_ex(glyph.shape, delta));
893 }
894 if (font_prop.skew.has_value()) {
895 double ratio = *font_prop.skew;
896 auto skew = [&ratio](Polygon &polygon) {
897 for (Slic3r::Point &p : polygon.points)
898 p.x() += static_cast<Point::coord_type>(std::round(p.y() * ratio));
899 };
900 for (ExPolygon &expolygon : glyph.shape) {
901 skew(expolygon.contour);
902 for (Polygon &hole : expolygon.holes) skew(hole);
903 }
904 }
905 }
906 auto [it, success] = cache.try_emplace(unicode, std::move(glyph));
907 assert(success);
908 return &it->second;
909}
Polygon contour
Definition ExPolygon.hpp:42
Polygons holes
Definition ExPolygon.hpp:43
coord_t coord_type
Definition Point.hpp:201
static constexpr double RESOLUTION
Definition libslic3r.h:86
Definition Emboss.hpp:54
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:605
bool is_valid(const FontFile &font, unsigned int index)
Definition Emboss.cpp:284
fontinfo_opt load_font_info(const unsigned char *data, unsigned int index=0)
Definition Emboss.cpp:291
std::optional< Glyph > get_glyph(const stbtt_fontinfo &font_info, int unicode_letter, float flatness)
Definition Emboss.cpp:779
std::vector< Info > infos
Definition Emboss.hpp:87
std::unique_ptr< std::vector< unsigned char > > data
Definition Emboss.hpp:76
std::optional< float > boldness
Definition TextConfiguration.hpp:34
std::optional< int > char_gap
Definition TextConfiguration.hpp:25
std::optional< float > skew
Definition TextConfiguration.hpp:39
std::optional< unsigned int > collection_number
Definition TextConfiguration.hpp:43
float size_in_mm
Definition TextConfiguration.hpp:63

References Slic3r::Emboss::Glyph::advance_width, Slic3r::FontProp::boldness, Slic3r::FontProp::char_gap, Slic3r::FontProp::collection_number, Slic3r::ExPolygon::contour, Slic3r::Emboss::FontFile::data, get_glyph(), Slic3r::ExPolygon::holes, Slic3r::Emboss::FontFile::infos, is_valid(), Slic3r::Emboss::Glyph::left_side_bearing, load_font_info(), Slic3r::offset_ex(), Slic3r::MultiPoint::points, RESOLUTION, Slic3r::Emboss::Glyph::shape, SHAPE_SCALE, Slic3r::FontProp::size_in_mm, Slic3r::FontProp::skew, and Slic3r::union_ex().

Here is the call graph for this function:

◆ get_holes_with_points()

Polygons anonymous_namespace{Emboss.cpp}::get_holes_with_points ( const Polygons & holes,
const Points & points )
564{
565 Polygons result;
566 for (const Slic3r::Polygon &hole : holes)
567 for (const Point &p : points)
568 for (const Point &h : hole)
569 if (p == h) {
570 result.push_back(hole);
571 break;
572 }
573 return result;
574}
Definition Polygon.hpp:31

References Slic3r::holes().

Referenced by fill_trouble_holes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_points()

Points anonymous_namespace{Emboss.cpp}::get_points ( const Duplicates & duplicate_indices)
640{
641 Points result;
642 if (duplicate_indices.empty())
643 return result;
644
645 // convert intersections into Points
646 result.reserve(duplicate_indices.size());
647 std::transform(duplicate_indices.begin(), duplicate_indices.end(), std::back_inserter(result),
648 [](const Duplicate &d) { return d.point; });
649 return result;
650}

Referenced by heal_dupl_inter().

Here is the caller graph for this function:

◆ get_unique_intersections()

Points anonymous_namespace{Emboss.cpp}::get_unique_intersections ( const Slic3r::IntersectionsLines & intersections)
544{
545 Points result;
546 if (intersections.empty())
547 return result;
548
549 // convert intersections into Points
550 result.reserve(intersections.size());
551 std::transform(intersections.begin(), intersections.end(), std::back_inserter(result),
552 [](const Slic3r::IntersectionLines &i) { return Point(
553 std::floor(i.intersection.x()),
554 std::floor(i.intersection.y()));
555 });
556 // intersections should be unique poits
557 std::sort(result.begin(), result.end());
558 auto it = std::unique(result.begin(), result.end());
559 result.erase(it, result.end());
560 return result;
561}
Definition IntersectionPoints.hpp:13

Referenced by heal_dupl_inter().

Here is the caller graph for this function:

◆ heal_dupl_inter()

bool anonymous_namespace{Emboss.cpp}::heal_dupl_inter ( ExPolygons & shape,
unsigned max_iteration )
653{
654 if (shape.empty()) return true;
656
657 // create loop permanent memory
659 while (--max_iteration) {
660 Duplicates duplicate_indices = collect_duplicit_indices(shape);
661 //Points duplicates = collect_duplicates(to_points(shape));
662 IntersectionsLines intersections = get_intersections(shape);
663
664 // Check whether shape is already healed
665 if (intersections.empty() && duplicate_indices.empty())
666 return true;
667
668 Points duplicate_points = get_points(duplicate_indices);
669 Points intersection_points = get_unique_intersections(intersections);
670
671 if (fill_trouble_holes(holes, duplicate_points, intersection_points, shape)) {
672 holes.clear();
673 continue;
674 }
675
676 holes.clear();
677 holes.reserve(intersections.size() + duplicate_points.size());
678
679 remove_spikes_in_duplicates(shape, duplicate_points);
680
681 // Fix self intersection in result by subtracting hole 2x2
682 for (const Point &p : intersection_points) {
683 Polygon hole(pts_2x2);
684 hole.translate(p);
685 holes.push_back(hole);
686 }
687
688 // Fix duplicit points by hole 3x3 around duplicit point
689 for (const Point &p : duplicate_points) {
690 Polygon hole(pts_3x3);
691 hole.translate(p);
692 holes.push_back(hole);
693 }
694
695 shape = Slic3r::diff_ex(shape, holes, ApplySafetyOffset::No);
696 // ApplySafetyOffset::Yes is incompatible with function fill_trouble_holes
697 }
698
699 // Create partialy healed output
700 Duplicates duplicates = collect_duplicit_indices(shape);
701 IntersectionsLines intersections = get_intersections(shape);
702 if (duplicates.empty() && intersections.empty()){
703 // healed in the last loop
704 return true;
705 }
706
707 #ifdef VISUALIZE_HEAL
708 visualize_heal(visualize_heal_svg_filepath, shape);
709 #endif // VISUALIZE_HEAL
710
711 assert(false); // Can not heal this shape
712 // investigate how to heal better way
713
714 ExPolygonsIndices ei(shape);
715 std::vector<bool> is_healed(shape.size(), {true});
716 for (const Duplicate &duplicate : duplicates){
717 for (uint32_t i : duplicate.indices)
718 is_healed[ei.cvt(i).expolygons_index] = false;
719 }
720 for (const IntersectionLines &intersection : intersections) {
721 is_healed[ei.cvt(intersection.line_index1).expolygons_index] = false;
722 is_healed[ei.cvt(intersection.line_index2).expolygons_index] = false;
723 }
724
725 for (size_t shape_index = 0; shape_index < shape.size(); shape_index++) {
726 if (!is_healed[shape_index]) {
727 // exchange non healed expoly with bb rect
728 ExPolygon &expoly = shape[shape_index];
729 expoly = create_bounding_rect({expoly});
730 }
731 }
732 return false;
733}
bool remove_same_neighbor(ExPolygons &expolygons)
Definition ExPolygon.cpp:496
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:831
std::vector< IntersectionLines > IntersectionsLines
Definition IntersectionPoints.hpp:18
std::vector< IntersectionLine > IntersectionLines
Definition TriangleMeshSlicer.cpp:160
void duplicate(Model &model, Slic3r::arrangement::ArrangePolygons &copies, VirtualBedFn vfn)
Definition ModelArrange.cpp:77
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:769
IntersectionsLines get_intersections(const Lines &lines)
Definition IntersectionPoints.cpp:46
Points get_unique_intersections(const Slic3r::IntersectionsLines &intersections)
Definition Emboss.cpp:543
ExPolygon create_bounding_rect(const ExPolygons &shape)
Definition Emboss.cpp:735
void remove_spikes_in_duplicates(ExPolygons &expolygons, const Points &duplicates)
Definition Emboss.cpp:251
Duplicates collect_duplicit_indices(const ExPolygons &expoly)
Definition Emboss.cpp:608
Points get_points(const Duplicates &duplicate_indices)
Definition Emboss.cpp:639
bool fill_trouble_holes(const Polygons &holes, const Points &duplicates, const Points &intersections, ExPolygons &shape)
Fill holes which create duplicits or intersections When healing hole creates trouble in shape again t...
Definition Emboss.cpp:585
const Points pts_2x2({Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)})
const Points pts_3x3({Point(-1, -1), Point(1, -1), Point(1, 1), Point(-1, 1)})

References collect_duplicit_indices(), create_bounding_rect(), Slic3r::ExPolygonsIndices::cvt(), Slic3r::diff_ex(), Slic3r::duplicate(), fill_trouble_holes(), Slic3r::get_intersections(), get_points(), get_unique_intersections(), Slic3r::holes(), Slic3r::intersection(), Slic3r::No, pts_2x2(), pts_3x3(), Slic3r::remove_same_neighbor(), remove_spikes_in_duplicates(), and Slic3r::MultiPoint::translate().

Here is the call graph for this function:

◆ is_valid()

bool anonymous_namespace{Emboss.cpp}::is_valid ( const FontFile & font,
unsigned int index )
284 {
285 if (font.data == nullptr) return false;
286 if (font.data->empty()) return false;
287 if (index >= font.infos.size()) return false;
288 return true;
289}

References Slic3r::Emboss::FontFile::data, and Slic3r::Emboss::FontFile::infos.

Referenced by Slic3r::Emboss::create_range_text(), Slic3r::Emboss::get_font_info(), get_glyph(), Slic3r::Emboss::letter2glyph(), and Slic3r::Emboss::text2vshapes().

Here is the caller graph for this function:

◆ letter2shapes()

ExPolygons anonymous_namespace{Emboss.cpp}::letter2shapes ( wchar_t letter,
Point & cursor,
FontFileWithCache & font_with_cache,
const FontProp & font_prop,
fontinfo_opt & font_info_cache )
1290{
1291 assert(font_with_cache.has_value());
1292 if (!font_with_cache.has_value())
1293 return {};
1294
1295 Glyphs &cache = *font_with_cache.cache;
1296 const FontFile &font = *font_with_cache.font_file;
1297
1298 if (letter == '\n') {
1299 cursor.x() = 0;
1300 // 2d shape has opposit direction of y
1301 cursor.y() -= get_line_height(font, font_prop);
1302 return {};
1303 }
1304 if (letter == '\t') {
1305 // '\t' = 4*space => same as imgui
1306 const int count_spaces = 4;
1307 const Glyph *space = get_glyph(int(' '), font, font_prop, cache, font_info_cache);
1308 if (space == nullptr)
1309 return {};
1310 cursor.x() += count_spaces * space->advance_width;
1311 return {};
1312 }
1313 if (letter == '\r')
1314 return {};
1315
1316 int unicode = static_cast<int>(letter);
1317 auto it = cache.find(unicode);
1318
1319 // Create glyph from font file and cache it
1320 const Glyph *glyph_ptr = (it != cache.end()) ? &it->second : get_glyph(unicode, font, font_prop, cache, font_info_cache);
1321 if (glyph_ptr == nullptr)
1322 return {};
1323
1324 // move glyph to cursor position
1325 ExPolygons expolygons = glyph_ptr->shape; // copy
1326 for (ExPolygon &expolygon : expolygons)
1327 expolygon.translate(cursor);
1328
1329 cursor.x() += glyph_ptr->advance_width;
1330 return expolygons;
1331}
std::map< int, Glyph > Glyphs
Definition Emboss.hpp:63
std::shared_ptr< Emboss::Glyphs > cache
Definition Emboss.hpp:121
bool has_value() const
Definition Emboss.hpp:128
std::shared_ptr< const FontFile > font_file
Definition Emboss.hpp:116
keep information from file about font (store file data itself)
Definition Emboss.hpp:71

References Slic3r::Emboss::Glyph::advance_width, Slic3r::Emboss::FontFileWithCache::cache, Slic3r::Emboss::FontFileWithCache::font_file, get_glyph(), Slic3r::Emboss::get_line_height(), Slic3r::Emboss::FontFileWithCache::has_value(), and Slic3r::Emboss::Glyph::shape.

Referenced by Slic3r::Emboss::text2vshapes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_font_info()

fontinfo_opt anonymous_namespace{Emboss.cpp}::load_font_info ( const unsigned char * data,
unsigned int index = 0 )
293{
294 int font_offset = stbtt_GetFontOffsetForIndex(data, index);
295 if (font_offset < 0) {
296 assert(false);
297 // "Font index(" << index << ") doesn't exist.";
298 return {};
299 }
300 stbtt_fontinfo font_info;
301 if (stbtt_InitFont(&font_info, data, font_offset) == 0) {
302 // Can't initialize font.
303 assert(false);
304 return {};
305 }
306 return font_info;
307}

Referenced by Slic3r::Emboss::create_font_file(), Slic3r::Emboss::create_range_text(), get_glyph(), Slic3r::Emboss::is_italic(), and Slic3r::Emboss::letter2glyph().

Here is the caller graph for this function:

◆ point_in_distance() [1/2]

bool anonymous_namespace{Emboss.cpp}::point_in_distance ( const Coord2 & distance_sq,
PolygonPoint & polygon_point,
const size_t & i,
const Slic3r::Polygon & polygon,
bool is_first,
bool is_reverse = false )
1869{
1870 size_t s = polygon.size();
1871 size_t ii = (i + polygon_point.index) % s;
1872
1873 // second point of line
1874 const Point &p = polygon[ii];
1875 Point p_d = p - polygon_point.point;
1876
1877 P2 p_d2 = p_d.cast<Coord2>();
1878 Coord2 p_distance_sq = p_d2.squaredNorm();
1879 if (p_distance_sq < distance_sq)
1880 return false;
1881
1882 // found line
1883 if (is_first) {
1884 // on same line
1885 // center also lay on line
1886 // new point is distance moved from point by direction
1887 polygon_point.point += p_d * sqrt(distance_sq / p_distance_sq);
1888 return true;
1889 }
1890
1891 // line cross circle
1892
1893 // start point of line
1894 size_t ii2 = (is_reverse) ? (ii + 1) % s : (ii + s - 1) % s;
1895 polygon_point.index = (is_reverse) ? ii : ii2;
1896 const Point &p2 = polygon[ii2];
1897
1898 Point line_dir = p2 - p;
1899 P2 line_dir2 = line_dir.cast<Coord2>();
1900
1901 Coord2 a = line_dir2.dot(line_dir2);
1902 Coord2 b = 2 * p_d2.dot(line_dir2);
1903 Coord2 c = p_d2.dot(p_d2) - distance_sq;
1904
1905 double discriminant = b * b - 4 * a * c;
1906 if (discriminant < 0) {
1907 assert(false);
1908 // no intersection
1909 polygon_point.point = p;
1910 return true;
1911 }
1912
1913 // ray didn't totally miss sphere,
1914 // so there is a solution to
1915 // the equation.
1916 discriminant = sqrt(discriminant);
1917
1918 // either solution may be on or off the ray so need to test both
1919 // t1 is always the smaller value, because BOTH discriminant and
1920 // a are nonnegative.
1921 double t1 = (-b - discriminant) / (2 * a);
1922 double t2 = (-b + discriminant) / (2 * a);
1923
1924 double t = std::min(t1, t2);
1925 if (t < 0. || t > 1.) {
1926 // Bad intersection
1927 assert(false);
1928 polygon_point.point = p;
1929 return true;
1930 }
1931
1932 polygon_point.point = p + (t * line_dir2).cast<Point::coord_type>();
1933 return true;
1934}
size_t size() const
Definition MultiPoint.hpp:50
size_t index
Definition Polygon.hpp:305
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299
Point point
Definition Polygon.hpp:308
Eigen::Matrix< Coord2, 2, 1, Eigen::DontAlign > P2
Definition Emboss.cpp:1866
double Coord2
Definition Emboss.cpp:1865

References Slic3r::cast(), Slic3r::PolygonPoint::index, Slic3r::PolygonPoint::point, point_in_distance(), and Slic3r::MultiPoint::size().

Referenced by point_in_distance(), point_in_distance(), and point_in_reverse_distance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ point_in_distance() [2/2]

void anonymous_namespace{Emboss.cpp}::point_in_distance ( int32_t distance,
PolygonPoint & p,
const Slic3r::Polygon & polygon )
1937{
1938 Coord2 distance_sq = static_cast<Coord2>(distance) * distance;
1939 bool is_first = true;
1940 for (size_t i = 1; i < polygon.size(); ++i) {
1941 if (point_in_distance(distance_sq, p, i, polygon, is_first))
1942 return;
1943 is_first = false;
1944 }
1945 // There is not point on polygon with this distance
1946}
bool point_in_distance(const Coord2 &distance_sq, PolygonPoint &polygon_point, const size_t &i, const Slic3r::Polygon &polygon, bool is_first, bool is_reverse=false)
Definition Emboss.cpp:1868

References point_in_distance(), and Slic3r::MultiPoint::size().

Here is the call graph for this function:

◆ point_in_reverse_distance()

void anonymous_namespace{Emboss.cpp}::point_in_reverse_distance ( int32_t distance,
PolygonPoint & p,
const Slic3r::Polygon & polygon )
1949{
1950 Coord2 distance_sq = static_cast<Coord2>(distance) * distance;
1951 bool is_first = true;
1952 bool is_reverse = true;
1953 for (size_t i = polygon.size(); i > 0; --i) {
1954 if (point_in_distance(distance_sq, p, i, polygon, is_first, is_reverse))
1955 return;
1956 is_first = false;
1957 }
1958 // There is not point on polygon with this distance
1959}

References point_in_distance(), point_in_reverse_distance(), and Slic3r::MultiPoint::size().

Referenced by point_in_reverse_distance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ polygons2model_duplicit()

indexed_triangle_set anonymous_namespace{Emboss.cpp}::polygons2model_duplicit ( const ExPolygons & shape2d,
const IProjection & projection,
const Points & points,
const Points & duplicits )
1655{
1656 // CW order of triangle indices
1657 std::vector<uint32_t> changes = Triangulation::create_changes(points, duplicits);
1658 std::vector<Vec3i32> shape_triangles = Triangulation::triangulate(shape2d, points, changes);
1659 uint32_t count_point = *std::max_element(changes.begin(), changes.end()) + 1;
1660
1661 indexed_triangle_set result;
1662 result.vertices.reserve(2 * count_point);
1663 std::vector<Vec3f> &front_points = result.vertices;
1664 std::vector<Vec3f> back_points;
1665 back_points.reserve(count_point);
1666
1667 uint32_t max_index = std::numeric_limits<uint32_t>::max();
1668 for (uint32_t i = 0; i < changes.size(); ++i) {
1669 uint32_t index = changes[i];
1670 if (max_index != std::numeric_limits<uint32_t>::max() &&
1671 index <= max_index) continue; // duplicit point
1672 assert(index == max_index + 1);
1673 assert(front_points.size() == index);
1674 assert(back_points.size() == index);
1675 max_index = index;
1676 const Point &p = points[i];
1677 auto p2 = projection.create_front_back(p);
1678 front_points.push_back(p2.first.cast<float>());
1679 back_points.push_back(p2.second.cast<float>());
1680 }
1681 assert(max_index+1 == count_point);
1682
1683 // insert back points, front are already in
1684 result.vertices.insert(result.vertices.end(),
1685 std::make_move_iterator(back_points.begin()),
1686 std::make_move_iterator(back_points.end()));
1687
1688 result.indices.reserve(shape_triangles.size() * 2 + points.size() * 2);
1689 // top triangles - change to CCW
1690 for (const Vec3i32 &t : shape_triangles)
1691 result.indices.emplace_back(t.x(), t.z(), t.y());
1692 // bottom triangles - use CW
1693 for (const Vec3i32 &t : shape_triangles)
1694 result.indices.emplace_back(t.x() + count_point, t.y() + count_point,
1695 t.z() + count_point);
1696
1697 // quads around - zig zag by triangles
1698 size_t polygon_offset = 0;
1699 auto add_quads = [&polygon_offset, &result, count_point, &changes]
1700 (const Polygon &polygon) {
1701 uint32_t polygon_points = polygon.points.size();
1702 // previous index
1703 uint32_t prev = changes[polygon_offset + polygon_points - 1];
1704 for (uint32_t p = 0; p < polygon_points; ++p) {
1705 uint32_t index = changes[polygon_offset + p];
1706 if (prev == index) continue;
1707 add_quad(prev, index, result, count_point);
1708 prev = index;
1709 }
1710 polygon_offset += polygon_points;
1711 };
1712
1713 for (const ExPolygon &expolygon : shape2d) {
1714 add_quads(expolygon.contour);
1715 for (const Polygon &hole : expolygon.holes) add_quads(hole);
1716 }
1717 return result;
1718}
virtual std::pair< Vec3d, Vec3d > create_front_back(const Point &p) const =0
convert 2d point to 3d points
static Indices triangulate(const Points &points, const HalfEdges &half_edges)
Connect points by triangulation to create filled surface by triangles Input points have to be unique ...
Definition Triangulation.cpp:103
static Changes create_changes(const Points &points, const Points &duplicits)
Create conversion map from original index into new with respect of duplicit point.
Definition Triangulation.cpp:321
Eigen::Matrix< int32_t, 3, 1, Eigen::DontAlign > Vec3i32
Definition Point.hpp:59
void add_quad(uint32_t i1, uint32_t i2, indexed_triangle_set &result, uint32_t count_point)
Definition Emboss.cpp:1580

References add_quad(), Slic3r::Triangulation::create_changes(), Slic3r::Emboss::IProjection::create_front_back(), and Slic3r::Triangulation::triangulate().

Referenced by Slic3r::Emboss::polygons2model().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ polygons2model_unique()

indexed_triangle_set anonymous_namespace{Emboss.cpp}::polygons2model_unique ( const ExPolygons & shape2d,
const IProjection & projection,
const Points & points )
1596{
1597 // CW order of triangle indices
1598 std::vector<Vec3i32> shape_triangles=Triangulation::triangulate(shape2d, points);
1599 uint32_t count_point = points.size();
1600
1601 indexed_triangle_set result;
1602 result.vertices.reserve(2 * count_point);
1603 std::vector<Vec3f> &front_points = result.vertices; // alias
1604 std::vector<Vec3f> back_points;
1605 back_points.reserve(count_point);
1606
1607 for (const Point &p : points) {
1608 auto p2 = projection.create_front_back(p);
1609 front_points.push_back(p2.first.cast<float>());
1610 back_points.push_back(p2.second.cast<float>());
1611 }
1612
1613 // insert back points, front are already in
1614 result.vertices.insert(result.vertices.end(),
1615 std::make_move_iterator(back_points.begin()),
1616 std::make_move_iterator(back_points.end()));
1617 result.indices.reserve(shape_triangles.size() * 2 + points.size() * 2);
1618 // top triangles - change to CCW
1619 for (const Vec3i32 &t : shape_triangles)
1620 result.indices.emplace_back(t.x(), t.z(), t.y());
1621 // bottom triangles - use CW
1622 for (const Vec3i32 &t : shape_triangles)
1623 result.indices.emplace_back(t.x() + count_point,
1624 t.y() + count_point,
1625 t.z() + count_point);
1626
1627 // quads around - zig zag by triangles
1628 size_t polygon_offset = 0;
1629 auto add_quads = [&polygon_offset,&result, &count_point]
1630 (const Polygon& polygon) {
1631 uint32_t polygon_points = polygon.points.size();
1632 // previous index
1633 uint32_t prev = polygon_offset + polygon_points - 1;
1634 for (uint32_t p = 0; p < polygon_points; ++p) {
1635 uint32_t index = polygon_offset + p;
1636 add_quad(prev, index, result, count_point);
1637 prev = index;
1638 }
1639 polygon_offset += polygon_points;
1640 };
1641
1642 for (const ExPolygon &expolygon : shape2d) {
1643 add_quads(expolygon.contour);
1644 for (const Polygon &hole : expolygon.holes) add_quads(hole);
1645 }
1646
1647 return result;
1648}

References add_quad(), Slic3r::Emboss::IProjection::create_front_back(), and Slic3r::Triangulation::triangulate().

Referenced by Slic3r::Emboss::polygons2model().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pts_2x2()

const Points anonymous_namespace{Emboss.cpp}::pts_2x2 ( {Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)} )

Referenced by heal_dupl_inter().

Here is the caller graph for this function:

◆ pts_3x3()

const Points anonymous_namespace{Emboss.cpp}::pts_3x3 ( {Point(-1, -1), Point(1, -1), Point(1, 1), Point(-1, 1)} )

Referenced by heal_dupl_inter().

Here is the caller graph for this function:

◆ remove_bad() [1/2]

void anonymous_namespace{Emboss.cpp}::remove_bad ( ExPolygons & expolygons)
316 {
317 expolygons.erase(
318 std::remove_if(expolygons.begin(), expolygons.end(),
319 [](const ExPolygon &p) { return p.contour.size() < 3; }),
320 expolygons.end());
321
322 for (ExPolygon &expolygon : expolygons)
323 remove_bad(expolygon.holes);
324}
void remove_bad(Polygons &polygons)
Definition Emboss.cpp:309

References remove_bad().

Here is the call graph for this function:

◆ remove_bad() [2/2]

void anonymous_namespace{Emboss.cpp}::remove_bad ( Polygons & polygons)
309 {
310 polygons.erase(
311 std::remove_if(polygons.begin(), polygons.end(),
312 [](const Polygon &p) { return p.size() < 3; }),
313 polygons.end());
314}

Referenced by remove_bad(), and remove_spikes_in_duplicates().

Here is the caller graph for this function:

◆ remove_spikes_in_duplicates()

void anonymous_namespace{Emboss.cpp}::remove_spikes_in_duplicates ( ExPolygons & expolygons,
const Points & duplicates )
251 {
252 if (duplicates.empty())
253 return;
254 auto check = [](Slic3r::Polygon &polygon, const Point &d) -> bool {
255 double spike_bevel = 1 / SHAPE_SCALE;
256 double spike_length = 5.;
257 const static SpikeDesc sd(spike_bevel, spike_length);
258 Points& pts = polygon.points;
259 bool exist_remove = false;
260 for (size_t i = 0; i < pts.size(); i++) {
261 if (pts[i] != d)
262 continue;
263 exist_remove |= remove_when_spike(polygon, i, sd);
264 }
265 return exist_remove && pts.size() < 3;
266 };
267
268 bool exist_remove = false;
269 for (ExPolygon &expolygon : expolygons) {
270 BoundingBox bb(to_points(expolygon.contour));
271 for (const Point &d : duplicates) {
272 if (!bb.contains(d))
273 continue;
274 exist_remove |= check(expolygon.contour, d);
275 for (Polygon &hole : expolygon.holes)
276 exist_remove |= check(hole, d);
277 }
278 }
279
280 if (exist_remove)
281 remove_bad(expolygons);
282}
Points points
Definition MultiPoint.hpp:22
bool remove_when_spike(Polygon &polygon, size_t index, const SpikeDesc &spike_desc)
Definition Emboss.cpp:167
bool check(ModelVolumeType volume_type)
Definition GLGizmoEmboss.cpp:515

References Slic3r::BoundingBoxBase< PointType, APointsType >::contains(), Slic3r::MultiPoint::points, remove_bad(), remove_when_spike(), SHAPE_SCALE, and Slic3r::to_points().

Referenced by heal_dupl_inter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_when_spike()

bool anonymous_namespace{Emboss.cpp}::remove_when_spike ( Slic3r::Polygon & polygon,
size_t index,
const SpikeDesc & spike_desc )
167 {
168
169 std::optional<Point> add;
170 bool do_erase = false;
171 Points &pts = polygon.points;
172 {
173 size_t pts_size = pts.size();
174 if (pts_size < 3)
175 return false;
176
177 const Point &a = (index == 0) ? pts.back() : pts[index - 1];
178 const Point &b = pts[index];
179 const Point &c = (index == (pts_size - 1)) ? pts.front() : pts[index + 1];
180
181 // calc sides
182 Vec2d ba = (a - b).cast<double>();
183 Vec2d bc = (c - b).cast<double>();
184
185 double dot_product = ba.dot(bc);
186
187 // sqrt together after multiplication save one sqrt
188 double ba_size_sq = ba.squaredNorm();
189 double bc_size_sq = bc.squaredNorm();
190 double norm = sqrt(ba_size_sq * bc_size_sq);
191 double cos_angle = dot_product / norm;
192
193 // small angle are around 1 --> cos(0) = 1
194 if (cos_angle < spike_desc.cos_angle)
195 return false; // not a spike
196
197 // has to be in range <-1, 1>
198 // Due to preccission of floating point number could be sligtly out of range
199 if (cos_angle > 1.)
200 cos_angle = 1.;
201 // if (cos_angle < -1.)
202 // cos_angle = -1.;
203
204 // Current Spike angle
205 double angle = acos(cos_angle);
206 double wanted_size = spike_desc.half_bevel / cos(angle / 2.);
207 double wanted_size_sq = wanted_size * wanted_size;
208
209 bool is_ba_short = ba_size_sq < wanted_size_sq;
210 bool is_bc_short = bc_size_sq < wanted_size_sq;
211
212 auto a_side = [&b, &ba, &ba_size_sq, &wanted_size]() -> Point {
213 Vec2d ba_norm = ba / sqrt(ba_size_sq);
214 return b + (wanted_size * ba_norm).cast<coord_t>();
215 };
216 auto c_side = [&b, &bc, &bc_size_sq, &wanted_size]() -> Point {
217 Vec2d bc_norm = bc / sqrt(bc_size_sq);
218 return b + (wanted_size * bc_norm).cast<coord_t>();
219 };
220
221 if (is_ba_short && is_bc_short) {
222 // remove short spike
223 do_erase = true;
224 } else if (is_ba_short) {
225 // move point B on C-side
226 pts[index] = c_side();
227 } else if (is_bc_short) {
228 // move point B on A-side
229 pts[index] = a_side();
230 } else {
231 // move point B on C-side and add point on A-side(left - before)
232 pts[index] = c_side();
233 add = a_side();
234 if (*add == pts[index]) {
235 // should be very rare, when SpikeDesc has small base
236 // will be fixed by remove B point
237 add.reset();
238 do_erase = true;
239 }
240 }
241 }
242 if (do_erase) {
243 pts.erase(pts.begin() + index);
244 return true;
245 }
246 if (add.has_value())
247 pts.insert(pts.begin() + index, *add);
248 return false;
249}
SpiralVase::SpiralPoint add(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:26
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
double cos_angle
Definition Emboss.cpp:129
double half_bevel
Definition Emboss.cpp:132

References Slic3r::angle(), Slic3r::cast(), anonymous_namespace{Emboss.cpp}::SpikeDesc::cos_angle, anonymous_namespace{Emboss.cpp}::SpikeDesc::half_bevel, and Slic3r::MultiPoint::points.

Referenced by remove_spikes_in_duplicates().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_point()

Point anonymous_namespace{Emboss.cpp}::to_point ( const stbtt__point & point)
911 {
912 return Point(static_cast<int>(std::round(point.x / SHAPE_SCALE)),
913 static_cast<int>(std::round(point.y / SHAPE_SCALE)));
914}

References SHAPE_SCALE.

Referenced by get_glyph().

Here is the caller graph for this function:

◆ union_with_delta()

HealedExPolygons anonymous_namespace{Emboss.cpp}::union_with_delta ( const ExPolygonsWithIds & shapes,
float delta,
unsigned max_heal_iteration )
1341{
1342 // unify to one expolygons
1343 ExPolygons expolygons;
1344 for (const ExPolygonsWithId &shape : shapes) {
1345 if (shape.expoly.empty())
1346 continue;
1347 expolygons_append(expolygons, offset_ex(shape.expoly, delta));
1348 }
1349 ExPolygons result = union_ex(expolygons);
1350 result = offset_ex(result, -delta);
1351 bool is_healed = heal_expolygons(result, max_heal_iteration);
1352 return {result, is_healed};
1353}
bool heal_expolygons(ExPolygons &shape, unsigned max_iteration=10)
NOTE: call Slic3r::union_ex before this call.
Definition Emboss.cpp:536
void expolygons_append(ExPolygons &dst, const ExPolygons &src)
Definition ExPolygon.hpp:447

References Slic3r::expolygons_append(), Slic3r::Emboss::heal_expolygons(), Slic3r::offset_ex(), and Slic3r::union_ex().

Referenced by Slic3r::union_with_delta().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ CANCEL_CHECK

const int anonymous_namespace{Emboss.cpp}::CANCEL_CHECK = 10