Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::EdgeGrid::Grid Class Reference

#include <src/libslic3r/EdgeGrid.hpp>

+ Collaboration diagram for Slic3r::EdgeGrid::Grid:

Classes

struct  Cell
 
struct  ClosestPointResult
 

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 BoundingBoxbbox () 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< Contourm_contours
 
std::vector< std::pair< size_t, size_t > > m_cell_data
 
std::vector< Cellm_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
95: m_bbox(bbox) {}
const BoundingBox & bbox() const
Definition EdgeGrid.hpp:159
BoundingBox m_bbox
Definition EdgeGrid.hpp:383

Member Function Documentation

◆ bbox()

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

References m_bbox.

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

+ Here is the caller graph for this function:

◆ calculate_sdf()

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

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::contour(), Slic3r::debug_out_path(), Slic3r::EdgeGrid::Grid::Cell::end, floor(), L, PROPAGATE_SIGNUM_SINGLE_STEP, sign(), sqrt(), 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
337 {
338 assert(row >= 0 && size_t(row) < m_rows);
339 assert(col >= 0 && size_t(col) < m_cols);
340 const EdgeGrid::Grid::Cell &cell = m_cells[row * m_cols + col];
341 return std::make_pair(m_cell_data.begin() + cell.begin, m_cell_data.begin() + cell.end);
342 }
EIGEN_DEVICE_FUNC RowXpr row(Index i)
This is the const version of row(). *‍/.
Definition BlockMethods.h:859
EIGEN_DEVICE_FUNC ColXpr col(Index i)
This is the const version of col().
Definition BlockMethods.h:838

References Slic3r::EdgeGrid::Grid::Cell::begin, col(), Slic3r::EdgeGrid::Grid::Cell::end, m_cell_data, m_cells, m_cols, m_rows, and row().

Referenced by Slic3r::contour_distance(), Slic3r::contour_distance(), Slic3r::contour_distance2(), Slic3r::mark_boundary_segments_touching_infill(), Slic3r::AllIntersectionsVisitor::operator()(), Slic3r::FirstIntersectionVisitor::operator()(), Slic3r::MinDistanceVisitor::operator()(), and Slic3r::PaintedLineVisitor::operator()().

+ Here is the call graph for this function:
+ 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
370 {
371 if (r < 0 || (size_t)r >= m_rows ||
372 c < 0 || (size_t)c >= m_cols)
373 // The cell is outside the domain. Hoping that the contours were correctly oriented, so
374 // there is a CCW outmost contour so the out of domain cells are outside.
375 return false;
376 const Cell &cell = m_cells[r * m_cols + c];
377 return
378 (cell.begin < cell.end) ||
379 (! m_signed_distance_field.empty() && m_signed_distance_field[r * (m_cols + 1) + c] <= 0.f);
380 }

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

◆ closest_point_signed_distance()

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

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::contour(), Slic3r::EdgeGrid::Grid::ClosestPointResult::contour_idx, Slic3r::BoundingBoxBase< PointType, APointsType >::defined, Slic3r::EdgeGrid::Grid::ClosestPointResult::distance, Slic3r::EdgeGrid::Grid::Cell::end, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, sqrt(), 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
162{ return m_cols; }

References m_cols.

◆ contours()

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

References m_contours.

◆ contours_simplified()

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

References Slic3r::cross(), Slic3r::offset(), Slic3r::MultiPoint::points, 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 
)
103{
104 m_contours.clear();
105 m_contours.reserve((expoly.contour.empty() ? 0 : 1) + std::count_if(expoly.holes.begin(), expoly.holes.end(), [](const Polygon &p) { return ! p.empty(); }));
106 if (! expoly.contour.empty())
107 m_contours.emplace_back(expoly.contour.points, false);
108 for (const Polygon &hole : expoly.holes)
109 if (! hole.empty())
110 m_contours.emplace_back(hole.points, false);
111
113}
void create_from_m_contours(coord_t resolution)
Definition EdgeGrid.cpp:140
const coord_t resolution() const
Definition EdgeGrid.hpp:160
#define const
Definition getopt.c:38
if(!(yy_init))
Definition lexer.c:1190
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:229
const Polygons & holes(const ExPolygon &p)
Definition AGGRaster.hpp:22
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
S::iterator end(S &sh, const PathTag &)
Definition geometry_traits.hpp:620
Slic3r::Polygon & hole(Slic3r::ExPolygon &sh, unsigned long idx)
Definition geometries.hpp:200
STL namespace.

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

+ Here is the call graph for this function:

◆ create() [2/7]

