OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::EdgeGrid::Grid Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/EdgeGrid.hpp>

Collaboration diagram for Slic3r::EdgeGrid::Grid:

Classes

struct  ClosestPointResult
struct  Cell

Public Types

typedef std::pair< const Contour *, size_t > ContourPoint
typedef std::pair< const Contour *, size_t > ContourEdge

Public Member Functions

 Grid ()=default
 Grid (const BoundingBox &bbox)
void set_bbox (const BoundingBox &bbox)
void create (const std::vector< Points > &polylines_or_polygons, coord_t resolution, bool open)
void create (const Polygons &polygons, const Polylines &polylines, coord_t resolution)
void create (const Polygons &polygons, coord_t resolution)
void create (const std::vector< const Polygon * > &polygons, coord_t resolution)
void create (const std::vector< Points > &polygons, coord_t resolution)
void create (const ExPolygon &expoly, coord_t resolution)
void create (const ExPolygons &expolygons, coord_t resolution)
const std::vector< Contour > & contours () const
void calculate_sdf ()
float signed_distance_bilinear (const Point &pt) const
ClosestPointResult closest_point_signed_distance (const Point &pt, coord_t search_radius) const
bool signed_distance_edges (const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment=nullptr) const
bool signed_distance (const Point &pt, coord_t search_radius, coordf_t &result_min_dist) const
const BoundingBox & bbox () const
const coord_t resolution () const
const size_t rows () const
const size_t cols () const
Polygons contours_simplified (coord_t offset, bool fill_holes) const
std::vector< std::pair< ContourEdge, ContourEdge > > intersecting_edges () const
bool has_intersecting_edges () const
template<typename VISITOR>
void visit_cells_intersecting_line (Slic3r::Point p1, Slic3r::Point p2, VISITOR &visitor) const
template<typename VISITOR>
void visit_cells_intersecting_box (BoundingBox bbox, VISITOR &visitor) const
std::pair< std::vector< std::pair< size_t, size_t > >::const_iterator, std::vector< std::pair< size_t, size_t > >::const_iterator > cell_data_range (coord_t row, coord_t col) const
std::pair< const Slic3r::Point &, const Slic3r::Point & > segment (const std::pair< size_t, size_t > &contour_and_segment_idx) const
Line line (const std::pair< size_t, size_t > &contour_and_segment_idx) const

Protected Member Functions

void create_from_m_contours (coord_t resolution)
bool cell_inside_or_crossing (int r, int c) const

Protected Attributes

BoundingBox m_bbox
coord_t m_resolution
size_t m_rows = 0
size_t m_cols = 0
std::vector< Contour > m_contours
std::vector< std::pair< size_t, size_t > > m_cell_data
std::vector< Cell > m_cells
std::vector< float > m_signed_distance_field

Detailed Description

Member Typedef Documentation

◆ ContourEdge

typedef std::pair<const Contour*, size_t> Slic3r::EdgeGrid::Grid::ContourEdge

◆ ContourPoint

typedef std::pair<const Contour*, size_t> Slic3r::EdgeGrid::Grid::ContourPoint

Constructor & Destructor Documentation

◆ Grid() [1/2]

Slic3r::EdgeGrid::Grid::Grid ( )
default

◆ Grid() [2/2]

Slic3r::EdgeGrid::Grid::Grid ( const BoundingBox & bbox)
inline
107: m_bbox(bbox) {}
const BoundingBox & bbox() const
Definition EdgeGrid.hpp:171
BoundingBox m_bbox
Definition EdgeGrid.hpp:403

References bbox(), and m_bbox.

Here is the call graph for this function:

Member Function Documentation

◆ bbox()

const BoundingBox & Slic3r::EdgeGrid::Grid::bbox ( ) const
inline
171{ return m_bbox; }

References m_bbox.

Referenced by Grid(), Slic3r::any_expolygon_contains(), closest_point_signed_distance(), Slic3r::contour_distance(), Slic3r::FillLightning::Generator::generateTrees(), Slic3r::FillLightning::Generator::generateTreesforSupport(), set_bbox(), signed_distance_edges(), and visit_cells_intersecting_box().

Here is the caller graph for this function:

◆ calculate_sdf()

