From 54a5c1da1e7b9bcdf7237fc560cffd514bd56a30 Mon Sep 17 00:00:00 2001
From: Vojtech Bubnik <bubnikv@gmail.com>
Date: Fri, 20 Nov 2020 18:46:39 +0100
Subject: [PATCH] Fixed crash in reworked infill anchoring due to numeric
 issues. Added some more asserts to EdgeGrid.

---
 src/libslic3r/EdgeGrid.hpp      | 24 ++++++++++++++++++++----
 src/libslic3r/Fill/FillBase.cpp | 15 +++++++--------
 2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/src/libslic3r/EdgeGrid.hpp b/src/libslic3r/EdgeGrid.hpp
index 71d636628..fd13ddc7f 100644
--- a/src/libslic3r/EdgeGrid.hpp
+++ b/src/libslic3r/EdgeGrid.hpp
@@ -84,10 +84,14 @@ public:
 	template<typename VISITOR> void visit_cells_intersecting_line(Slic3r::Point p1, Slic3r::Point p2, VISITOR &visitor) const
 	{
 		// End points of the line segment.
-		p1(0) -= m_bbox.min(0);
-		p1(1) -= m_bbox.min(1);
-		p2(0) -= m_bbox.min(0);
-		p2(1) -= m_bbox.min(1);
+		assert(m_bbox.contains(p1));
+		assert(m_bbox.contains(p2));
+		p1 -= m_bbox.min;
+		p2 -= m_bbox.min;
+		assert(p1.x() >= 0 && p1.x() < m_cols * m_resolution);
+		assert(p1.y() >= 0 && p1.y() < m_rows * m_resolution);
+		assert(p2.x() >= 0 && p2.x() < m_cols * m_resolution);
+		assert(p2.y() >= 0 && p2.y() < m_rows * m_resolution);
 		// Get the cells of the end points.
 		coord_t ix = p1(0) / m_resolution;
 		coord_t iy = p1(1) / m_resolution;
@@ -115,18 +119,22 @@ public:
 						ey -= ex;
 						ex = int64_t(dy) * m_resolution;
 						ix += 1;
+						assert(ix <= ixb);
 					}
 					else if (ex == ey) {
 						ex = int64_t(dy) * m_resolution;
 						ey = int64_t(dx) * m_resolution;
 						ix += 1;
 						iy += 1;
+						assert(ix <= ixb);
+						assert(iy <= iyb);
 					}
 					else {
 						assert(ex > ey);
 						ex -= ey;
 						ey = int64_t(dx) * m_resolution;
 						iy += 1;
+						assert(iy <= iyb);
 					}
 					if (! visitor(iy, ix))
 						return;
@@ -141,11 +149,13 @@ public:
 						ey -= ex;
 						ex = int64_t(dy) * m_resolution;
 						ix += 1;
+						assert(ix <= ixb);
 					}
 					else {
 						ex -= ey;
 						ey = int64_t(dx) * m_resolution;
 						iy -= 1;
+						assert(iy >= iyb);
 					}
 					if (! visitor(iy, ix))
 						return;
@@ -163,12 +173,14 @@ public:
 						ey -= ex;
 						ex = int64_t(dy) * m_resolution;
 						ix -= 1;
+						assert(ix >= ixb);
 					}
 					else {
 						assert(ex >= ey);
 						ex -= ey;
 						ey = int64_t(dx) * m_resolution;
 						iy += 1;
+						assert(iy <= iyb);
 					}
 					if (! visitor(iy, ix))
 						return;
@@ -183,6 +195,7 @@ public:
 						ey -= ex;
 						ex = int64_t(dy) * m_resolution;
 						ix -= 1;
+						assert(ix >= ixb);
 					}
 					else if (ex == ey) {
 						// The lower edge of a grid cell belongs to the cell.
@@ -191,10 +204,12 @@ public:
 						if (dx > 0) {
 							ex = int64_t(dy) * m_resolution;
 							ix -= 1;
+							assert(ix >= ixb);
 						}
 						if (dy > 0) {
 							ey = int64_t(dx) * m_resolution;
 							iy -= 1;
+							assert(iy >= iyb);
 						}
 					}
 					else {
@@ -202,6 +217,7 @@ public:
 						ex -= ey;
 						ey = int64_t(dx) * m_resolution;
 						iy -= 1;
+						assert(iy >= iyb);
 					}
 					if (! visitor(iy, ix))
 						return;
diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp
index 7ed928741..4e714b570 100644
--- a/src/libslic3r/Fill/FillBase.cpp
+++ b/src/libslic3r/Fill/FillBase.cpp
@@ -841,7 +841,7 @@ void mark_boundary_segments_touching_infill(
 
 	EdgeGrid::Grid grid;
     // Make sure that the the grid is big enough for queries against the thick segment.
-	grid.set_bbox(boundary_bbox.inflated(distance_colliding + SCALED_EPSILON));
+	grid.set_bbox(boundary_bbox.inflated(distance_colliding * 1.43));
 	// Inflate the bounding box by a thick line width.
 	grid.create(boundary, std::max(clip_distance, distance_colliding) + scale_(10.));
 
@@ -961,9 +961,6 @@ void mark_boundary_segments_touching_infill(
 #endif // INFILL_DEBUG_OUTPUT
 	} visitor(grid, boundary, boundary_parameters, boundary_intersections, distance_colliding);
 
-	BoundingBoxf bboxf(boundary_bbox.min.cast<double>(), boundary_bbox.max.cast<double>());
-	bboxf.offset(- SCALED_EPSILON);
-
 	for (const Polyline &polyline : infill) {
 #ifdef INFILL_DEBUG_OUTPUT
         ++ iStep;
@@ -1019,12 +1016,14 @@ void mark_boundary_segments_touching_infill(
 				Vec2d vperp = perp(v);
 				Vec2d a = pt1 - v - vperp;
 				Vec2d b = pt2 + v - vperp;
-				if (Geometry::liang_barsky_line_clipping(a, b, bboxf))
-					grid.visit_cells_intersecting_line(a.cast<coord_t>(), b.cast<coord_t>(), visitor);
+                assert(grid.bbox().contains(a.cast<coord_t>()));
+                assert(grid.bbox().contains(b.cast<coord_t>()));
+				grid.visit_cells_intersecting_line(a.cast<coord_t>(), b.cast<coord_t>(), visitor);
 				a = pt1 - v + vperp;
 				b = pt2 + v + vperp;
-				if (Geometry::liang_barsky_line_clipping(a, b, bboxf))
-					grid.visit_cells_intersecting_line(a.cast<coord_t>(), b.cast<coord_t>(), visitor);
+                assert(grid.bbox().contains(a.cast<coord_t>()));
+                assert(grid.bbox().contains(b.cast<coord_t>()));
+                grid.visit_cells_intersecting_line(a.cast<coord_t>(), b.cast<coord_t>(), visitor);
 #endif
 #ifdef INFILL_DEBUG_OUTPUT
 //                export_infill_to_svg(boundary, boundary_parameters, boundary_intersections, infill, distance_colliding * 2, debug_out_path("%s-%03d-%03d-%03d.svg", "FillBase-mark_boundary_segments_touching_infill-step", iRun, iStep, int(point_idx)), { polyline });