void Slic3r::EdgeGrid::Grid::create ( const ExPolygons expolygons,
coord_t  resolution 
)
116{
117 // Count the contours.
118 size_t ncontours = 0;
119 for (const ExPolygon &expoly : expolygons) {
120 if (! expoly.contour.empty())
121 ++ ncontours;
122 ncontours += std::count_if(expoly.holes.begin(), expoly.holes.end(), [](const Polygon &p) { return ! p.empty(); });
123 }
124
125 // Collect the contours.
126 m_contours.clear();
127 m_contours.reserve(ncontours);
128 for (const ExPolygon &expoly : expolygons) {
129 if (! expoly.contour.empty())
130 m_contours.emplace_back(expoly.contour.points, false);
131 for (const Polygon &hole : expoly.holes)
132 if (! hole.empty())
133 m_contours.emplace_back(hole.points, false);
134 }
135
137}

References Slic3r::MultiPoint::empty(), and Slic3r::MultiPoint::points.

+ 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 
)
76{
77 // Collect the contours.
78 m_contours.clear();
79 m_contours.reserve(
80 std::count_if(polygons.begin(), polygons.end(), [](const Polygon &p) { return p.size() > 1; }) +
81 std::count_if(polylines.begin(), polylines.end(), [](const Polyline &p) { return p.size() > 1; }));
82
83 for (const Polyline &polyline : polylines)
84 if (polyline.size() > 1) {
85 const Point *begin = polyline.points.data();
86 const Point *end = polyline.points.data() + polyline.size();
87 bool open = true;
88 if (*begin == end[-1]) {
89 open = false;
90 -- end;
91 }
92 m_contours.emplace_back(begin, end, open);
93 }
94
95 for (const Polygon &polygon : polygons)
96 if (polygon.size() > 1)
97 m_contours.emplace_back(polygon.points, false);
98
100}
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:183

◆ create() [4/7]

void Slic3r::EdgeGrid::Grid::create ( const Polygons polygons,
coord_t  resolution 
)
29{
30 // Collect the contours.
31 m_contours.clear();
32 m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Polygon &p) { return ! p.empty(); }));
33 for (const Polygon &polygon : polygons)
34 if (! polygon.empty())
35 m_contours.emplace_back(polygon.points, false);
36
38}

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 
)
41{
42 // Collect the contours.
43 m_contours.clear();
44 m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Polygon *p) { return ! p->empty(); }));
45 for (const Polygon *polygon : polygons)
46 if (! polygon->empty())
47 m_contours.emplace_back(polygon->points, false);
48
50}

◆ create() [6/7]

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

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 
)
53{
54 // Collect the contours.
55 m_contours.clear();
56 m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Points &p) { return p.size() > 1; }));
57 for (const Points &points : polygons)
58 if (points.size() > 1) {
59 const Point *begin = points.data();
60 const Point *end = points.data() + points.size();
61 bool open = open_polylines;
62 if (open_polylines) {
63 if (*begin == end[-1]) {
64 open = false;
65 -- end;
66 }
67 } else
68 assert(*begin != end[-1]);
69 m_contours.emplace_back(begin, end, open);
70 }
71
73}

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

+ Here is the caller graph for this function:

◆ create_from_m_contours()

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

References Slic3r::MultiPoint::begin(), Slic3r::contour(), and Slic3r::MultiPoint::end().