void Slic3r::EdgeGrid::Grid::calculate_sdf ( )
684{
685#ifdef EDGE_GRID_DEBUG_OUTPUT
686 static int iRun = 0;
687 ++ iRun;
688#endif
689
690 // 1) Initialize a signum and an unsigned vector to a zero iso surface.
691 size_t nrows = m_rows + 1;
692 size_t ncols = m_cols + 1;
693 // Unsigned vectors towards the closest point on the surface.
694 std::vector<float> L(nrows * ncols * 2, FLT_MAX);
695 // Bit 0 set - negative.
696 // Bit 1 set - original value, the distance value shall not be changed by the Danielsson propagation.
697 // Bit 2 set - signum not propagated yet.
698 std::vector<unsigned char> signs(nrows * ncols, 4);
699 // SDF will be initially filled with unsigned DF.
700// m_signed_distance_field.assign(nrows * ncols, FLT_MAX);
701 float search_radius = float(m_resolution<<1);
702 m_signed_distance_field.assign(nrows * ncols, search_radius);
703 // For each cell:
704 for (int r = 0; r < (int)m_rows; ++ r) {
705 for (int c = 0; c < (int)m_cols; ++ c) {
706 const Cell &cell = m_cells[r * m_cols + c];
707 // For each segment in the cell:
708 for (size_t i = cell.begin; i != cell.end; ++ i) {
709 const Contour &contour = m_contours[m_cell_data[i].first];
710 assert(contour.closed());
711 size_t ipt = m_cell_data[i].second;
712 // End points of the line segment.
713 const Slic3r::Point &p1 = contour.segment_start(ipt);
714 const Slic3r::Point &p2 = contour.segment_end(ipt);
715 // Segment vector
716 const Slic3r::Point v_seg = p2 - p1;
717 // l2 of v_seg
718 const int64_t l2_seg = int64_t(v_seg(0)) * int64_t(v_seg(0)) + int64_t(v_seg(1)) * int64_t(v_seg(1));
719 // For each corner of this cell and its 1 ring neighbours:
720 for (int corner_y = -1; corner_y < 3; ++ corner_y) {
721 coord_t corner_r = r + corner_y;
722 if (corner_r < 0 || (size_t)corner_r >= nrows)
723 continue;
724 for (int corner_x = -1; corner_x < 3; ++ corner_x) {
725 coord_t corner_c = c + corner_x;
726 if (corner_c < 0 || (size_t)corner_c >= ncols)
727 continue;
728 float &d_min = m_signed_distance_field[corner_r * ncols + corner_c];
729 Slic3r::Point pt(m_bbox.min(0) + corner_c * m_resolution, m_bbox.min(1) + corner_r * m_resolution);
730 Slic3r::Point v_pt = pt - p1;
731 // dot(p2-p1, pt-p1)
732 int64_t t_pt = int64_t(v_seg(0)) * int64_t(v_pt(0)) + int64_t(v_seg(1)) * int64_t(v_pt(1));
733 if (t_pt < 0) {
734 // Closest to p1.
735 double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1)));
736 if (dabs < d_min) {
737 // Previous point.
738 const Slic3r::Point &p0 = contour.segment_prev(ipt);
739 Slic3r::Point v_seg_prev = p1 - p0;
740 int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1));
741 if (t2_pt > 0) {
742 // Inside the wedge between the previous and the next segment.
743 // Set the signum depending on whether the vertex is convex or reflex.
744 int64_t det = int64_t(v_seg_prev(0)) * int64_t(v_seg(1)) - int64_t(v_seg_prev(1)) * int64_t(v_seg(0));
745 assert(det != 0);
746 d_min = dabs;
747 // Fill in an unsigned vector towards the zero iso surface.
748 float *l = &L[(corner_r * ncols + corner_c) << 1];
749 l[0] = std::abs(v_pt(0));
750 l[1] = std::abs(v_pt(1));
751 #ifdef _DEBUG
752 double dabs2 = sqrt(l[0]*l[0]+l[1]*l[1]);
753 assert(std::abs(dabs-dabs2) < 1e-4 * std::max(dabs, dabs2));
754 #endif /* _DEBUG */
755 signs[corner_r * ncols + corner_c] = ((det < 0) ? 1 : 0) | 2;
756 }
757 }
758 }
759 else if (t_pt > l2_seg) {
760 // Closest to p2. Then p2 is the starting point of another segment, which shall be discovered in the same cell.
761 continue;
762 } else {
763 // Closest to the segment.
764 assert(t_pt >= 0 && t_pt <= l2_seg);
765 int64_t d_seg = int64_t(v_seg(1)) * int64_t(v_pt(0)) - int64_t(v_seg(0)) * int64_t(v_pt(1));
766 double d = double(d_seg) / sqrt(double(l2_seg));
767 double dabs = std::abs(d);
768 if (dabs < d_min) {
769 d_min = dabs;
770 // Fill in an unsigned vector towards the zero iso surface.
771 float *l = &L[(corner_r * ncols + corner_c) << 1];
772 float linv = float(d_seg) / float(l2_seg);
773 l[0] = std::abs(float(v_seg(1)) * linv);
774 l[1] = std::abs(float(v_seg(0)) * linv);
775 #ifdef _DEBUG
776 double dabs2 = sqrt(l[0]*l[0]+l[1]*l[1]);
777 assert(std::abs(dabs-dabs2) <= 1e-4 * std::max(dabs, dabs2));
778 #endif /* _DEBUG */
779 signs[corner_r * ncols + corner_c] = ((d_seg < 0) ? 1 : 0) | 2;
780 }
781 }
782 }
783 }
784 }
785 }
786 }
787
788#ifdef EDGE_GRID_DEBUG_OUTPUT
789 {
790 std::vector<uint8_t> pixels(ncols * nrows * 3, 0);
791 for (coord_t r = 0; r < nrows; ++ r) {
792 for (coord_t c = 0; c < ncols; ++ c) {
793 uint8_t *pxl = pixels.data() + (((nrows - r - 1) * ncols) + c) * 3;
794 float d = m_signed_distance_field[r * ncols + c];
795 if (d != search_radius) {
796 float s = 255 * d / search_radius;
797 int is = std::max(0, std::min(255, int(floor(s + 0.5f))));
798 pxl[0] = 255;
799 pxl[1] = 255 - is;
800 pxl[2] = 255 - is;
801 }
802 else {
803 pxl[0] = 0;
804 pxl[1] = 255;
805 pxl[2] = 0;
806 }
807 }
808 }
809 png::write_rgb_to_file_scaled(debug_out_path("unsigned_df-%d.png", iRun), ncols, nrows, pixels, 10);
810 }
811 {
812 std::vector<uint8_t> pixels(ncols * nrows * 3, 0);
813 for (coord_t r = 0; r < nrows; ++ r) {
814 for (coord_t c = 0; c < ncols; ++ c) {
815 unsigned char *pxl = pixels.data() + (((nrows - r - 1) * ncols) + c) * 3;
816 float d = m_signed_distance_field[r * ncols + c];
817 if (d != search_radius) {
818 float s = 255 * d / search_radius;
819 int is = std::max(0, std::min(255, int(floor(s + 0.5f))));
820 if ((signs[r * ncols + c] & 1) == 0) {
821 // Positive
822 pxl[0] = 255;
823 pxl[1] = 255 - is;
824 pxl[2] = 255 - is;
825 }
826 else {
827 // Negative
828 pxl[0] = 255 - is;
829 pxl[1] = 255 - is;
830 pxl[2] = 255;
831 }
832 }
833 else {
834 pxl[0] = 0;
835 pxl[1] = 255;
836 pxl[2] = 0;
837 }
838 }
839 }
840 png::write_rgb_to_file_scaled(debug_out_path("signed_df-%d.png", iRun), ncols, nrows, pixels, 10);
841 }
842#endif // EDGE_GRID_DEBUG_OUTPUT
843
844 // 2) Propagate the signum.
845 #define PROPAGATE_SIGNUM_SINGLE_STEP(DELTA) do { \
846 size_t addr = r * ncols + c; \
847 unsigned char &cur_val = signs[addr]; \
848 if (cur_val & 4) { \
849 unsigned char old_val = signs[addr + (DELTA)]; \
850 if ((old_val & 4) == 0) \
851 cur_val = old_val & 1; \
852 } \
853 } while (0);
854 // Top to bottom propagation.
855 for (size_t r = 0; r < nrows; ++ r) {
856 if (r > 0)
857 for (size_t c = 0; c < ncols; ++ c)
858 PROPAGATE_SIGNUM_SINGLE_STEP(- int(ncols));
859 for (size_t c = 1; c < ncols; ++ c)
861 for (int c = int(ncols) - 2; c >= 0; -- c)
863 }
864 // Bottom to top propagation.
865 for (int r = int(nrows) - 2; r >= 0; -- r) {
866 for (size_t c = 0; c < ncols; ++ c)
868 for (size_t c = 1; c < ncols; ++ c)
870 for (int c = int(ncols) - 2; c >= 0; -- c)
872 }
873 #undef PROPAGATE_SIGNUM_SINGLE_STEP
874
875 // 3) Propagate the distance by the Danielsson chamfer metric.
876 // Top to bottom propagation.
877 PropagateDanielssonSingleStep<1, 0> danielsson_hstep(L.data(), signs.data(), ncols, m_resolution);
878 PropagateDanielssonSingleStep<0, 1> danielsson_vstep(L.data(), signs.data(), ncols, m_resolution);
879 PropagateDanielssonSingleVStep3 danielsson_vstep3(L.data(), signs.data(), ncols, m_resolution);
880 // Top to bottom propagation.
881 for (size_t r = 0; r < nrows; ++ r) {
882 if (r > 0)
883 for (size_t c = 0; c < ncols; ++ c)
884 danielsson_vstep(r, c, -int(ncols));
885// PROPAGATE_DANIELSSON_SINGLE_VSTEP3(-int(ncols), c != 0, c + 1 != ncols);
886 for (size_t c = 1; c < ncols; ++ c)
887 danielsson_hstep(r, c, -1);
888 for (int c = int(ncols) - 2; c >= 0; -- c)
889 danielsson_hstep(r, c, +1);
890 }
891 // Bottom to top propagation.
892 for (int r = int(nrows) - 2; r >= 0; -- r) {
893 for (size_t c = 0; c < ncols; ++ c)
894 danielsson_vstep(r, c, +ncols);
895// PROPAGATE_DANIELSSON_SINGLE_VSTEP3(+int(ncols), c != 0, c + 1 != ncols);
896 for (size_t c = 1; c < ncols; ++ c)
897 danielsson_hstep(r, c, -1);
898 for (int c = int(ncols) - 2; c >= 0; -- c)
899 danielsson_hstep(r, c, +1);
900 }
901
902 // Update signed distance field from absolte vectors to the iso-surface.
903 for (size_t r = 0; r < nrows; ++ r) {
904 for (size_t c = 0; c < ncols; ++ c) {
905 size_t addr = r * ncols + c;
906 float *v = &L[addr<<1];
907 float d = sqrt(v[0]*v[0]+v[1]*v[1]);
908 if (signs[addr] & 1)
909 d = -d;
910 m_signed_distance_field[addr] = d;
911 }
912 }
913
914#ifdef EDGE_GRID_DEBUG_OUTPUT
915 {
916 std::vector<uint8_t> pixels(ncols * nrows * 3, 0);
917 float search_radius = float(m_resolution * 5);
918 for (coord_t r = 0; r < nrows; ++r) {
919 for (coord_t c = 0; c < ncols; ++c) {
920 uint8_t *pxl = pixels.data() + (((nrows - r - 1) * ncols) + c) * 3;
921 uint8_t sign = signs[r * ncols + c];
922 switch (sign) {
923 case 0:
924 // Positive, outside of a narrow band.
925 pxl[0] = 0;
926 pxl[1] = 0;
927 pxl[2] = 255;
928 break;
929 case 1:
930 // Negative, outside of a narrow band.
931 pxl[0] = 255;
932 pxl[1] = 0;
933 pxl[2] = 0;
934 break;
935 case 2:
936 // Positive, outside of a narrow band.
937 pxl[0] = 100;
938 pxl[1] = 100;
939 pxl[2] = 255;
940 break;
941 case 3:
942 // Negative, outside of a narrow band.
943 pxl[0] = 255;
944 pxl[1] = 100;
945 pxl[2] = 100;
946 break;
947 case 4:
948 // This shall not happen. Undefined signum.
949 pxl[0] = 0;
950 pxl[1] = 255;
951 pxl[2] = 0;
952 break;
953 default:
954 // This shall not happen. Invalid signum value.
955 pxl[0] = 255;
956 pxl[1] = 255;
957 pxl[2] = 255;
958 break;
959 }
960 }
961 }
962 png::write_rgb_to_file_scaled(debug_out_path("signed_df-signs-%d.png", iRun), ncols, nrows, pixels, 10);
963 }
964#endif // EDGE_GRID_DEBUG_OUTPUT
965
966#ifdef EDGE_GRID_DEBUG_OUTPUT
967 {
968 std::vector<uint8_t> pixels(ncols * nrows * 3, 0);
969 float search_radius = float(m_resolution * 5);
970 for (coord_t r = 0; r < nrows; ++r) {
971 for (coord_t c = 0; c < ncols; ++c) {
972 uint8_t *pxl = pixels.data() + (((nrows - r - 1) * ncols) + c) * 3;
973 float d = m_signed_distance_field[r * ncols + c];
974 float s = 255.f * fabs(d) / search_radius;
975 int is = std::max(0, std::min(255, int(floor(s + 0.5f))));
976 if (d < 0.f) {
977 pxl[0] = 255;
978 pxl[1] = 255 - is;
979 pxl[2] = 255 - is;
980 }
981 else {
982 pxl[0] = 255 - is;
983 pxl[1] = 255 - is;
984 pxl[2] = 255;
985 }
986 }
987 }
988 png::write_rgb_to_file_scaled(debug_out_path("signed_df2-%d.png", iRun), ncols, nrows, pixels, 10);
989 }
990#endif // EDGE_GRID_DEBUG_OUTPUT
991}
#define PROPAGATE_SIGNUM_SINGLE_STEP(DELTA)
#define L(s)
Definition ExtrusionEntity.cpp:25
std::vector< std::pair< size_t, size_t > > m_cell_data
Definition EdgeGrid.hpp:415
std::vector< Cell > m_cells
Definition EdgeGrid.hpp:418
coord_t m_resolution
Definition EdgeGrid.hpp:405
std::vector< Contour > m_contours
Definition EdgeGrid.hpp:412
size_t m_rows
Definition EdgeGrid.hpp:406
std::vector< float > m_signed_distance_field
Definition EdgeGrid.hpp:422
size_t m_cols
Definition EdgeGrid.hpp:407
int64_t coord_t
Definition libslic3r.h:48
bool write_rgb_to_file_scaled(const char *file_name_utf8, size_t width, size_t height, const uint8_t *data_rgb, size_t scale)
Definition PNGReadWrite.cpp:384
std::string debug_out_path(const char *name,...)
Definition utils.cpp:382
const Polygon & contour(const ExPolygon &p)
Definition AGGRaster.hpp:30
Definition EdgeGrid.hpp:379

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::contour(), Slic3r::debug_out_path(), Slic3r::EdgeGrid::Grid::Cell::end, L, m_bbox, m_cell_data, m_cells, m_cols, m_contours, m_resolution, m_rows, m_signed_distance_field, PROPAGATE_SIGNUM_SINGLE_STEP, and Slic3r::png::write_rgb_to_file_scaled().

Here is the call graph for this function:

◆ cell_data_range()

std::pair< std::vector< std::pair< size_t, size_t > >::const_iterator, std::vector< std::pair< size_t, size_t > >::const_iterator > Slic3r::EdgeGrid::Grid::cell_data_range ( coord_t row,
coord_t col ) const
inline
357 {
358 assert(row >= 0 && size_t(row) < m_rows);
359 assert(col >= 0 && size_t(col) < m_cols);
360 const EdgeGrid::Grid::Cell &cell = m_cells[row * m_cols + col];
361 return std::make_pair(m_cell_data.begin() + cell.begin, m_cell_data.begin() + cell.end);
362 }

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::EdgeGrid::Grid::Cell::end, m_cell_data, m_cells, m_cols, and m_rows.

Referenced by Slic3r::contour_distance(), Slic3r::contour_distance(), Slic3r::contour_distance2(), and Slic3r::mark_boundary_segments_touching_infill().

Here is the caller graph for this function:

◆ cell_inside_or_crossing()

bool Slic3r::EdgeGrid::Grid::cell_inside_or_crossing ( int r,
int c ) const
inlineprotected
390 {
391 if (r < 0 || (size_t)r >= m_rows ||
392 c < 0 || (size_t)c >= m_cols)
393 // The cell is outside the domain. Hoping that the contours were correctly oriented, so
394 // there is a CCW outmost contour so the out of domain cells are outside.
395 return false;
396 const Cell &cell = m_cells[r * m_cols + c];
397 return
398 (cell.begin < cell.end) ||
399 (! m_signed_distance_field.empty() && m_signed_distance_field[r * (m_cols + 1) + c] <= 0.f);
400 }

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::EdgeGrid::Grid::Cell::end, m_cells, m_cols, m_rows, and m_signed_distance_field.

Referenced by contours_simplified().

Here is the caller graph for this function:

◆ closest_point_signed_distance()

EdgeGrid::Grid::ClosestPointResult Slic3r::EdgeGrid::Grid::closest_point_signed_distance ( const Point & pt,
coord_t search_radius ) const
1059{
1060 BoundingBox bbox;
1061 bbox.min = bbox.max = Point(pt(0) - m_bbox.min(0), pt(1) - m_bbox.min(1));
1062 bbox.defined = true;
1063 // Upper boundary, round to grid and test validity.
1064 bbox.max(0) += search_radius;
1065 bbox.max(1) += search_radius;
1066 ClosestPointResult result;
1067 if (bbox.max(0) < 0 || bbox.max(1) < 0)
1068 return result;
1069 bbox.max(0) /= m_resolution;
1070 bbox.max(1) /= m_resolution;
1071 if ((size_t)bbox.max(0) >= m_cols)
1072 bbox.max(0) = m_cols - 1;
1073 if ((size_t)bbox.max(1) >= m_rows)
1074 bbox.max(1) = m_rows - 1;
1075 // Lower boundary, round to grid and test validity.
1076 bbox.min(0) -= search_radius;
1077 bbox.min(1) -= search_radius;
1078 if (bbox.min(0) < 0)
1079 bbox.min(0) = 0;
1080 if (bbox.min(1) < 0)
1081 bbox.min(1) = 0;
1082 bbox.min(0) /= m_resolution;
1083 bbox.min(1) /= m_resolution;
1084 // Is the interval empty?
1085 if (bbox.min(0) > bbox.max(0) ||
1086 bbox.min(1) > bbox.max(1))
1087 return result;
1088 // Traverse all cells in the bounding box.
1089 double d_min = double(search_radius);
1090 // Signum of the distance field at pt.
1091 int sign_min = 0;
1092 double l2_seg_min = 1.;
1093 for (int r = bbox.min(1); r <= bbox.max(1); ++ r) {
1094 for (int c = bbox.min(0); c <= bbox.max(0); ++ c) {
1095 const Cell &cell = m_cells[r * m_cols + c];
1096 for (size_t i = cell.begin; i < cell.end; ++ i) {
1097 const size_t contour_idx = m_cell_data[i].first;
1098 const Contour &contour = m_contours[contour_idx];
1099 assert(contour.closed());
1100 size_t ipt = m_cell_data[i].second;
1101 // End points of the line segment.
1102 const Slic3r::Point &p1 = contour.segment_start(ipt);
1103 const Slic3r::Point &p2 = contour.segment_end(ipt);
1104 const Slic3r::Point v_seg = p2 - p1;
1105 const Slic3r::Point v_pt = pt - p1;
1106 // dot(p2-p1, pt-p1)
1107 int64_t t_pt = int64_t(v_seg(0)) * int64_t(v_pt(0)) + int64_t(v_seg(1)) * int64_t(v_pt(1));
1108 // l2 of seg
1109 int64_t l2_seg = int64_t(v_seg(0)) * int64_t(v_seg(0)) + int64_t(v_seg(1)) * int64_t(v_seg(1));
1110 if (t_pt < 0) {
1111 // Closest to p1.
1112 double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1)));
1113 if (dabs < d_min) {
1114 // Previous point.
1115 const Slic3r::Point &p0 = contour.segment_prev(ipt);
1116 Slic3r::Point v_seg_prev = p1 - p0;
1117 int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1));
1118 if (t2_pt > 0) {
1119 // Inside the wedge between the previous and the next segment.
1120 d_min = dabs;
1121 // Set the signum depending on whether the vertex is convex or reflex.
1122 int64_t det = int64_t(v_seg_prev(0)) * int64_t(v_seg(1)) - int64_t(v_seg_prev(1)) * int64_t(v_seg(0));
1123 assert(det != 0);
1124 sign_min = (det > 0) ? 1 : -1;
1125 result.contour_idx = contour_idx;
1126 result.start_point_idx = ipt;
1127 result.t = 0.;
1128#ifndef NDEBUG
1129 Vec2d vfoot = (p1 - pt).cast<double>();
1130 double dist_foot = vfoot.norm();
1131 double dist_foot_err = dist_foot - d_min;
1132 assert(std::abs(dist_foot_err) < 1e-7 * d_min);
1133#endif /* NDEBUG */
1134 }
1135 }
1136 }
1137 else if (t_pt > l2_seg) {
1138 // Closest to p2. Then p2 is the starting point of another segment, which shall be discovered in the same cell.
1139 continue;
1140 } else {
1141 // Closest to the segment.
1142 assert(t_pt >= 0 && t_pt <= l2_seg);
1143 int64_t d_seg = int64_t(v_seg(1)) * int64_t(v_pt(0)) - int64_t(v_seg(0)) * int64_t(v_pt(1));
1144 double d = double(d_seg) / sqrt(double(l2_seg));
1145 double dabs = std::abs(d);
1146 if (dabs < d_min) {
1147 d_min = dabs;
1148 sign_min = (d_seg < 0) ? -1 : ((d_seg == 0) ? 0 : 1);
1149 l2_seg_min = l2_seg;
1150 result.contour_idx = contour_idx;
1151 result.start_point_idx = ipt;
1152 result.t = t_pt;
1153#ifndef NDEBUG
1154 Vec2d foot = p1.cast<double>() * (1. - result.t / l2_seg_min) + p2.cast<double>() * (result.t / l2_seg_min);
1155 Vec2d vfoot = foot - pt.cast<double>();
1156 double dist_foot = vfoot.norm();
1157 double dist_foot_err = dist_foot - d_min;
1158 assert(std::abs(dist_foot_err) < 1e-7 || std::abs(dist_foot_err) < 1e-7 * d_min);
1159#endif /* NDEBUG */
1160 }
1161 }
1162 }
1163 }
1164 }
1165 if (result.contour_idx != size_t(-1) && d_min <= double(search_radius)) {
1166 result.distance = d_min * sign_min;
1167 result.t /= l2_seg_min;
1168 assert(result.t >= 0. && result.t <= 1.);
1169#ifndef NDEBUG
1170 {
1171 const Contour &contour = m_contours[result.contour_idx];
1172 const Slic3r::Point &p1 = contour.segment_start(result.start_point_idx);
1173 const Slic3r::Point &p2 = contour.segment_end(result.start_point_idx);
1174 Vec2d vfoot;
1175 if (result.t == 0)
1176 vfoot = p1.cast<double>() - pt.cast<double>();
1177 else
1178 vfoot = p1.cast<double>() * (1. - result.t) + p2.cast<double>() * result.t - pt.cast<double>();
1179 double dist_foot = vfoot.norm();
1180 double dist_foot_err = dist_foot - std::abs(result.distance);
1181 assert(std::abs(dist_foot_err) < 1e-7 || std::abs(dist_foot_err) < 1e-7 * std::abs(result.distance));
1182 }
1183#endif /* NDEBUG */
1184 } else
1185 result = ClosestPointResult();
1186 return result;
1187}
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References bbox(), Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::cast(), Slic3r::contour(), Slic3r::EdgeGrid::Grid::ClosestPointResult::contour_idx, Slic3r::EdgeGrid::Grid::ClosestPointResult::distance, Slic3r::EdgeGrid::Grid::Cell::end, m_bbox, m_cell_data, m_cells, m_cols, m_contours, m_resolution, m_rows, Slic3r::EdgeGrid::Grid::ClosestPointResult::start_point_idx, and Slic3r::EdgeGrid::Grid::ClosestPointResult::t.