Referenced by 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
1451{
1452 // For each cell:
1453 for (int r = 0; r < (int)m_rows; ++ r) {
1454 for (int c = 0; c < (int)m_cols; ++ c) {
1455 const Cell &cell = m_cells[r * m_cols + c];
1456 // For each pair of segments in the cell:
1457 for (size_t i = cell.begin; i != cell.end; ++ i) {
1458 const Contour &icontour = m_contours[m_cell_data[i].first];
1459 size_t ipt = m_cell_data[i].second;
1460 // End points of the line segment and their vector.
1461 const Slic3r::Point &ip1 = icontour.segment_start(ipt);
1462 const Slic3r::Point &ip2 = icontour.segment_end(ipt);
1463 for (size_t j = i + 1; j != cell.end; ++ j) {
1464 const Contour &jcontour = m_contours[m_cell_data[j].first];
1465 size_t jpt = m_cell_data[j].second;
1466 // End points of the line segment and their vector.
1467 const Slic3r::Point &jp1 = jcontour.segment_start(jpt);
1468 const Slic3r::Point &jp2 = jcontour.segment_end(jpt);
1469 if (! (&icontour == &jcontour && (&ip1 == &jp2 || &jp1 == &ip2)) &&
1470 Geometry::segments_intersect(ip1, ip2, jp1, jp2))
1471 return true;
1472 }
1473 }
1474 }
1475 }
1476 return false;
1477}
bool segments_intersect(const Slic3r::Point &ip1, const Slic3r::Point &ip2, const Slic3r::Point &jp1, const Slic3r::Point &jp2)
Definition Geometry.hpp:112

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::EdgeGrid::Grid::Cell::end, 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
1413{
1414 std::vector<std::pair<ContourEdge, ContourEdge>> out;
1415 // For each cell:
1416 for (int r = 0; r < (int)m_rows; ++ r) {
1417 for (int c = 0; c < (int)m_cols; ++ c) {
1418 const Cell &cell = m_cells[r * m_cols + c];
1419 // For each pair of segments in the cell:
1420 for (size_t i = cell.begin; i != cell.end; ++ i) {
1421 const Contour &icontour = m_contours[m_cell_data[i].first];
1422 size_t ipt = m_cell_data[i].second;
1423 // End points of the line segment and their vector.
1424 const Slic3r::Point &ip1 = icontour.segment_start(ipt);
1425 const Slic3r::Point &ip2 = icontour.segment_end(ipt);
1426 for (size_t j = i + 1; j != cell.end; ++ j) {
1427 const Contour &jcontour = m_contours[m_cell_data[j].first];
1428 size_t jpt = m_cell_data[j].second;
1429 // End points of the line segment and their vector.
1430 const Slic3r::Point &jp1 = jcontour.segment_start(jpt);
1431 const Slic3r::Point &jp2 = jcontour.segment_end(jpt);
1432 if (&icontour == &jcontour && (&ip1 == &jp2 || &jp1 == &ip2))
1433 // Segments of the same contour share a common vertex.
1434 continue;
1435 if (Geometry::segments_intersect(ip1, ip2, jp1, jp2)) {
1436 // The two segments intersect. Add them to the output.
1437 int jfirst = (&jcontour < &icontour) || (&jcontour == &icontour && jpt < ipt);
1438 out.emplace_back(jfirst ?
1439 std::make_pair(std::make_pair(&icontour, ipt), std::make_pair(&jcontour, jpt)) :
1440 std::make_pair(std::make_pair(&icontour, ipt), std::make_pair(&jcontour, jpt)));
1441 }
1442 }
1443 }
1444 }
1445 }
1447 return out;
1448}
void sort_remove_duplicates(std::vector< T > &vec)
Definition libslic3r.h:188

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::EdgeGrid::Grid::Cell::end, 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
352 {
353 const Contour &contour = m_contours[contour_and_segment_idx.first];
354 size_t iseg = contour_and_segment_idx.second;
355 return Line(contour.segment_start(iseg), contour.segment_end(iseg));
356 }

References Slic3r::contour(), and m_contours.

Referenced by Slic3r::AllIntersectionsVisitor::operator()(), and Slic3r::PaintedLineVisitor::operator()().

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

◆ resolution()

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

References m_resolution.

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

+ Here is the caller graph for this function:

◆ rows()