Here is the call graph for this function:

◆ cols()

const size_t Slic3r::EdgeGrid::Grid::cols ( ) const
inline
174{ return m_cols; }

References m_cols.

Referenced by create_from_m_contours().

Here is the caller graph for this function:

◆ contours()

const std::vector< Contour > & Slic3r::EdgeGrid::Grid::contours ( ) const
inline
127{ return m_contours; }

References m_contours.

◆ contours_simplified()

Polygons Slic3r::EdgeGrid::Grid::contours_simplified ( coord_t offset,
bool fill_holes ) const
1295{
1296 assert(std::abs(2 * offset) < m_resolution);
1297
1298 typedef std::unordered_multimap<Point, int, PointHash> EndPointMapType;
1299 // 0) Prepare a binary grid.
1300 size_t cell_rows = m_rows + 2;
1301 size_t cell_cols = m_cols + 2;
1302 std::vector<char> cell_inside(cell_rows * cell_cols, false);
1303 for (int r = 0; r < int(cell_rows); ++ r)
1304 for (int c = 0; c < int(cell_cols); ++ c)
1305 cell_inside[r * cell_cols + c] = cell_inside_or_crossing(r - 1, c - 1);
1306 // Fill in empty cells, which have a left / right neighbor filled.
1307 // Fill in empty cells, which have the top / bottom neighbor filled.
1308 if (fill_holes) {
1309 std::vector<char> cell_inside2(cell_inside);
1310 for (int r = 1; r + 1 < int(cell_rows); ++ r) {
1311 for (int c = 1; c + 1 < int(cell_cols); ++ c) {
1312 int addr = r * cell_cols + c;
1313 if ((cell_inside2[addr - 1] && cell_inside2[addr + 1]) ||
1314 (cell_inside2[addr - cell_cols] && cell_inside2[addr + cell_cols]))
1315 cell_inside[addr] = true;
1316 }
1317 }
1318 }
1319
1320 // 1) Collect the lines.
1321 std::vector<Line> lines;
1322 EndPointMapType start_point_to_line_idx;
1323 for (coord_t r = 0; r <= coord_t(m_rows); ++ r) {
1324 for (coord_t c = 0; c <= coord_t(m_cols); ++ c) {
1325 size_t addr = (r + 1) * cell_cols + c + 1;
1326 bool left = cell_inside[addr - 1];
1327 bool top = cell_inside[addr - cell_cols];
1328 bool current = cell_inside[addr];
1329 if (left != current) {
1330 lines.push_back(
1331 left ?
1332 Line(Point(c, r+1), Point(c, r )) :
1333 Line(Point(c, r ), Point(c, r+1)));
1334 start_point_to_line_idx.insert(std::pair<Point, int>(lines.back().a, int(lines.size()) - 1));
1335 }
1336 if (top != current) {
1337 lines.push_back(
1338 top ?
1339 Line(Point(c , r), Point(c+1, r)) :
1340 Line(Point(c+1, r), Point(c , r)));
1341 start_point_to_line_idx.insert(std::pair<Point, int>(lines.back().a, int(lines.size()) - 1));
1342 }
1343 }
1344 }
1345
1346 // 2) Chain the lines.
1347 std::vector<char> line_processed(lines.size(), false);
1348 Polygons out;
1349 for (int i_candidate = 0; i_candidate < int(lines.size()); ++ i_candidate) {
1350 if (line_processed[i_candidate])
1351 continue;
1352 Polygon poly;
1353 line_processed[i_candidate] = true;
1354 poly.points.push_back(lines[i_candidate].b);
1355 int i_line_current = i_candidate;
1356 for (;;) {
1357 std::pair<EndPointMapType::iterator,EndPointMapType::iterator> line_range =
1358 start_point_to_line_idx.equal_range(lines[i_line_current].b);
1359 // The interval has to be non empty, there shall be at least one line continuing the current one.
1360 assert(line_range.first != line_range.second);
1361 int i_next = -1;
1362 for (EndPointMapType::iterator it = line_range.first; it != line_range.second; ++ it) {
1363 if (it->second == i_candidate) {
1364 // closing the loop.
1365 goto end_of_poly;
1366 }
1367 if (line_processed[it->second])
1368 continue;
1369 if (i_next == -1) {
1370 i_next = it->second;
1371 } else {
1372 // This is a corner, where two lines meet exactly. Pick the line, which encloses a smallest angle with
1373 // the current edge.
1374 const Line &line_current = lines[i_line_current];
1375 const Line &line_next = lines[it->second];
1376 const Vector v1 = line_current.vector();
1377 const Vector v2 = line_next.vector();
1378 int64_t cross = int64_t(v1(0)) * int64_t(v2(1)) - int64_t(v2(0)) * int64_t(v1(1));
1379 if (cross > 0) {
1380 // This has to be a convex right angle. There is no better next line.
1381 i_next = it->second;
1382 break;
1383 }
1384 }
1385 }
1386 line_processed[i_next] = true;
1387 i_line_current = i_next;
1388 poly.points.push_back(lines[i_line_current].b);
1389 }
1390 end_of_poly:
1391 out.push_back(std::move(poly));
1392 }
1393
1394 // 3) Scale the polygons back into world, shrink slightly and remove collinear points.
1395 for (size_t i = 0; i < out.size(); ++ i) {
1396 Polygon &poly = out[i];
1397 for (size_t j = 0; j < poly.points.size(); ++ j) {
1398 Point &p = poly.points[j];
1399 p(0) *= m_resolution;
1400 p(1) *= m_resolution;
1401 p(0) += m_bbox.min(0);
1402 p(1) += m_bbox.min(1);
1403 }
1404 // Shrink the contour slightly, so if the same contour gets discretized and simplified again, one will get the same result.
1405 // Remove collineaer points.
1406 Points pts;
1407 pts.reserve(poly.points.size());
1408 for (size_t j = 0; j < poly.points.size(); ++ j) {
1409 size_t j0 = (j == 0) ? poly.points.size() - 1 : j - 1;
1410 size_t j2 = (j + 1 == poly.points.size()) ? 0 : j + 1;
1411 Point v = poly.points[j2] - poly.points[j0];
1412 if (v(0) != 0 && v(1) != 0) {
1413 // This is a corner point. Copy it to the output contour.
1414 Point p = poly.points[j];
1415 p(1) += (v(0) < 0) ? - offset : offset;
1416 p(0) += (v(1) > 0) ? - offset : offset;
1417 pts.push_back(p);
1418 }
1419 }
1420 poly.points = std::move(pts);
1421 }
1422 return out;
1423}
bool cell_inside_or_crossing(int r, int c) const
Definition EdgeGrid.hpp:389
void poly(std::vector< std::pair< Vec2d, Vec2d > > &out, std::initializer_list< Vec2d > p)
Definition DesignSketchTool.cpp:7751
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
Point Vector
Definition Point.hpp:42
T cross(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:168
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
Slic3r::Polygon Polygon
Definition Emboss.cpp:101
@ left
Definition MarchingSquares.hpp:188

References cell_inside_or_crossing(), Slic3r::cross(), m_bbox, m_cols, m_resolution, m_rows, Slic3r::offset(), and Slic3r::Line::vector().

Here is the call graph for this function:

◆ create() [1/7]

void Slic3r::EdgeGrid::Grid::create ( const ExPolygon & expoly,
coord_t resolution )
116{
117 m_contours.clear();
118 m_contours.reserve((expoly.contour.empty() ? 0 : 1) + std::count_if(expoly.holes.begin(), expoly.holes.end(), [](const Polygon &p) { return ! p.empty(); }));
119 if (! expoly.contour.empty())
120 m_contours.emplace_back(expoly.contour.points, false);
121 for (const Polygon &hole : expoly.holes)
122 if (! hole.empty())
123 m_contours.emplace_back(hole.points, false);
124
126}
void create_from_m_contours(coord_t resolution)
Definition EdgeGrid.cpp:153
const coord_t resolution() const
Definition EdgeGrid.hpp:172

References Slic3r::ExPolygon::contour, create_from_m_contours(), Slic3r::MultiPoint::empty(), Slic3r::ExPolygon::holes, m_contours, Slic3r::MultiPoint::points, and resolution().

Here is the call graph for this function:

◆ create() [2/7]

void Slic3r::EdgeGrid::Grid::create ( const ExPolygons & expolygons,
coord_t resolution )
129{
130 // Count the contours.
131 size_t ncontours = 0;
132 for (const ExPolygon &expoly : expolygons) {
133 if (! expoly.contour.empty())
134 ++ ncontours;
135 ncontours += std::count_if(expoly.holes.begin(), expoly.holes.end(), [](const Polygon &p) { return ! p.empty(); });
136 }
137
138 // Collect the contours.
139 m_contours.clear();
140 m_contours.reserve(ncontours);
141 for (const ExPolygon &expoly : expolygons) {
142 if (! expoly.contour.empty())
143 m_contours.emplace_back(expoly.contour.points, false);
144 for (const Polygon &hole : expoly.holes)
145 if (! hole.empty())
146 m_contours.emplace_back(hole.points, false);
147 }
148
150}

References create_from_m_contours(), Slic3r::MultiPoint::empty(), m_contours, Slic3r::MultiPoint::points, and resolution().

Here is the call graph for this function:

◆ create() [3/7]

void Slic3r::EdgeGrid::Grid::create ( const Polygons & polygons,
const Polylines & polylines,
coord_t resolution )
89{
90 // Collect the contours.
91 m_contours.clear();
92 m_contours.reserve(
93 std::count_if(polygons.begin(), polygons.end(), [](const Polygon &p) { return p.size() > 1; }) +
94 std::count_if(polylines.begin(), polylines.end(), [](const Polyline &p) { return p.size() > 1; }));
95
96 for (const Polyline &polyline : polylines)
97 if (polyline.size() > 1) {
98 const Point *begin = polyline.points.data();
99 const Point *end = polyline.points.data() + polyline.size();
100 bool open = true;
101 if (*begin == end[-1]) {
102 open = false;
103 -- end;
104 }
105 m_contours.emplace_back(begin, end, open);
106 }
107
108 for (const Polygon &polygon : polygons)
109 if (polygon.size() > 1)
110 m_contours.emplace_back(polygon.points, false);
111
113}
T * begin(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:838
T * end(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:841

References create_from_m_contours(), m_contours, and resolution().

Here is the call graph for this function:

◆ create() [4/7]

void Slic3r::EdgeGrid::Grid::create ( const Polygons & polygons,
coord_t resolution )
40{
41 // Collect the contours.
42 m_contours.clear();
43 m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Polygon &p) { return ! p.empty(); }));
44 for (const Polygon &polygon : polygons)
45 if (! polygon.empty())
46 m_contours.emplace_back(polygon.points, false);
47
49}

References create_from_m_contours(), m_contours, and resolution().

Here is the call graph for this function:

◆ create() [5/7]

void Slic3r::EdgeGrid::Grid::create ( const std::vector< const Polygon * > & polygons,
coord_t resolution )
52{
53 // Collect the contours.
54 m_contours.clear();
55 m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Polygon *p) { return ! p->empty(); }));
56 for (const Polygon *polygon : polygons)
57 if (! polygon->empty())
58 m_contours.emplace_back(polygon->points, false);
59
61}

References create_from_m_contours(), m_contours, and resolution().

Here is the call graph for this function:

◆ create() [6/7]

void Slic3r::EdgeGrid::Grid::create ( const std::vector< Points > & polygons,
coord_t resolution )
inline
123{ this->create(polygons, resolution, false); }
void create(const std::vector< Points > &polylines_or_polygons, coord_t resolution, bool open)
Definition EdgeGrid.cpp:63

References create(), and resolution().

Referenced by create().

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

◆ create() [7/7]

void Slic3r::EdgeGrid::Grid::create ( const std::vector< Points > & polylines_or_polygons,
coord_t resolution,
bool open )
64{
65 // Collect the contours.
66 m_contours.clear();
67 m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Points &p) { return p.size() > 1; }));
68 for (const Points &points : polygons)
69 if (points.size() > 1) {
70 const Point *begin = points.data();
71 const Point *end = points.data() + points.size();
72 bool open = open_polylines;
73 if (open_polylines) {
74 if (*begin == end[-1]) {
75 open = false;
76 -- end;
77 }
78 } else {
79 //assert(*begin != end[-1]);
80 }
81
82 m_contours.emplace_back(begin, end, open);
83 }
84
86}

References create_from_m_contours(), m_contours, and resolution().

Referenced by Slic3r::FillLightning::Generator::generateTrees(), Slic3r::FillLightning::Generator::generateTreesforSupport(), Slic3r::init_boundary(), and Slic3r::init_boundary().

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

◆ create_from_m_contours()

void Slic3r::EdgeGrid::Grid::create_from_m_contours ( coord_t resolution)
protected
154{
155 assert(resolution > 0);
156 // 1) Measure the bounding box.
157 for (const Contour &contour : m_contours) {
158 //assert(contour.num_segments() > 0);
159 //assert(*contour.begin() != contour.end()[-1]);
160 for (const Slic3r::Point &pt : contour)
161 m_bbox.merge(pt);
162 }
163
164 coord_t eps = 16;
165 m_bbox.min(0) -= eps;
166 m_bbox.min(1) -= eps;
167 m_bbox.max(0) += eps;
168 m_bbox.max(1) += eps;
169
170 // 2) Initialize the edge grid.
172 m_cols = (m_bbox.max(0) - m_bbox.min(0) + m_resolution - 1) / m_resolution;
173 m_rows = (m_bbox.max(1) - m_bbox.min(1) + m_resolution - 1) / m_resolution;
174 m_cells.assign(m_rows * m_cols, Cell());
175
176 // 3) First round of contour rasterization, count the edges per grid cell.
177 for (size_t i = 0; i < m_contours.size(); ++ i) {
178 const Contour &contour = m_contours[i];
179 for (size_t j = 0; j < contour.num_segments(); ++ j) {
180 // End points of the line segment.
181 Slic3r::Point p1(contour.segment_start(j));
182 Slic3r::Point p2(contour.segment_end(j));
183 p1(0) -= m_bbox.min(0);
184 p1(1) -= m_bbox.min(1);
185 p2(0) -= m_bbox.min(0);
186 p2(1) -= m_bbox.min(1);
187 // Get the cells of the end points.
188 coord_t ix = p1(0) / m_resolution;
189 coord_t iy = p1(1) / m_resolution;
190 coord_t ixb = p2(0) / m_resolution;
191 coord_t iyb = p2(1) / m_resolution;
192 assert(ix >= 0 && size_t(ix) < m_cols);
193 assert(iy >= 0 && size_t(iy) < m_rows);
194 assert(ixb >= 0 && size_t(ixb) < m_cols);
195 assert(iyb >= 0 && size_t(iyb) < m_rows);
196 // Account for the end points.
197 ++ m_cells[iy*m_cols+ix].end;
198 if (ix == ixb && iy == iyb)
199 // Both ends fall into the same cell.
200 continue;
201 // Raster the centeral part of the line.
202 coord_t dx = std::abs(p2(0) - p1(0));
203 coord_t dy = std::abs(p2(1) - p1(1));
204 if (p1(0) < p2(0)) {
205 int64_t ex = int64_t((ix + 1)*m_resolution - p1(0)) * int64_t(dy);
206 if (p1(1) < p2(1)) {
207 // x positive, y positive
208 int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
209 do {
210 assert(ix <= ixb && iy <= iyb);
211 if (ex < ey) {
212 ey -= ex;
213 ex = int64_t(dy) * m_resolution;
214 ix += 1;
215 }
216 else if (ex == ey) {
217 ex = int64_t(dy) * m_resolution;
218 ey = int64_t(dx) * m_resolution;
219 ix += 1;
220 iy += 1;
221 }
222 else {
223 assert(ex > ey);
224 ex -= ey;
225 ey = int64_t(dx) * m_resolution;
226 iy += 1;
227 }
228 ++m_cells[iy*m_cols + ix].end;
229 } while (ix != ixb || iy != iyb);
230 }
231 else {
232 // x positive, y non positive
233 int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
234 do {
235 assert(ix <= ixb && iy >= iyb);
236 if (ex <= ey) {
237 ey -= ex;
238 ex = int64_t(dy) * m_resolution;
239 ix += 1;
240 }
241 else {
242 ex -= ey;
243 ey = int64_t(dx) * m_resolution;
244 iy -= 1;
245 }
246 ++m_cells[iy*m_cols + ix].end;
247 } while (ix != ixb || iy != iyb);
248 }
249 }
250 else {
251 int64_t ex = int64_t(p1(0) - ix*m_resolution) * int64_t(dy);
252 if (p1(1) < p2(1)) {
253 // x non positive, y positive
254 int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
255 do {
256 assert(ix >= ixb && iy <= iyb);
257 if (ex < ey) {
258 ey -= ex;
259 ex = int64_t(dy) * m_resolution;
260 ix -= 1;
261 }
262 else {
263 assert(ex >= ey);
264 ex -= ey;
265 ey = int64_t(dx) * m_resolution;
266 iy += 1;
267 }
268 ++m_cells[iy*m_cols + ix].end;
269 } while (ix != ixb || iy != iyb);
270 }
271 else {
272 // x non positive, y non positive
273 int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
274 do {
275 assert(ix >= ixb && iy >= iyb);
276 if (ex < ey) {
277 ey -= ex;
278 ex = int64_t(dy) * m_resolution;
279 ix -= 1;
280 }
281 else if (ex == ey) {
282 // The lower edge of a grid cell belongs to the cell.
283 // Handle the case where the ray may cross the lower left corner of a cell in a general case,
284 // or a left or lower edge in a degenerate case (horizontal or vertical line).
285 if (dx > 0) {
286 ex = int64_t(dy) * m_resolution;
287 ix -= 1;
288 }
289 if (dy > 0) {
290 ey = int64_t(dx) * m_resolution;
291 iy -= 1;
292 }
293 }
294 else {
295 assert(ex > ey);
296 ex -= ey;
297 ey = int64_t(dx) * m_resolution;
298 iy -= 1;
299 }
300 ++m_cells[iy*m_cols + ix].end;
301 } while (ix != ixb || iy != iyb);
302 }
303 }
304 }
305 }
306
307 // 4) Prefix sum the numbers of hits per cells to get an index into m_cell_data.
308 size_t cnt = m_cells.front().end;
309 for (size_t i = 1; i < m_cells.size(); ++ i) {
310 m_cells[i].begin = cnt;
311 cnt += m_cells[i].end;
312 m_cells[i].end = cnt;
313 }
314
315 // 5) Allocate the cell data.
316 m_cell_data.assign(cnt, std::pair<size_t, size_t>(size_t(-1), size_t(-1)));
317
318 // 6) Finally fill in m_cell_data by rasterizing the lines once again.
319 for (size_t i = 0; i < m_cells.size(); ++i)
320 m_cells[i].end = m_cells[i].begin;
321
322 struct Visitor {
323 Visitor(std::vector<std::pair<size_t, size_t>> &cell_data, std::vector<Cell> &cells, size_t cols) :
324 cell_data(cell_data), cells(cells), cols(cols), i(0), j(0) {}
325
326 inline bool operator()(coord_t iy, coord_t ix) {
327 cell_data[cells[iy*cols + ix].end++] = std::pair<size_t, size_t>(i, j);
328 // Continue traversing the grid along the edge.
329 return true;
330 }
331
332 std::vector<std::pair<size_t, size_t>> &cell_data;
333 std::vector<Cell> &cells;
334 size_t cols;
335 size_t i;
336 size_t j;
337 } visitor(m_cell_data, m_cells, m_cols);
338
339 assert(visitor.i == 0);
340 for (; visitor.i < m_contours.size(); ++ visitor.i) {
341 const Contour &contour = m_contours[visitor.i];
342 for (visitor.j = 0; visitor.j < contour.num_segments(); ++ visitor.j)
343 this->visit_cells_intersecting_line(contour.segment_start(visitor.j), contour.segment_end(visitor.j), visitor);
344 }
345}
void visit_cells_intersecting_line(Slic3r::Point p1, Slic3r::Point p2, VISITOR &visitor) const
Definition EdgeGrid.hpp:184
size_t cols(const T &raster)
Definition MarchingSquares.hpp:173

References cols(), Slic3r::contour(), m_bbox, m_cell_data, m_cells, m_cols, m_contours, m_resolution, m_rows, resolution(), and visit_cells_intersecting_line().

Referenced by create(), create(), create(), create(), create(), and create().

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

◆ has_intersecting_edges()

bool Slic3r::EdgeGrid::Grid::has_intersecting_edges ( ) const
1464{
1465 // For each cell:
1466 for (int r = 0; r < (int)m_rows; ++ r) {
1467 for (int c = 0; c < (int)m_cols; ++ c) {
1468 const Cell &cell = m_cells[r * m_cols + c];
1469 // For each pair of segments in the cell:
1470 for (size_t i = cell.begin; i != cell.end; ++ i) {
1471 const Contour &icontour = m_contours[m_cell_data[i].first];
1472 size_t ipt = m_cell_data[i].second;
1473 // End points of the line segment and their vector.
1474 const Slic3r::Point &ip1 = icontour.segment_start(ipt);
1475 const Slic3r::Point &ip2 = icontour.segment_end(ipt);
1476 for (size_t j = i + 1; j != cell.end; ++ j) {
1477 const Contour &jcontour = m_contours[m_cell_data[j].first];
1478 size_t jpt = m_cell_data[j].second;
1479 // End points of the line segment and their vector.
1480 const Slic3r::Point &jp1 = jcontour.segment_start(jpt);
1481 const Slic3r::Point &jp2 = jcontour.segment_end(jpt);
1482 if (! (&icontour == &jcontour && (&ip1 == &jp2 || &jp1 == &ip2)) &&
1483 Geometry::segments_intersect(ip1, ip2, jp1, jp2))
1484 return true;
1485 }
1486 }
1487 }
1488 }
1489 return false;
1490}
bool segments_intersect(const Slic3r::Point &ip1, const Slic3r::Point &ip2, const Slic3r::Point &jp1, const Slic3r::Point &jp2)
Definition Geometry.hpp:134

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::EdgeGrid::Grid::Cell::end, m_cell_data, m_cells, m_cols, m_contours, m_rows, Slic3r::EdgeGrid::Contour::segment_end(), Slic3r::EdgeGrid::Contour::segment_start(), and Slic3r::Geometry::segments_intersect().

Here is the call graph for this function:

◆ intersecting_edges()

std::vector< std::pair< EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge > > Slic3r::EdgeGrid::Grid::intersecting_edges ( ) const
1426{
1427 std::vector<std::pair<ContourEdge, ContourEdge>> out;
1428 // For each cell:
1429 for (int r = 0; r < (int)m_rows; ++ r) {
1430 for (int c = 0; c < (int)m_cols; ++ c) {
1431 const Cell &cell = m_cells[r * m_cols + c];
1432 // For each pair of segments in the cell:
1433 for (size_t i = cell.begin; i != cell.end; ++ i) {
1434 const Contour &icontour = m_contours[m_cell_data[i].first];
1435 size_t ipt = m_cell_data[i].second;
1436 // End points of the line segment and their vector.
1437 const Slic3r::Point &ip1 = icontour.segment_start(ipt);
1438 const Slic3r::Point &ip2 = icontour.segment_end(ipt);
1439 for (size_t j = i + 1; j != cell.end; ++ j) {
1440 const Contour &jcontour = m_contours[m_cell_data[j].first];
1441 size_t jpt = m_cell_data[j].second;
1442 // End points of the line segment and their vector.
1443 const Slic3r::Point &jp1 = jcontour.segment_start(jpt);
1444 const Slic3r::Point &jp2 = jcontour.segment_end(jpt);
1445 if (&icontour == &jcontour && (&ip1 == &jp2 || &jp1 == &ip2))
1446 // Segments of the same contour share a common vertex.
1447 continue;
1448 if (Geometry::segments_intersect(ip1, ip2, jp1, jp2)) {
1449 // The two segments intersect. Add them to the output.
1450 int jfirst = (&jcontour < &icontour) || (&jcontour == &icontour && jpt < ipt);
1451 out.emplace_back(jfirst ?
1452 std::make_pair(std::make_pair(&icontour, ipt), std::make_pair(&jcontour, jpt)) :
1453 std::make_pair(std::make_pair(&icontour, ipt), std::make_pair(&jcontour, jpt)));
1454 }
1455 }
1456 }
1457 }
1458 }
1460 return out;
1461}
void sort_remove_duplicates(std::vector< T > &vec)
Definition libslic3r.h:231

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::EdgeGrid::Grid::Cell::end, m_cell_data, m_cells, m_cols, m_contours, m_rows, Slic3r::EdgeGrid::Contour::segment_end(), Slic3r::EdgeGrid::Contour::segment_start(), Slic3r::Geometry::segments_intersect(), and Slic3r::sort_remove_duplicates().

Here is the call graph for this function:

◆ line()

Line Slic3r::EdgeGrid::Grid::line ( const std::pair< size_t, size_t > & contour_and_segment_idx) const
inline
372 {
373 const Contour &contour = m_contours[contour_and_segment_idx.first];
374 size_t iseg = contour_and_segment_idx.second;
375 return Line(contour.segment_start(iseg), contour.segment_end(iseg));
376 }

References Slic3r::contour(), and m_contours.

Here is the call graph for this function:

◆ resolution()

const coord_t Slic3r::EdgeGrid::Grid::resolution ( ) const
inline
172{ return m_resolution; }

References m_resolution.

Referenced by create(), create(), create(), create(), create(), create(), create(), create_from_m_contours(), and Slic3r::FillLightning::Layer::reconnectRoots().

Here is the caller graph for this function:

◆ rows()

const size_t Slic3r::EdgeGrid::Grid::rows ( ) const
inline
173{ return m_rows; }

References m_rows.

◆ segment()

std::pair< const Slic3r::Point &, const Slic3r::Point & > Slic3r::EdgeGrid::Grid::segment ( const std::pair< size_t, size_t > & contour_and_segment_idx) const
inline
365 {
366 const Contour &contour = m_contours[contour_and_segment_idx.first];
367 size_t iseg = contour_and_segment_idx.second;
368 return std::pair<const Slic3r::Point&, const Slic3r::Point&>(contour.segment_start(iseg), contour.segment_end(iseg));
369 }

References Slic3r::contour(), and m_contours.

Referenced by Slic3r::contour_distance(), Slic3r::contour_distance(), Slic3r::contour_distance2(), and Slic3r::mark_boundary_segments_touching_infill().

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

◆ set_bbox()

void Slic3r::EdgeGrid::Grid::set_bbox ( const BoundingBox & bbox)
inline
109{ m_bbox = bbox; }

References bbox(), and m_bbox.

Referenced by Slic3r::FillLightning::Generator::generateTrees(), Slic3r::FillLightning::Generator::generateTreesforSupport(), Slic3r::init_boundary(), and Slic3r::init_boundary().

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

◆ signed_distance()

bool Slic3r::EdgeGrid::Grid::signed_distance ( const Point & pt,
coord_t search_radius,
coordf_t & result_min_dist ) const
1285{
1286 if (signed_distance_edges(pt, search_radius, result_min_dist))
1287 return true;
1288 if (m_signed_distance_field.empty())
1289 return false;
1290 result_min_dist = signed_distance_bilinear(pt);
1291 return true;
1292}
float signed_distance_bilinear(const Point &pt) const
Definition EdgeGrid.cpp:993
bool signed_distance_edges(const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment=nullptr) const
Definition EdgeGrid.cpp:1189

References m_signed_distance_field, signed_distance_bilinear(), and signed_distance_edges().

Here is the call graph for this function:

◆ signed_distance_bilinear()

float Slic3r::EdgeGrid::Grid::signed_distance_bilinear ( const Point & pt) const
994{
995 coord_t x = pt(0) - m_bbox.min(0);
996 coord_t y = pt(1) - m_bbox.min(1);
999 bool clamped = false;
1000 coord_t xcl = x;
1001 coord_t ycl = y;
1002 if (x < 0) {
1003 xcl = 0;
1004 clamped = true;
1005 } else if (x >= w) {
1006 xcl = w - 1;
1007 clamped = true;
1008 }
1009 if (y < 0) {
1010 ycl = 0;
1011 clamped = true;
1012 } else if (y >= h) {
1013 ycl = h - 1;
1014 clamped = true;
1015 }
1016
1017 coord_t cell_c = coord_t(floor(xcl / m_resolution));
1018 coord_t cell_r = coord_t(floor(ycl / m_resolution));
1019 float tx = float(xcl - cell_c * m_resolution) / float(m_resolution);
1020 assert(tx >= -1e-5 && tx < 1.f + 1e-5);
1021 float ty = float(ycl - cell_r * m_resolution) / float(m_resolution);
1022 assert(ty >= -1e-5 && ty < 1.f + 1e-5);
1023 size_t addr = cell_r * (m_cols + 1) + cell_c;
1024 float f00 = m_signed_distance_field[addr];
1025 float f01 = m_signed_distance_field[addr+1];
1026 addr += m_cols + 1;
1027 float f10 = m_signed_distance_field[addr];
1028 float f11 = m_signed_distance_field[addr+1];
1029 float f0 = (1.f - tx) * f00 + tx * f01;
1030 float f1 = (1.f - tx) * f10 + tx * f11;
1031 float f = (1.f - ty) * f0 + ty * f1;
1032
1033 if (clamped) {
1034 if (f > 0) {
1035 if (x < 0)
1036 f += -x;
1037 else if (x >= w)
1038 f += x - w + 1;
1039 if (y < 0)
1040 f += -y;
1041 else if (y >= h)
1042 f += y - h + 1;
1043 } else {
1044 if (x < 0)
1045 f -= -x;
1046 else if (x >= w)
1047 f -= x - w + 1;
1048 if (y < 0)
1049 f -= -y;
1050 else if (y >= h)
1051 f -= y - h + 1;
1052 }
1053 }
1054
1055 return f;
1056}
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:124

References Slic3r::f(), m_bbox, m_cols, m_resolution, m_rows, and m_signed_distance_field.

Referenced by signed_distance().

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

◆ signed_distance_edges()

bool Slic3r::EdgeGrid::Grid::signed_distance_edges ( const Point & pt,
coord_t search_radius,
coordf_t & result_min_dist,
bool * pon_segment = nullptr ) const
1190{
1191 BoundingBox bbox;
1192 bbox.min = bbox.max = Point(pt(0) - m_bbox.min(0), pt(1) - m_bbox.min(1));
1193 bbox.defined = true;
1194 // Upper boundary, round to grid and test validity.
1195 bbox.max(0) += search_radius;
1196 bbox.max(1) += search_radius;
1197 if (bbox.max(0) < 0 || bbox.max(1) < 0)
1198 return false;
1199 bbox.max(0) /= m_resolution;
1200 bbox.max(1) /= m_resolution;
1201 if ((size_t)bbox.max(0) >= m_cols)
1202 bbox.max(0) = m_cols - 1;
1203 if ((size_t)bbox.max(1) >= m_rows)
1204 bbox.max(1) = m_rows - 1;
1205 // Lower boundary, round to grid and test validity.
1206 bbox.min(0) -= search_radius;
1207 bbox.min(1) -= search_radius;
1208 if (bbox.min(0) < 0)
1209 bbox.min(0) = 0;
1210 if (bbox.min(1) < 0)
1211 bbox.min(1) = 0;
1212 bbox.min(0) /= m_resolution;
1213 bbox.min(1) /= m_resolution;
1214 // Is the interval empty?
1215 if (bbox.min(0) > bbox.max(0) ||
1216 bbox.min(1) > bbox.max(1))
1217 return false;
1218 // Traverse all cells in the bounding box.
1219 double d_min = double(search_radius);
1220 // Signum of the distance field at pt.
1221 int sign_min = 0;
1222 bool on_segment = false;
1223 for (int r = bbox.min(1); r <= bbox.max(1); ++ r) {
1224 for (int c = bbox.min(0); c <= bbox.max(0); ++ c) {
1225 const Cell &cell = m_cells[r * m_cols + c];
1226 for (size_t i = cell.begin; i < cell.end; ++ i) {
1227 const Contour &contour = m_contours[m_cell_data[i].first];
1228 assert(contour.closed());
1229 size_t ipt = m_cell_data[i].second;
1230 // End points of the line segment.
1231 const Slic3r::Point &p1 = contour.segment_start(ipt);
1232 const Slic3r::Point &p2 = contour.segment_end(ipt);
1233 Slic3r::Point v_seg = p2 - p1;
1234 Slic3r::Point v_pt = pt - p1;
1235 // dot(p2-p1, pt-p1)
1236 int64_t t_pt = int64_t(v_seg(0)) * int64_t(v_pt(0)) + int64_t(v_seg(1)) * int64_t(v_pt(1));
1237 // l2 of seg
1238 int64_t l2_seg = int64_t(v_seg(0)) * int64_t(v_seg(0)) + int64_t(v_seg(1)) * int64_t(v_seg(1));
1239 if (t_pt < 0) {
1240 // Closest to p1.
1241 double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1)));
1242 if (dabs < d_min) {
1243 // Previous point.
1244 const Slic3r::Point &p0 = contour.segment_prev(ipt);
1245 Slic3r::Point v_seg_prev = p1 - p0;
1246 int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1));
1247 if (t2_pt > 0) {
1248 // Inside the wedge between the previous and the next segment.
1249 d_min = dabs;
1250 // Set the signum depending on whether the vertex is convex or reflex.
1251 int64_t det = int64_t(v_seg_prev(0)) * int64_t(v_seg(1)) - int64_t(v_seg_prev(1)) * int64_t(v_seg(0));
1252 assert(det != 0);
1253 sign_min = (det > 0) ? 1 : -1;
1254 on_segment = false;
1255 }
1256 }
1257 }
1258 else if (t_pt > l2_seg) {
1259 // Closest to p2. Then p2 is the starting point of another segment, which shall be discovered in the same cell.
1260 continue;
1261 } else {
1262 // Closest to the segment.
1263 assert(t_pt >= 0 && t_pt <= l2_seg);
1264 int64_t d_seg = int64_t(v_seg(1)) * int64_t(v_pt(0)) - int64_t(v_seg(0)) * int64_t(v_pt(1));
1265 double d = double(d_seg) / sqrt(double(l2_seg));
1266 double dabs = std::abs(d);
1267 if (dabs < d_min) {
1268 d_min = dabs;
1269 sign_min = (d_seg < 0) ? -1 : ((d_seg == 0) ? 0 : 1);
1270 on_segment = true;
1271 }
1272 }
1273 }
1274 }
1275 }
1276 if (d_min >= search_radius)
1277 return false;
1278 result_min_dist = d_min * sign_min;
1279 if (pon_segment != NULL)
1280 *pon_segment = on_segment;
1281 return true;
1282}

References bbox(), Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::contour(), Slic3r::EdgeGrid::Grid::Cell::end, m_bbox, m_cell_data, m_cells, m_cols, m_contours, m_resolution, and m_rows.

Referenced by signed_distance().

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

◆ visit_cells_intersecting_box()

template<typename VISITOR>
void Slic3r::EdgeGrid::Grid::visit_cells_intersecting_box ( BoundingBox bbox,
VISITOR & visitor ) const
inline
338 {
339 // End points of the line segment.
340 bbox.min -= m_bbox.min;
341 bbox.max -= m_bbox.min + Point(1, 1);
342 // Get the cells of the end points.
343 bbox.min /= m_resolution;
344 bbox.max /= m_resolution;
345 // Trim with the cells.
346 bbox.min.x() = std::max<coord_t>(bbox.min.x(), 0);
347 bbox.min.y() = std::max<coord_t>(bbox.min.y(), 0);
348 bbox.max.x() = std::min<coord_t>(bbox.max.x(), (coord_t)m_cols - 1);
349 bbox.max.y() = std::min<coord_t>(bbox.max.y(), (coord_t)m_rows - 1);
350 for (coord_t iy = bbox.min.y(); iy <= bbox.max.y(); ++ iy)
351 for (coord_t ix = bbox.min.x(); ix <= bbox.max.x(); ++ ix)
352 if (! visitor(iy, ix))
353 return;
354 }

References bbox(), m_bbox, m_cols, m_resolution, and m_rows.

Here is the call graph for this function:

◆ visit_cells_intersecting_line()

template<typename VISITOR>
void Slic3r::EdgeGrid::Grid::visit_cells_intersecting_line ( Slic3r::Point p1,
Slic3r::Point p2,
VISITOR & visitor ) const
inline
185 {
186 // End points of the line segment.
187 assert(m_bbox.contains(p1));
188 assert(m_bbox.contains(p2));
189 p1 -= m_bbox.min;
190 p2 -= m_bbox.min;
191 assert(p1.x() >= 0 && size_t(p1.x()) < m_cols * m_resolution);
192 assert(p1.y() >= 0 && size_t(p1.y()) < m_rows * m_resolution);
193 assert(p2.x() >= 0 && size_t(p2.x()) < m_cols * m_resolution);
194 assert(p2.y() >= 0 && size_t(p2.y()) < m_rows * m_resolution);
195 // Get the cells of the end points.
196 coord_t ix = p1(0) / m_resolution;
197 coord_t iy = p1(1) / m_resolution;
198 coord_t ixb = p2(0) / m_resolution;
199 coord_t iyb = p2(1) / m_resolution;
200 assert(ix >= 0 && size_t(ix) < m_cols);
201 assert(iy >= 0 && size_t(iy) < m_rows);
202 assert(ixb >= 0 && size_t(ixb) < m_cols);
203 assert(iyb >= 0 && size_t(iyb) < m_rows);
204 // Account for the end points.
205 if (! visitor(iy, ix) || (ix == ixb && iy == iyb))
206 // Both ends fall into the same cell.
207 return;
208 // Raster the centeral part of the line.
209 coord_t dx = std::abs(p2(0) - p1(0));
210 coord_t dy = std::abs(p2(1) - p1(1));
211 if (p1(0) < p2(0)) {
212 int64_t ex = int64_t((ix + 1)*m_resolution - p1(0)) * int64_t(dy);
213 if (p1(1) < p2(1)) {
214 // x positive, y positive
215 int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
216 do {
217 assert(ix <= ixb && iy <= iyb);
218 if (ex < ey) {
219 ey -= ex;
220 ex = int64_t(dy) * m_resolution;
221 ix += 1;
222 assert(ix <= ixb);
223 }
224 else if (ex == ey) {
225 ex = int64_t(dy) * m_resolution;
226 ey = int64_t(dx) * m_resolution;
227 ix += 1;
228 iy += 1;
229 assert(ix <= ixb);
230 assert(iy <= iyb);
231 }
232 else {
233 assert(ex > ey);
234 ex -= ey;
235 ey = int64_t(dx) * m_resolution;
236 iy += 1;
237 assert(iy <= iyb);
238 }
239 if (ix < 0 || iy < 0 || ix >= (int64_t)m_cols || iy >= (int64_t)m_rows)
240 return;
241 if (! visitor(iy, ix))
242 return;
243 } while (ix != ixb || iy != iyb);
244 }
245 else {
246 // x positive, y non positive
247 int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
248 do {
249 assert(ix <= ixb && iy >= iyb);
250 if (ex <= ey) {
251 ey -= ex;
252 ex = int64_t(dy) * m_resolution;
253 ix += 1;
254 assert(ix <= ixb);
255 }
256 else {
257 ex -= ey;
258 ey = int64_t(dx) * m_resolution;
259 iy -= 1;
260 assert(iy >= iyb);
261 }
262 if (ix < 0 || iy < 0 || ix >= (int64_t)m_cols || iy >= (int64_t)m_rows)
263 return;
264 if (! visitor(iy, ix))
265 return;
266 } while (ix != ixb || iy != iyb);
267 }
268 }
269 else {
270 int64_t ex = int64_t(p1(0) - ix*m_resolution) * int64_t(dy);
271 if (p1(1) < p2(1)) {
272 // x non positive, y positive
273 int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
274 do {
275 assert(ix >= ixb && iy <= iyb);
276 if (ex < ey) {
277 ey -= ex;
278 ex = int64_t(dy) * m_resolution;
279 ix -= 1;
280 assert(ix >= ixb);
281 }
282 else {
283 assert(ex >= ey);
284 ex -= ey;
285 ey = int64_t(dx) * m_resolution;
286 iy += 1;
287 assert(iy <= iyb);
288 }
289 if (ix < 0 || iy < 0 || ix >= (int64_t)m_cols || iy >= (int64_t)m_rows)
290 return;
291 if (! visitor(iy, ix))
292 return;
293 } while (ix != ixb || iy != iyb);
294 }
295 else {
296 // x non positive, y non positive
297 int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
298 do {
299 assert(ix >= ixb && iy >= iyb);
300 if (ex < ey) {
301 ey -= ex;
302 ex = int64_t(dy) * m_resolution;
303 ix -= 1;
304 assert(ix >= ixb);
305 }
306 else if (ex == ey) {
307 // The lower edge of a grid cell belongs to the cell.
308 // Handle the case where the ray may cross the lower left corner of a cell in a general case,
309 // or a left or lower edge in a degenerate case (horizontal or vertical line).
310 if (dx > 0) {
311 ex = int64_t(dy) * m_resolution;
312 ix -= 1;
313 assert(ix >= ixb);
314 }
315 if (dy > 0) {
316 ey = int64_t(dx) * m_resolution;
317 iy -= 1;
318 assert(iy >= iyb);
319 }
320 }
321 else {
322 assert(ex > ey);
323 ex -= ey;
324 ey = int64_t(dx) * m_resolution;
325 iy -= 1;
326 assert(iy >= iyb);
327 }
328 if (ix < 0 || iy < 0 || ix >= (int64_t)m_cols || iy >= (int64_t)m_rows)
329 return;
330 if (! visitor(iy, ix))
331 return;
332 } while (ix != ixb || iy != iyb);
333 }
334 }
335 }

References m_bbox, m_cols, m_resolution, and m_rows.

Referenced by Slic3r::any_expolygon_contains(), Slic3r::any_expolygon_contains(), Slic3r::avoid_perimeters_inner(), create_from_m_contours(), Slic3r::FillLightning::lineSegmentPolygonsIntersection(), Slic3r::FillLightning::polygonCollidesWithLineSegment(), and Slic3r::simplify_travel().

Here is the caller graph for this function:

Member Data Documentation

◆ m_bbox

◆ m_cell_data

std::vector<std::pair<size_t, size_t> > Slic3r::EdgeGrid::Grid::m_cell_data
protected

◆ m_cells

◆ m_cols

◆ m_contours

◆ m_resolution

◆ m_rows

◆ m_signed_distance_field

std::vector<float> Slic3r::EdgeGrid::Grid::m_signed_distance_field
protected

The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/EdgeGrid.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/EdgeGrid.cpp