const size_t Slic3r::EdgeGrid::Grid::rows ( ) const
inline
161{ 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
345 {
346 const Contour &contour = m_contours[contour_and_segment_idx.first];
347 size_t iseg = contour_and_segment_idx.second;
348 return std::pair<const Slic3r::Point&, const Slic3r::Point&>(contour.segment_start(iseg), contour.segment_end(iseg));
349 }

References Slic3r::contour(), and m_contours.

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

+ 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
97{ m_bbox = bbox; }

References bbox(), and m_bbox.

Referenced by Slic3r::FillLightning::Generator::generateTrees(), 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
1272{
1273 if (signed_distance_edges(pt, search_radius, result_min_dist))
1274 return true;
1275 if (m_signed_distance_field.empty())
1276 return false;
1277 result_min_dist = signed_distance_bilinear(pt);
1278 return true;
1279}
float signed_distance_bilinear(const Point &pt) const
Definition EdgeGrid.cpp:980
bool signed_distance_edges(const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment=nullptr) const
Definition EdgeGrid.cpp:1176

◆ signed_distance_bilinear()

float Slic3r::EdgeGrid::Grid::signed_distance_bilinear ( const Point pt) const
981{
982 coord_t x = pt(0) - m_bbox.min(0);
983 coord_t y = pt(1) - m_bbox.min(1);
986 bool clamped = false;
987 coord_t xcl = x;
988 coord_t ycl = y;
989 if (x < 0) {
990 xcl = 0;
991 clamped = true;
992 } else if (x >= w) {
993 xcl = w - 1;
994 clamped = true;
995 }
996 if (y < 0) {
997 ycl = 0;
998 clamped = true;
999 } else if (y >= h) {
1000 ycl = h - 1;
1001 clamped = true;
1002 }
1003
1004 coord_t cell_c = coord_t(floor(xcl / m_resolution));
1005 coord_t cell_r = coord_t(floor(ycl / m_resolution));
1006 float tx = float(xcl - cell_c * m_resolution) / float(m_resolution);
1007 assert(tx >= -1e-5 && tx < 1.f + 1e-5);
1008 float ty = float(ycl - cell_r * m_resolution) / float(m_resolution);
1009 assert(ty >= -1e-5 && ty < 1.f + 1e-5);
1010 size_t addr = cell_r * (m_cols + 1) + cell_c;
1011 float f00 = m_signed_distance_field[addr];
1012 float f01 = m_signed_distance_field[addr+1];
1013 addr += m_cols + 1;
1014 float f10 = m_signed_distance_field[addr];
1015 float f11 = m_signed_distance_field[addr+1];
1016 float f0 = (1.f - tx) * f00 + tx * f01;
1017 float f1 = (1.f - tx) * f10 + tx * f11;
1018 float f = (1.f - ty) * f0 + ty * f1;
1019
1020 if (clamped) {
1021 if (f > 0) {
1022 if (x < 0)
1023 f += -x;
1024 else if (x >= w)
1025 f += x - w + 1;
1026 if (y < 0)
1027 f += -y;
1028 else if (y >= h)
1029 f += y - h + 1;
1030 } else {
1031 if (x < 0)
1032 f -= -x;
1033 else if (x >= w)
1034 f -= x - w + 1;
1035 if (y < 0)
1036 f -= -y;
1037 else if (y >= h)
1038 f -= y - h + 1;
1039 }
1040 }
1041
1042 return f;
1043}
const Scalar & y
Definition MathFunctions.h:552
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:12
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297

References Slic3r::f(), and floor().

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

References Slic3r::EdgeGrid::Grid::Cell::begin, Slic3r::contour(), Slic3r::BoundingBoxBase< PointType, APointsType >::defined, Slic3r::EdgeGrid::Grid::Cell::end, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, and sqrt().

+ Here is the call 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
318 {
319 // End points of the line segment.
320 bbox.min -= m_bbox.min;
321 bbox.max -= m_bbox.min + Point(1, 1);
322 // Get the cells of the end points.
325 // Trim with the cells.
326 bbox.min.x() = std::max<coord_t>(bbox.min.x(), 0);
327 bbox.min.y() = std::max<coord_t>(bbox.min.y(), 0);
328 bbox.max.x() = std::min<coord_t>(bbox.max.x(), (coord_t)m_cols - 1);
329 bbox.max.y() = std::min<coord_t>(bbox.max.y(), (coord_t)m_rows - 1);
330 for (coord_t iy = bbox.min.y(); iy <= bbox.max.y(); ++ iy)
331 for (coord_t ix = bbox.min.x(); ix <= bbox.max.x(); ++ ix)
332 if (! visitor(iy, ix))
333 return;
334 }

References bbox(), m_bbox, m_cols, m_resolution, m_rows, Slic3r::BoundingBoxBase< PointType, APointsType >::max, and Slic3r::BoundingBoxBase< PointType, APointsType >::min.

+ 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
173 {
174 // End points of the line segment.
175 assert(m_bbox.contains(p1));
176 assert(m_bbox.contains(p2));
177 p1 -= m_bbox.min;
178 p2 -= m_bbox.min;
179 assert(p1.x() >= 0 && size_t(p1.x()) < m_cols * m_resolution);
180 assert(p1.y() >= 0 && size_t(p1.y()) < m_rows * m_resolution);
181 assert(p2.x() >= 0 && size_t(p2.x()) < m_cols * m_resolution);
182 assert(p2.y() >= 0 && size_t(p2.y()) < m_rows * m_resolution);
183 // Get the cells of the end points.
184 coord_t ix = p1(0) / m_resolution;
185 coord_t iy = p1(1) / m_resolution;
186 coord_t ixb = p2(0) / m_resolution;
187 coord_t iyb = p2(1) / m_resolution;
188 assert(ix >= 0 && size_t(ix) < m_cols);
189 assert(iy >= 0 && size_t(iy) < m_rows);
190 assert(ixb >= 0 && size_t(ixb) < m_cols);
191 assert(iyb >= 0 && size_t(iyb) < m_rows);
192 // Account for the end points.
193 if (! visitor(iy, ix) || (ix == ixb && iy == iyb))
194 // Both ends fall into the same cell.
195 return;
196 // Raster the centeral part of the line.
197 coord_t dx = std::abs(p2(0) - p1(0));
198 coord_t dy = std::abs(p2(1) - p1(1));
199 if (p1(0) < p2(0)) {
200 int64_t ex = int64_t((ix + 1)*m_resolution - p1(0)) * int64_t(dy);
201 if (p1(1) < p2(1)) {
202 // x positive, y positive
203 int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
204 do {
205 assert(ix <= ixb && iy <= iyb);
206 if (ex < ey) {
207 ey -= ex;
208 ex = int64_t(dy) * m_resolution;
209 ix += 1;
210 assert(ix <= ixb);
211 }
212 else if (ex == ey) {
213 ex = int64_t(dy) * m_resolution;
214 ey = int64_t(dx) * m_resolution;
215 ix += 1;
216 iy += 1;
217 assert(ix <= ixb);
218 assert(iy <= iyb);
219 }
220 else {
221 assert(ex > ey);
222 ex -= ey;
223 ey = int64_t(dx) * m_resolution;
224 iy += 1;
225 assert(iy <= iyb);
226 }
227 if (! visitor(iy, ix))
228 return;
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 assert(ix <= ixb);
241 }
242 else {
243 ex -= ey;
244 ey = int64_t(dx) * m_resolution;
245 iy -= 1;
246 assert(iy >= iyb);
247 }
248 if (! visitor(iy, ix))
249 return;
250 } while (ix != ixb || iy != iyb);
251 }
252 }
253 else {
254 int64_t ex = int64_t(p1(0) - ix*m_resolution) * int64_t(dy);
255 if (p1(1) < p2(1)) {
256 // x non positive, y positive
257 int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx);
258 do {
259 assert(ix >= ixb && iy <= iyb);
260 if (ex < ey) {
261 ey -= ex;
262 ex = int64_t(dy) * m_resolution;
263 ix -= 1;
264 assert(ix >= ixb);
265 }
266 else {
267 assert(ex >= ey);
268 ex -= ey;
269 ey = int64_t(dx) * m_resolution;
270 iy += 1;
271 assert(iy <= iyb);
272 }
273 if (! visitor(iy, ix))
274 return;
275 } while (ix != ixb || iy != iyb);
276 }
277 else {
278 // x non positive, y non positive
279 int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx);
280 do {
281 assert(ix >= ixb && iy >= iyb);
282 if (ex < ey) {
283 ey -= ex;
284 ex = int64_t(dy) * m_resolution;
285 ix -= 1;
286 assert(ix >= ixb);
287 }
288 else if (ex == ey) {
289 // The lower edge of a grid cell belongs to the cell.
290 // Handle the case where the ray may cross the lower left corner of a cell in a general case,
291 // or a left or lower edge in a degenerate case (horizontal or vertical line).
292 if (dx > 0) {
293 ex = int64_t(dy) * m_resolution;
294 ix -= 1;
295 assert(ix >= ixb);
296 }
297 if (dy > 0) {
298 ey = int64_t(dx) * m_resolution;
299 iy -= 1;
300 assert(iy >= iyb);
301 }
302 }
303 else {
304 assert(ex > ey);
305 ex -= ey;
306 ey = int64_t(dx) * m_resolution;
307 iy -= 1;
308 assert(iy >= iyb);
309 }
310 if (! visitor(iy, ix))
311 return;
312 } while (ix != ixb || iy != iyb);
313 }
314 }
315 }
bool contains(const PointType &point) const
Definition BoundingBox.hpp:46

References Slic3r::BoundingBoxBase< PointType, APointsType >::contains(), m_bbox, m_cols, m_resolution, m_rows, and Slic3r::BoundingBoxBase< PointType, APointsType >::min.

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

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

Member Data Documentation

◆ m_bbox

BoundingBox Slic3r::EdgeGrid::Grid::m_bbox
protected

◆ m_cell_data

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

Referenced by cell_data_range().

◆ m_cells

std::vector<Cell> Slic3r::EdgeGrid::Grid::m_cells
protected

◆ m_cols

size_t Slic3r::EdgeGrid::Grid::m_cols = 0
protected

◆ m_contours

std::vector<Contour> Slic3r::EdgeGrid::Grid::m_contours
protected

Referenced by contours(), create(), line(), and segment().

◆ m_resolution

coord_t Slic3r::EdgeGrid::Grid::m_resolution
protected

◆ m_rows

size_t Slic3r::EdgeGrid::Grid::m_rows = 0
protected

◆ m_signed_distance_field

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

Referenced by cell_inside_or_crossing().


The documentation for this class was generated from the following files: