diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp index ca650faf8..e807a2164 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp @@ -27,10 +27,6 @@ // We want our version of assert. #include "../libslic3r.h" -#ifndef myassert -#define myassert assert -#endif - namespace Slic3r { // Having a segment of a closed polygon, calculate its Euclidian length. @@ -50,8 +46,8 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po std::swap(pa.x, pb.x); if (pa.y > pb.y) std::swap(pa.y, pb.y); - myassert(px.x >= pa.x && px.x <= pb.x); - myassert(px.y >= pa.y && px.y <= pb.y); + assert(px.x >= pa.x && px.x <= pb.x); + assert(px.y >= pa.y && px.y <= pb.y); } #endif /* SLIC3R_DEBUG */ const Point *pPrev = &p1; @@ -288,9 +284,9 @@ public: // for the infill pattern, don't cut the corners. // default miterLimt = 3 //double mitterLimit = 10.; - myassert(aoffset1 < 0); - myassert(aoffset2 < 0); - myassert(aoffset2 < aoffset1); + assert(aoffset1 < 0); + assert(aoffset2 < 0); + assert(aoffset2 < aoffset1); bool sticks_removed = remove_sticks(polygons_src); // if (sticks_removed) printf("Sticks removed!\n"); polygons_outer = offset(polygons_src, aoffset1, @@ -311,7 +307,7 @@ public: polygons_ccw.assign(n_contours, false); for (size_t i = 0; i < n_contours; ++ i) { contour(i).remove_duplicate_points(); - myassert(! contour(i).has_duplicate_points()); + assert(! contour(i).has_duplicate_points()); polygons_ccw[i] = Slic3r::Geometry::is_ccw(contour(i)); } } @@ -406,23 +402,23 @@ static inline int intersection_on_prev_next_vertical_line( if (itsct.iContour == itsct2.iContour && itsct.type == itsct2.type) { /* if (itsct.is_low()) { - myassert(itsct.type == SegmentIntersection::INNER_LOW); - myassert(iIntersection > 0); - myassert(il.intersections[iIntersection-1].type == SegmentIntersection::OUTER_LOW); - myassert(i > 0); + assert(itsct.type == SegmentIntersection::INNER_LOW); + assert(iIntersection > 0); + assert(il.intersections[iIntersection-1].type == SegmentIntersection::OUTER_LOW); + assert(i > 0); if (il2.intersections[i-1].is_inner()) // Take only the lowest inner intersection point. continue; - myassert(il2.intersections[i-1].type == SegmentIntersection::OUTER_LOW); + assert(il2.intersections[i-1].type == SegmentIntersection::OUTER_LOW); } else { - myassert(itsct.type == SegmentIntersection::INNER_HIGH); - myassert(iIntersection+1 < il.intersections.size()); - myassert(il.intersections[iIntersection+1].type == SegmentIntersection::OUTER_HIGH); - myassert(i+1 < il2.intersections.size()); + assert(itsct.type == SegmentIntersection::INNER_HIGH); + assert(iIntersection+1 < il.intersections.size()); + assert(il.intersections[iIntersection+1].type == SegmentIntersection::OUTER_HIGH); + assert(i+1 < il2.intersections.size()); if (il2.intersections[i+1].is_inner()) // Take only the highest inner intersection point. continue; - myassert(il2.intersections[i+1].type == SegmentIntersection::OUTER_HIGH); + assert(il2.intersections[i+1].type == SegmentIntersection::OUTER_HIGH); } */ // The intersection points lie on the same contour and have the same orientation. @@ -487,21 +483,21 @@ static inline IntersectionTypeOtherVLine intersection_type_on_prev_next_vertical // iVertical line multiple times before reaching iIntersectionOther. if (iIntersectionOther == -1) return INTERSECTION_TYPE_OTHER_VLINE_UNDEFINED; - myassert(dir_is_next ? (iVerticalLine + 1 < segs.size()) : (iVerticalLine > 0)); + assert(dir_is_next ? (iVerticalLine + 1 < segs.size()) : (iVerticalLine > 0)); const SegmentedIntersectionLine &il_this = segs[iVerticalLine]; const SegmentIntersection &itsct_this = il_this.intersections[iIntersection]; const SegmentedIntersectionLine &il_other = segs[dir_is_next ? (iVerticalLine+1) : (iVerticalLine-1)]; const SegmentIntersection &itsct_other = il_other.intersections[iIntersectionOther]; - myassert(itsct_other.is_inner()); - myassert(iIntersectionOther > 0); - myassert(iIntersectionOther + 1 < il_other.intersections.size()); + assert(itsct_other.is_inner()); + assert(iIntersectionOther > 0); + assert(iIntersectionOther + 1 < il_other.intersections.size()); // Is iIntersectionOther at the boundary of a vertical segment? const SegmentIntersection &itsct_other2 = il_other.intersections[itsct_other.is_low() ? iIntersectionOther - 1 : iIntersectionOther + 1]; if (itsct_other2.is_inner()) // Cannot follow a perimeter segment into the middle of another vertical segment. // Only perimeter segments connecting to the end of a vertical segment are followed. return INTERSECTION_TYPE_OTHER_VLINE_INNER; - myassert(itsct_other.is_low() == itsct_other2.is_low()); + assert(itsct_other.is_low() == itsct_other2.is_low()); if (dir_is_next ? itsct_this.consumed_perimeter_right : itsct_other.consumed_perimeter_right) // This perimeter segment was already consumed. return INTERSECTION_TYPE_OTHER_VLINE_CONSUMED; @@ -555,9 +551,9 @@ static inline coordf_t measure_perimeter_prev_next_segment_length( const SegmentIntersection &itsct2 = il2.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour(iInnerContour); // const bool ccw = poly_with_offset.is_contour_ccw(iInnerContour); - myassert(itsct.type == itsct2.type); - myassert(itsct.iContour == itsct2.iContour); - myassert(itsct.is_inner()); + assert(itsct.type == itsct2.type); + assert(itsct.iContour == itsct2.iContour); + assert(itsct.is_inner()); const bool forward = itsct.is_low() == dir_is_next; Point p1(il.pos, itsct.pos()); @@ -605,9 +601,9 @@ static inline void emit_perimeter_prev_next_segment( size_t iVerticalLineOther = iVerticalLine; if (dir_is_next) { ++ iVerticalLineOther; - myassert(iVerticalLineOther < segs.size()); + assert(iVerticalLineOther < segs.size()); } else { - myassert(iVerticalLineOther > 0); + assert(iVerticalLineOther > 0); -- iVerticalLineOther; } @@ -617,9 +613,9 @@ static inline void emit_perimeter_prev_next_segment( const SegmentIntersection &itsct2 = il2.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour(iInnerContour); // const bool ccw = poly_with_offset.is_contour_ccw(iInnerContour); - myassert(itsct.type == itsct2.type); - myassert(itsct.iContour == itsct2.iContour); - myassert(itsct.is_inner()); + assert(itsct.type == itsct2.type); + assert(itsct.iContour == itsct2.iContour); + assert(itsct.is_inner()); const bool forward = itsct.is_low() == dir_is_next; // Do not append the first point. // out.points.push_back(Point(il.pos, itsct.pos)); @@ -644,11 +640,11 @@ static inline coordf_t measure_perimeter_segment_on_vertical_line_length( const SegmentIntersection &itsct = il.intersections[iIntersection]; const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour(iInnerContour); - myassert(itsct.is_inner()); - myassert(itsct2.is_inner()); - myassert(itsct.type != itsct2.type); - myassert(itsct.iContour == iInnerContour); - myassert(itsct.iContour == itsct2.iContour); + assert(itsct.is_inner()); + assert(itsct2.is_inner()); + assert(itsct.type != itsct2.type); + assert(itsct.iContour == iInnerContour); + assert(itsct.iContour == itsct2.iContour); Point p1(il.pos, itsct.pos()); Point p2(il.pos, itsct2.pos()); return forward ? @@ -673,11 +669,11 @@ static inline void emit_perimeter_segment_on_vertical_line( const SegmentIntersection &itsct = il.intersections[iIntersection]; const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour(iInnerContour); - myassert(itsct.is_inner()); - myassert(itsct2.is_inner()); - myassert(itsct.type != itsct2.type); - myassert(itsct.iContour == iInnerContour); - myassert(itsct.iContour == itsct2.iContour); + assert(itsct.is_inner()); + assert(itsct2.is_inner()); + assert(itsct.type != itsct2.type); + assert(itsct.iContour == iInnerContour); + assert(itsct.iContour == itsct2.iContour); // Do not append the first point. // out.points.push_back(Point(il.pos, itsct.pos)); if (forward) @@ -700,10 +696,10 @@ static inline float measure_outer_contour_slab( const SegmentIntersection &itsct = il.intersections[i_vline]; const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour((itsct.iContour); - myassert(itsct.is_outer()); - myassert(itsct2.is_outer()); - myassert(itsct.type != itsct2.type); - myassert(itsct.iContour == itsct2.iContour); + assert(itsct.is_outer()); + assert(itsct2.is_outer()); + assert(itsct.type != itsct2.type); + assert(itsct.iContour == itsct2.iContour); if (! itsct.is_outer() || ! itsct2.is_outer() || itsct.type == itsct2.type || itsct.iContour != itsct2.iContour) // Error, return zero area. return 0.f; @@ -770,13 +766,13 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // Shrink the input polygon a bit first to not push the infill lines out of the perimeters. // const float INFILL_OVERLAP_OVER_SPACING = 0.3f; const float INFILL_OVERLAP_OVER_SPACING = 0.45f; - myassert(INFILL_OVERLAP_OVER_SPACING > 0 && INFILL_OVERLAP_OVER_SPACING < 0.5f); + assert(INFILL_OVERLAP_OVER_SPACING > 0 && INFILL_OVERLAP_OVER_SPACING < 0.5f); // Rotate polygons so that we can work with vertical lines here std::pair rotate_vector = this->_infill_direction(surface); rotate_vector.first += angleBase; - myassert(params.density > 0.0001f && params.density <= 1.f); + assert(params.density > 0.0001f && params.density <= 1.f); coord_t line_spacing = coord_t(scale_(this->spacing) / params.density); // On the polygons of poly_with_offset, the infill lines will be connected. @@ -862,16 +858,16 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP if (il > ir) // No vertical line intersects this segment. continue; - myassert(il >= 0 && il < segs.size()); - myassert(ir >= 0 && ir < segs.size()); + assert(il >= 0 && il < segs.size()); + assert(ir >= 0 && ir < segs.size()); for (int i = il; i <= ir; ++ i) { coord_t this_x = segs[i].pos; assert(this_x == i * line_spacing + x0); SegmentIntersection is; is.iContour = iContour; is.iSegment = iSegment; - myassert(l <= this_x); - myassert(r >= this_x); + assert(l <= this_x); + assert(r >= this_x); // Calculate the intersection position in y axis. x is known. if (p1.x == this_x) { if (p2.x == this_x) { @@ -892,14 +888,14 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP is.pos_p = p1.x - this_x; is.pos_q = p1.x - p2.x; } - myassert(is.pos_p >= 0 && is.pos_p <= is.pos_q); + assert(is.pos_p >= 0 && is.pos_p <= is.pos_q); // Make an intersection point from the 't'. is.pos_p *= int64_t(p2.y - p1.y); is.pos_p += p1.y * int64_t(is.pos_q); } // +-1 to take rounding into account. - myassert(is.pos() + 1 >= std::min(p1.y, p2.y)); - myassert(is.pos() <= std::max(p1.y, p2.y) + 1); + assert(is.pos() + 1 >= std::min(p1.y, p2.y)); + assert(is.pos() <= std::max(p1.y, p2.y) + 1); segs[i].intersections.push_back(is); } } @@ -936,7 +932,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // Verify that the segments of sil.intersections[i] and sil.intersections[j-1] are adjoint. size_t iSegment2 = sil.intersections[j-1].iSegment; size_t iPrev2 = ((iSegment2 == 0) ? contour.size() : iSegment2) - 1; - myassert(iSegment == iPrev2 || iSegment2 == iPrev); + assert(iSegment == iPrev2 || iSegment2 == iPrev); #endif /* SLIC3R_DEBUG */ if (sil.intersections[i].type == sil.intersections[j-1].type) { // Two successive segments of the same direction (both to the right or both to the left) @@ -1058,14 +1054,14 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP for (size_t i_vline2 = 0; i_vline2 < segs.size(); ++ i_vline2) { const SegmentedIntersectionLine &seg = segs[i_vline2]; if (! seg.intersections.empty()) { - myassert(seg.intersections.size() > 1); + assert(seg.intersections.size() > 1); // Even number of intersections with the loops. - myassert((seg.intersections.size() & 1) == 0); - myassert(seg.intersections.front().type == SegmentIntersection::OUTER_LOW); + assert((seg.intersections.size() & 1) == 0); + assert(seg.intersections.front().type == SegmentIntersection::OUTER_LOW); for (size_t i = 0; i < seg.intersections.size(); ++ i) { const SegmentIntersection &intrsctn = seg.intersections[i]; if (intrsctn.is_outer()) { - myassert(intrsctn.is_low() || i > 0); + assert(intrsctn.is_low() || i > 0); bool consumed = intrsctn.is_low() ? intrsctn.consumed_vertical_up : seg.intersections[i-1].consumed_vertical_up; @@ -1104,11 +1100,11 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP bool going_up = intrsctn->is_low(); bool try_connect = false; if (going_up) { - myassert(! intrsctn->consumed_vertical_up); - myassert(i_intersection + 1 < seg.intersections.size()); + assert(! intrsctn->consumed_vertical_up); + assert(i_intersection + 1 < seg.intersections.size()); // Step back to the beginning of the vertical segment to mark it as consumed. if (intrsctn->is_inner()) { - myassert(i_intersection > 0); + assert(i_intersection > 0); -- intrsctn; -- i_intersection; } @@ -1117,25 +1113,25 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP intrsctn->consumed_vertical_up = true; ++ intrsctn; ++ i_intersection; - myassert(i_intersection < seg.intersections.size()); + assert(i_intersection < seg.intersections.size()); } while (intrsctn->type != SegmentIntersection::OUTER_HIGH); if ((intrsctn - 1)->is_inner()) { // Step back. -- intrsctn; -- i_intersection; - myassert(intrsctn->type == SegmentIntersection::INNER_HIGH); + assert(intrsctn->type == SegmentIntersection::INNER_HIGH); try_connect = true; } } else { // Going down. - myassert(intrsctn->is_high()); - myassert(i_intersection > 0); - myassert(! (intrsctn - 1)->consumed_vertical_up); + assert(intrsctn->is_high()); + assert(i_intersection > 0); + assert(! (intrsctn - 1)->consumed_vertical_up); // Consume the complete vertical segment up to the outer contour. if (intrsctn->is_inner()) intrsctn->consumed_vertical_up = true; do { - myassert(i_intersection > 0); + assert(i_intersection > 0); -- intrsctn; -- i_intersection; intrsctn->consumed_vertical_up = true; @@ -1144,7 +1140,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // Step back. ++ intrsctn; ++ i_intersection; - myassert(intrsctn->type == SegmentIntersection::INNER_LOW); + assert(intrsctn->type == SegmentIntersection::INNER_LOW); try_connect = true; } } @@ -1239,7 +1235,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP bool take_next = (intrsctn_type_prev == INTERSECTION_TYPE_OTHER_VLINE_OK && intrsctn_type_next == INTERSECTION_TYPE_OTHER_VLINE_OK) ? (distNext < distPrev) : intrsctn_type_next == INTERSECTION_TYPE_OTHER_VLINE_OK; - myassert(intrsctn->is_inner()); + assert(intrsctn->is_inner()); bool skip = params.dont_connect || (link_max_length > 0 && (take_next ? distNext : distPrev) > link_max_length); if (skip) { // Just skip the connecting contour and start a new path. @@ -1350,13 +1346,13 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // Finish the current vertical line, // reset the current vertical line to pick a new starting point in the next round. - myassert(intrsctn->is_outer()); - myassert(intrsctn->is_high() == going_up); + assert(intrsctn->is_outer()); + assert(intrsctn->is_high() == going_up); pointLast = Point(seg.pos, intrsctn->pos()); polyline_current->points.push_back(pointLast); // Handle duplicate points and zero length segments. polyline_current->remove_duplicate_points(); - myassert(! polyline_current->has_duplicate_points()); + assert(! polyline_current->has_duplicate_points()); // Handle nearly zero length edges. if (polyline_current->points.size() <= 1 || (polyline_current->points.size() == 2 && @@ -1388,17 +1384,17 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP for (Polylines::iterator it = polylines_out.begin() + n_polylines_out_initial; it != polylines_out.end(); ++ it) { // No need to translate, the absolute position is irrelevant. // it->translate(- rotate_vector.second.x, - rotate_vector.second.y); - myassert(! it->has_duplicate_points()); + assert(! it->has_duplicate_points()); it->rotate(rotate_vector.first); //FIXME rather simplify the paths to avoid very short edges? - //myassert(! it->has_duplicate_points()); + //assert(! it->has_duplicate_points()); it->remove_duplicate_points(); } #ifdef SLIC3R_DEBUG // Verify, that there are no duplicate points in the sequence. for (Polyline &polyline : polylines_out) - myassert(! polyline.has_duplicate_points()); + assert(! polyline.has_duplicate_points()); #endif /* SLIC3R_DEBUG */ return true; diff --git a/xs/src/libslic3r/Fill/FillRectilinear3.cpp b/xs/src/libslic3r/Fill/FillRectilinear3.cpp index b8b1c0b29..9101bd817 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear3.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear3.cpp @@ -15,23 +15,18 @@ #include "FillRectilinear3.hpp" -// #define SLIC3R_DEBUG + #define SLIC3R_DEBUG // Make assert active if SLIC3R_DEBUG #ifdef SLIC3R_DEBUG #undef NDEBUG + #define DEBUG + #define _DEBUG #include "SVG.hpp" #endif #include -// We want our version of assert. -#include "../libslic3r.h" - -#ifndef myassert -#define myassert assert -#endif - namespace Slic3r { namespace FillRectilinear3_Internal { @@ -55,9 +50,9 @@ public: // for the infill pattern, don't cut the corners. // default miterLimt = 3 //double mitterLimit = 10.; - myassert(aoffset1 < 0); - myassert(aoffset2 < 0); - myassert(aoffset2 < aoffset1); + assert(aoffset1 < 0); + assert(aoffset2 < 0); + assert(aoffset2 < aoffset1); // bool sticks_removed = remove_sticks(polygons_src); // if (sticks_removed) printf("Sticks removed!\n"); polygons_outer = offset(polygons_src, aoffset1, @@ -78,7 +73,7 @@ public: polygons_ccw.assign(n_contours, false); for (size_t i = 0; i < n_contours; ++ i) { contour(i).remove_duplicate_points(); - myassert(! contour(i).has_duplicate_points()); + assert(! contour(i).has_duplicate_points()); polygons_ccw[i] = Slic3r::Geometry::is_ccw(contour(i)); } } @@ -181,7 +176,8 @@ public: int ordering_along_line(const SegmentIntersection &other) const; // Compare two y intersection points given by rational numbers. - bool operator< (const SegmentIntersection &other) const { return this->ordering_along_line(other) == -1; } + bool operator< (const SegmentIntersection &other) const; + // { return this->ordering_along_line(other) == -1; } bool operator==(const SegmentIntersection &other) const { return this->ordering_along_line(other) == 0; } //FIXME legacy code, suporting the old graph traversal algorithm. Please remove. @@ -200,7 +196,7 @@ public: // Index of this vertical intersection line. size_t idx; // Position of the line along the X axis of the oriented bounding box. - coord_t x; +// coord_t x; // Position of this vertical intersection line, rotated to the world coordinate system. Point pos; // Direction of this vertical intersection line, rotated to the world coordinate system. The direction is not normalized to maintain a sufficient accuracy! @@ -218,8 +214,8 @@ Point SegmentIntersection::pos() const // Get the two rays to be intersected. const Polygon &poly = this->expoly_with_offset->contour(this->iContour); // 30 bits + 1 signum bit. - const Point &seg_start = poly.points[this->iSegment]; - const Point &seg_end = poly.points[(this->iSegment + 1) % poly.points.size()]; + const Point &seg_start = poly.points[(this->iSegment == 0) ? poly.points.size() - 1 : this->iSegment - 1]; + const Point &seg_end = poly.points[this->iSegment]; // Point, vector of the segment. const Pointf p1 = convert_to(seg_start); const Pointf v1 = convert_to(seg_end - seg_start); @@ -266,28 +262,35 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c // Segment of this const Polygon &poly_a = this->expoly_with_offset->contour(this->iContour); // 30 bits + 1 signum bit. - const Point &seg_start_a = poly_a.points[this->iSegment]; - const Point &seg_end_a = poly_a.points[(this->iSegment + 1) % poly_a.points.size()]; - const Point vec_a = seg_end_a - seg_start_a; + const Point &seg_start_a = poly_a.points[(this->iSegment == 0) ? poly_a.points.size() - 1 : this->iSegment - 1]; + const Point &seg_end_a = poly_a.points[this->iSegment]; // Segment of other const Polygon &poly_b = this->expoly_with_offset->contour(other.iContour); // 30 bits + 1 signum bit. - const Point &seg_start_b = poly_b.points[other.iSegment]; - const Point &seg_end_b = poly_b.points[(other.iSegment + 1) % poly_b.points.size()]; - const Point vec_b = seg_end_b - seg_start_b; + const Point &seg_start_b = poly_b.points[(other.iSegment == 0) ? poly_b.points.size() - 1 : other.iSegment - 1]; + const Point &seg_end_b = poly_b.points[other.iSegment]; if (this->iContour == other.iContour) { if ((this->iSegment + 1) % poly_a.points.size() == other.iSegment) { // other.iSegment succeeds this->iSegment + assert(seg_end_a == seg_start_b); + // Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point. + if (cross(this->line->dir, seg_end_b - this->line->pos) == 0) + return 0; } else if ((other.iSegment + 1) % poly_a.points.size() == this->iSegment) { // this->iSegment succeeds other.iSegment + assert(seg_start_a == seg_end_b); + // Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point. + if (cross(this->line->dir, seg_start_a - this->line->pos) == 0) + return 0; } else { // General case. } } // First test, whether both points of one segment are completely in one half-plane of the other line. + const Point vec_b = seg_end_b - seg_start_b; int side_start = signum(cross(vec_b, seg_start_a - seg_start_b)); int side_end = signum(cross(vec_b, seg_end_a - seg_start_b)); int side = side_start * side_end; @@ -295,31 +298,50 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c // This segment is completely inside one half-plane of the other line, therefore the ordering is trivial. return signum(cross(vec_b, this->line->dir)) * side_start; + const Point vec_a = seg_end_a - seg_start_a; int side_start2 = signum(cross(vec_a, seg_start_b - seg_start_a)); int side_end2 = signum(cross(vec_a, seg_end_b - seg_start_a)); int side2 = side_start2 * side_end2; + //if (side == 0 && side2 == 0) + // The segments share one of their end points. if (side2 > 0) // This segment is completely inside one half-plane of the other line, therefore the ordering is trivial. - return signum(cross(vec_a, this->line->dir)) * side_start2; - - if (side == 0 && side2 == 0) - // The segments share one of their end points. - return 0; + return signum(cross(this->line->dir, vec_a)) * side_start2; // The two segments intersect and they are not sucessive segments of the same contour. // Ordering of the points depends on the position of the segment intersection (left / right from this->line), // therefore a simple test over the input segment end points is not sufficient. // Find the parameters of intersection of the two segmetns with this->line. - int64_t denom1 = cross(vec_a, this->line->dir); - int64_t denom2 = cross(vec_b, this->line->dir); - int64_t t1_times_denom1 = int64_t(this->line->dir.x) * int64_t(seg_start_a.y - this->line->pos.y) - int64_t(this->line->dir.y) * int64_t(seg_start_a.x - this->line->pos.x); - int64_t t2_times_denom2 = int64_t(this->line->dir.x) * int64_t(seg_start_b.y - this->line->pos.y) - int64_t(this->line->dir.y) * int64_t(seg_start_b.x - this->line->pos.x); - assert(denom1 != 0); + int64_t denom1 = cross(this->line->dir, vec_a); + int64_t denom2 = cross(this->line->dir, vec_b); + Point vx_a = seg_start_a - this->line->pos; + Point vx_b = seg_start_b - this->line->pos; + int64_t t1_times_denom1 = int64_t(vx_a.x) * int64_t(vec_a.y) - int64_t(vx_a.y) * int64_t(vec_a.x); + int64_t t2_times_denom2 = int64_t(vx_b.x) * int64_t(vec_b.y) - int64_t(vx_b.y) * int64_t(vec_b.x); + assert(denom1 != 0); assert(denom2 != 0); return Int128::compare_rationals_filtered(t1_times_denom1, denom1, t2_times_denom2, denom2); } +// Compare two y intersection points given by rational numbers. +bool SegmentIntersection::operator<(const SegmentIntersection &other) const +{ +#ifdef _DEBUG + Point p1 = this->pos(); + Point p2 = other.pos(); + int64_t d = dot(this->line->dir, p2 - p1); +#endif /* _DEBUG */ + int ordering = this->ordering_along_line(other); +#ifdef _DEBUG + if (ordering == -1) + assert(d >= - int64_t(SCALED_EPSILON)); + else if (ordering == 1) + assert(d <= int64_t(SCALED_EPSILON)); +#endif /* _DEBUG */ + return ordering == -1; +} + // When doing a rectilinear / grid / triangle / stars / cubic infill, // the following class holds the hatching lines of each of the hatching directions. class InfillHatchingSingleDirection @@ -353,12 +375,12 @@ static bool prepare_infill_hatching_segments( InfillHatchingSingleDirection &out) { out.angle = rotate_vector.first + fill_dir_params.angle; - out.direction = Point(1000, 0); + out.direction = Point(coord_t(scale_(1000)), coord_t(0)); // Hatch along the Y axis of the rotated coordinate system. out.direction.rotate(out.angle + 0.5 * M_PI); out.segs.clear(); - myassert(params.density > 0.0001f && params.density <= 1.f); + assert(params.density > 0.0001f && params.density <= 1.f); coord_t line_spacing = coord_t(scale_(fill_dir_params.spacing) / params.density); // Bounding box around the source contour, aligned with out.angle. @@ -409,18 +431,18 @@ static bool prepare_infill_hatching_segments( // For each contour // Allocate storage for the segments. out.segs.assign(n_vlines, SegmentedIntersectionLine()); + double cos_a = cos(out.angle); + double sin_a = sin(out.angle); for (size_t i = 0; i < n_vlines; ++ i) { auto &seg = out.segs[i]; seg.idx = i; - seg.x = x0 + coord_t(i) * line_spacing; - seg.pos = Point(seg.x, bounding_box.min.y); - seg.pos.rotate(out.angle); + // seg.x = x0 + coord_t(i) * line_spacing; + coord_t x = x0 + coord_t(i) * line_spacing; + seg.pos.x = coord_t(floor(cos_a * x - sin_a * bounding_box.min.y + 0.5)); + seg.pos.y = coord_t(floor(cos_a * bounding_box.min.y + sin_a * x + 0.5)); seg.dir = out.direction; } - #if 1 - double cos_a = cos(- out.angle); - double sin_a = sin(- out.angle); for (size_t iContour = 0; iContour < poly_with_offset.n_contours; ++ iContour) { const Points &contour = poly_with_offset.contour(iContour).points; if (contour.size() < 2) @@ -440,60 +462,58 @@ static bool prepare_infill_hatching_segments( // Always orient the input segment consistently towards the hatching direction. std::swap(pl, pr); // Which of the equally spaced vertical lines is intersected by this segment? - coord_t l = (coord_t)floor(cos_a * pl->x - sin_a * pl->y - EPSILON); - coord_t r = (coord_t)ceil (cos_a * pr->x - sin_a * pr->y + EPSILON); + coord_t l = (coord_t)floor(cos_a * pl->x + sin_a * pl->y - SCALED_EPSILON); + coord_t r = (coord_t)ceil (cos_a * pr->x + sin_a * pr->y + SCALED_EPSILON); + assert(l < r - SCALED_EPSILON); // il, ir are the left / right indices of vertical lines intersecting a segment - int il = (l - x0) / line_spacing; - il = std::max(int(0), il); - while (il * line_spacing + x0 < l) - ++ il; - int ir = (r - x0 + line_spacing) / line_spacing; - while (ir * line_spacing + x0 > r) - -- ir; - ir = std::min(int(out.segs.size()) - 1, ir); - if (il > ir) - // No vertical line intersects this segment. - continue; + int il = std::max(0, (l - x0 + line_spacing) / line_spacing); + int ir = std::min(int(out.segs.size()) - 1, (r - x0) / line_spacing); // The previous tests were done with floating point arithmetics over an epsilon-extended interval. // Now do the same tests with exact arithmetics over the exact interval. while (il <= ir && Int128::orient(out.segs[il].pos, out.segs[il].pos + out.direction, *pl) < 0) ++ il; while (il <= ir && Int128::orient(out.segs[ir].pos, out.segs[ir].pos + out.direction, *pr) > 0) -- ir; - if (il > ir) - // No vertical line intersects this segment. - continue; // Here it is ensured, that // 1) out.seg is not parallel to (pl, pr) // 2) all lines from il to ir intersect . - myassert(il >= 0 && il < out.segs.size()); - myassert(ir >= 0 && ir < out.segs.size()); + assert(il >= 0 && ir < int(out.segs.size())); for (int i = il; i <= ir; ++ i) { - myassert(out.segs[i].x == i * line_spacing + x0); - myassert(l <= out.segs[i].x); - myassert(r >= out.segs[i].x); + // assert(out.segs[i].x == i * line_spacing + x0); + // assert(l <= out.segs[i].x); + // assert(r >= out.segs[i].x); SegmentIntersection is; is.line = &out.segs[i]; is.expoly_with_offset = &poly_with_offset; is.iContour = iContour; - is.iSegment = iSegment; + is.iSegment = iSegment; // Test whether the calculated intersection point falls into the bounding box of the input segment. // +-1 to take rounding into account. - myassert(is.pos().x + 1 >= std::min(pl->x, pr->x)); - myassert(is.pos().y + 1 >= std::min(pl->y, pr->y)); - myassert(is.pos().x <= std::max(pl->x, pr->x) + 1); - myassert(is.pos().y <= std::max(pl->y, pr->y) + 1); + assert(Int128::orient(out.segs[i].pos, out.segs[i].pos + out.direction, *pl) >= 0); + assert(Int128::orient(out.segs[i].pos, out.segs[i].pos + out.direction, *pr) <= 0); + assert(is.pos().x + 1 >= std::min(pl->x, pr->x)); + assert(is.pos().y + 1 >= std::min(pl->y, pr->y)); + assert(is.pos().x <= std::max(pl->x, pr->x) + 1); + assert(is.pos().y <= std::max(pl->y, pr->y) + 1); out.segs[i].intersections.push_back(is); } } } - #endif // Sort the intersections along their segments, specify the intersection types. for (size_t i_seg = 0; i_seg < out.segs.size(); ++ i_seg) { SegmentedIntersectionLine &sil = out.segs[i_seg]; // Sort the intersection points using exact rational arithmetic. std::sort(sil.intersections.begin(), sil.intersections.end()); +#ifdef _DEBUG + // Verify that the intersections are sorted along the haching direction. + for (size_t i = 1; i < sil.intersections.size(); ++ i) { + Point p1 = sil.intersections[i - 1].pos(); + Point p2 = sil.intersections[i].pos(); + int64_t d = dot(sil.dir, p2 - p1); + assert(d >= - int64_t(SCALED_EPSILON)); + } +#endif /* _DEBUG */ // Assign the intersection types, remove duplicate or overlapping intersection points. // When a loop vertex touches a vertical line, intersection point is generated for both segments. // If such two segments are oriented equally, then one of them is removed. @@ -507,7 +527,7 @@ static bool prepare_infill_hatching_segments( const Points &contour = poly_with_offset.contour(iContour).points; size_t iSegment = sil.intersections[i].iSegment; size_t iPrev = ((iSegment == 0) ? contour.size() : iSegment) - 1; - coord_t dir = contour[iSegment].x - contour[iPrev].x; + int dir = Int128::cross(contour[iSegment] - contour[iPrev], sil.dir); bool low = dir > 0; sil.intersections[i].type = poly_with_offset.is_contour_outer(iContour) ? (low ? SegmentIntersection::OUTER_LOW : SegmentIntersection::OUTER_HIGH) : @@ -520,7 +540,7 @@ static bool prepare_infill_hatching_segments( // Verify that the segments of sil.intersections[i] and sil.intersections[j-1] are adjoint. size_t iSegment2 = sil.intersections[j-1].iSegment; size_t iPrev2 = ((iSegment2 == 0) ? contour.size() : iSegment2) - 1; - myassert(iSegment == iPrev2 || iSegment2 == iPrev); + assert(iSegment == iPrev2 || iSegment2 == iPrev); #endif /* SLIC3R_DEBUG */ if (sil.intersections[i].type == sil.intersections[j-1].type) { // Two successive segments of the same direction (both to the right or both to the left) @@ -643,8 +663,8 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po std::swap(pa.x, pb.x); if (pa.y > pb.y) std::swap(pa.y, pb.y); - myassert(px.x >= pa.x && px.x <= pb.x); - myassert(px.y >= pa.y && px.y <= pb.y); + assert(px.x >= pa.x && px.x <= pb.x); + assert(px.y >= pa.y && px.y <= pb.y); } #endif /* SLIC3R_DEBUG */ const Point *pPrev = &p1; @@ -750,23 +770,23 @@ static inline int intersection_on_prev_next_vertical_line( if (itsct.iContour == itsct2.iContour && itsct.type == itsct2.type) { /* if (itsct.is_low()) { - myassert(itsct.type == SegmentIntersection::INNER_LOW); - myassert(iIntersection > 0); - myassert(il.intersections[iIntersection-1].type == SegmentIntersection::OUTER_LOW); - myassert(i > 0); + assert(itsct.type == SegmentIntersection::INNER_LOW); + assert(iIntersection > 0); + assert(il.intersections[iIntersection-1].type == SegmentIntersection::OUTER_LOW); + assert(i > 0); if (il2.intersections[i-1].is_inner()) // Take only the lowest inner intersection point. continue; - myassert(il2.intersections[i-1].type == SegmentIntersection::OUTER_LOW); + assert(il2.intersections[i-1].type == SegmentIntersection::OUTER_LOW); } else { - myassert(itsct.type == SegmentIntersection::INNER_HIGH); - myassert(iIntersection+1 < il.intersections.size()); - myassert(il.intersections[iIntersection+1].type == SegmentIntersection::OUTER_HIGH); - myassert(i+1 < il2.intersections.size()); + assert(itsct.type == SegmentIntersection::INNER_HIGH); + assert(iIntersection+1 < il.intersections.size()); + assert(il.intersections[iIntersection+1].type == SegmentIntersection::OUTER_HIGH); + assert(i+1 < il2.intersections.size()); if (il2.intersections[i+1].is_inner()) // Take only the highest inner intersection point. continue; - myassert(il2.intersections[i+1].type == SegmentIntersection::OUTER_HIGH); + assert(il2.intersections[i+1].type == SegmentIntersection::OUTER_HIGH); } */ // The intersection points lie on the same contour and have the same orientation. @@ -831,21 +851,21 @@ static inline IntersectionTypeOtherVLine intersection_type_on_prev_next_vertical // iVertical line multiple times before reaching iIntersectionOther. if (iIntersectionOther == -1) return INTERSECTION_TYPE_OTHER_VLINE_UNDEFINED; - myassert(dir_is_next ? (iVerticalLine + 1 < segs.size()) : (iVerticalLine > 0)); + assert(dir_is_next ? (iVerticalLine + 1 < segs.size()) : (iVerticalLine > 0)); const SegmentedIntersectionLine &il_this = segs[iVerticalLine]; const SegmentIntersection &itsct_this = il_this.intersections[iIntersection]; const SegmentedIntersectionLine &il_other = segs[dir_is_next ? (iVerticalLine+1) : (iVerticalLine-1)]; const SegmentIntersection &itsct_other = il_other.intersections[iIntersectionOther]; - myassert(itsct_other.is_inner()); - myassert(iIntersectionOther > 0); - myassert(iIntersectionOther + 1 < il_other.intersections.size()); + assert(itsct_other.is_inner()); + assert(iIntersectionOther > 0); + assert(iIntersectionOther + 1 < il_other.intersections.size()); // Is iIntersectionOther at the boundary of a vertical segment? const SegmentIntersection &itsct_other2 = il_other.intersections[itsct_other.is_low() ? iIntersectionOther - 1 : iIntersectionOther + 1]; if (itsct_other2.is_inner()) // Cannot follow a perimeter segment into the middle of another vertical segment. // Only perimeter segments connecting to the end of a vertical segment are followed. return INTERSECTION_TYPE_OTHER_VLINE_INNER; - myassert(itsct_other.is_low() == itsct_other2.is_low()); + assert(itsct_other.is_low() == itsct_other2.is_low()); if (dir_is_next ? itsct_this.consumed_perimeter_right : itsct_other.consumed_perimeter_right) // This perimeter segment was already consumed. return INTERSECTION_TYPE_OTHER_VLINE_CONSUMED; @@ -899,9 +919,9 @@ static inline coordf_t measure_perimeter_prev_next_segment_length( const SegmentIntersection &itsct2 = il2.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour(iInnerContour); // const bool ccw = poly_with_offset.is_contour_ccw(iInnerContour); - myassert(itsct.type == itsct2.type); - myassert(itsct.iContour == itsct2.iContour); - myassert(itsct.is_inner()); + assert(itsct.type == itsct2.type); + assert(itsct.iContour == itsct2.iContour); + assert(itsct.is_inner()); const bool forward = itsct.is_low() == dir_is_next; Point p1 = itsct.pos(); @@ -949,9 +969,9 @@ static inline void emit_perimeter_prev_next_segment( size_t iVerticalLineOther = iVerticalLine; if (dir_is_next) { ++ iVerticalLineOther; - myassert(iVerticalLineOther < segs.size()); + assert(iVerticalLineOther < segs.size()); } else { - myassert(iVerticalLineOther > 0); + assert(iVerticalLineOther > 0); -- iVerticalLineOther; } @@ -961,9 +981,9 @@ static inline void emit_perimeter_prev_next_segment( const SegmentIntersection &itsct2 = il2.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour(iInnerContour); // const bool ccw = poly_with_offset.is_contour_ccw(iInnerContour); - myassert(itsct.type == itsct2.type); - myassert(itsct.iContour == itsct2.iContour); - myassert(itsct.is_inner()); + assert(itsct.type == itsct2.type); + assert(itsct.iContour == itsct2.iContour); + assert(itsct.is_inner()); const bool forward = itsct.is_low() == dir_is_next; // Do not append the first point. // out.points.push_back(Point(il.pos, itsct.pos)); @@ -988,11 +1008,11 @@ static inline coordf_t measure_perimeter_segment_on_vertical_line_length( const SegmentIntersection &itsct = il.intersections[iIntersection]; const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour(iInnerContour); - myassert(itsct.is_inner()); - myassert(itsct2.is_inner()); - myassert(itsct.type != itsct2.type); - myassert(itsct.iContour == iInnerContour); - myassert(itsct.iContour == itsct2.iContour); + assert(itsct.is_inner()); + assert(itsct2.is_inner()); + assert(itsct.type != itsct2.type); + assert(itsct.iContour == iInnerContour); + assert(itsct.iContour == itsct2.iContour); return forward ? segment_length(poly, itsct .iSegment, itsct.pos(), itsct2.iSegment, itsct2.pos()) : segment_length(poly, itsct2.iSegment, itsct2.pos(), itsct .iSegment, itsct.pos()); @@ -1015,11 +1035,11 @@ static inline void emit_perimeter_segment_on_vertical_line( const SegmentIntersection &itsct = il.intersections[iIntersection]; const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour(iInnerContour); - myassert(itsct.is_inner()); - myassert(itsct2.is_inner()); - myassert(itsct.type != itsct2.type); - myassert(itsct.iContour == iInnerContour); - myassert(itsct.iContour == itsct2.iContour); + assert(itsct.is_inner()); + assert(itsct2.is_inner()); + assert(itsct.type != itsct2.type); + assert(itsct.iContour == iInnerContour); + assert(itsct.iContour == itsct2.iContour); // Do not append the first point. // out.points.push_back(Point(il.pos, itsct.pos)); if (forward) @@ -1042,10 +1062,10 @@ static inline float measure_outer_contour_slab( const SegmentIntersection &itsct = il.intersections[i_vline]; const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; const Polygon &poly = poly_with_offset.contour((itsct.iContour); - myassert(itsct.is_outer()); - myassert(itsct2.is_outer()); - myassert(itsct.type != itsct2.type); - myassert(itsct.iContour == itsct2.iContour); + assert(itsct.is_outer()); + assert(itsct2.is_outer()); + assert(itsct.type != itsct2.type); + assert(itsct.iContour == itsct2.iContour); if (! itsct.is_outer() || ! itsct2.is_outer() || itsct.type == itsct2.type || itsct.iContour != itsct2.iContour) // Error, return zero area. return 0.f; @@ -1159,14 +1179,14 @@ static bool fill_hatching_segments_legacy( for (size_t i_vline2 = 0; i_vline2 < segs.size(); ++ i_vline2) { const SegmentedIntersectionLine &seg = segs[i_vline2]; if (! seg.intersections.empty()) { - myassert(seg.intersections.size() > 1); + assert(seg.intersections.size() > 1); // Even number of intersections with the loops. - myassert((seg.intersections.size() & 1) == 0); - myassert(seg.intersections.front().type == SegmentIntersection::OUTER_LOW); + assert((seg.intersections.size() & 1) == 0); + assert(seg.intersections.front().type == SegmentIntersection::OUTER_LOW); for (size_t i = 0; i < seg.intersections.size(); ++ i) { const SegmentIntersection &intrsctn = seg.intersections[i]; if (intrsctn.is_outer()) { - myassert(intrsctn.is_low() || i > 0); + assert(intrsctn.is_low() || i > 0); bool consumed = intrsctn.is_low() ? intrsctn.consumed_vertical_up : seg.intersections[i-1].consumed_vertical_up; @@ -1205,11 +1225,11 @@ static bool fill_hatching_segments_legacy( bool going_up = intrsctn->is_low(); bool try_connect = false; if (going_up) { - myassert(! intrsctn->consumed_vertical_up); - myassert(i_intersection + 1 < seg.intersections.size()); + assert(! intrsctn->consumed_vertical_up); + assert(i_intersection + 1 < seg.intersections.size()); // Step back to the beginning of the vertical segment to mark it as consumed. if (intrsctn->is_inner()) { - myassert(i_intersection > 0); + assert(i_intersection > 0); -- intrsctn; -- i_intersection; } @@ -1218,25 +1238,25 @@ static bool fill_hatching_segments_legacy( intrsctn->consumed_vertical_up = true; ++ intrsctn; ++ i_intersection; - myassert(i_intersection < seg.intersections.size()); + assert(i_intersection < seg.intersections.size()); } while (intrsctn->type != SegmentIntersection::OUTER_HIGH); if ((intrsctn - 1)->is_inner()) { // Step back. -- intrsctn; -- i_intersection; - myassert(intrsctn->type == SegmentIntersection::INNER_HIGH); + assert(intrsctn->type == SegmentIntersection::INNER_HIGH); try_connect = true; } } else { // Going down. - myassert(intrsctn->is_high()); - myassert(i_intersection > 0); - myassert(! (intrsctn - 1)->consumed_vertical_up); + assert(intrsctn->is_high()); + assert(i_intersection > 0); + assert(! (intrsctn - 1)->consumed_vertical_up); // Consume the complete vertical segment up to the outer contour. if (intrsctn->is_inner()) intrsctn->consumed_vertical_up = true; do { - myassert(i_intersection > 0); + assert(i_intersection > 0); -- intrsctn; -- i_intersection; intrsctn->consumed_vertical_up = true; @@ -1245,7 +1265,7 @@ static bool fill_hatching_segments_legacy( // Step back. ++ intrsctn; ++ i_intersection; - myassert(intrsctn->type == SegmentIntersection::INNER_LOW); + assert(intrsctn->type == SegmentIntersection::INNER_LOW); try_connect = true; } } @@ -1340,7 +1360,7 @@ static bool fill_hatching_segments_legacy( bool take_next = (intrsctn_type_prev == INTERSECTION_TYPE_OTHER_VLINE_OK && intrsctn_type_next == INTERSECTION_TYPE_OTHER_VLINE_OK) ? (distNext < distPrev) : intrsctn_type_next == INTERSECTION_TYPE_OTHER_VLINE_OK; - myassert(intrsctn->is_inner()); + assert(intrsctn->is_inner()); bool skip = params.dont_connect || (link_max_length > 0 && (take_next ? distNext : distPrev) > link_max_length); if (skip) { // Just skip the connecting contour and start a new path. @@ -1451,13 +1471,13 @@ static bool fill_hatching_segments_legacy( // Finish the current vertical line, // reset the current vertical line to pick a new starting point in the next round. - myassert(intrsctn->is_outer()); - myassert(intrsctn->is_high() == going_up); + assert(intrsctn->is_outer()); + assert(intrsctn->is_high() == going_up); pointLast = intrsctn->pos(); polyline_current->points.push_back(pointLast); // Handle duplicate points and zero length segments. polyline_current->remove_duplicate_points(); - myassert(! polyline_current->has_duplicate_points()); + assert(! polyline_current->has_duplicate_points()); // Handle nearly zero length edges. if (polyline_current->points.size() <= 1 || (polyline_current->points.size() == 2 && @@ -1491,17 +1511,17 @@ static bool fill_hatching_segments_legacy( for (Polylines::iterator it = polylines_out.begin() + n_polylines_out_initial; it != polylines_out.end(); ++ it) { // No need to translate, the absolute position is irrelevant. // it->translate(- rotate_vector.second.x, - rotate_vector.second.y); - myassert(! it->has_duplicate_points()); + assert(! it->has_duplicate_points()); //it->rotate(rotate_vector.first); //FIXME rather simplify the paths to avoid very short edges? - //myassert(! it->has_duplicate_points()); + //assert(! it->has_duplicate_points()); it->remove_duplicate_points(); } #ifdef SLIC3R_DEBUG // Verify, that there are no duplicate points in the sequence. for (Polyline &polyline : polylines_out) - myassert(! polyline.has_duplicate_points()); + assert(! polyline.has_duplicate_points()); #endif /* SLIC3R_DEBUG */ return true; @@ -1511,10 +1531,10 @@ static bool fill_hatching_segments_legacy( bool FillRectilinear3::fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, std::vector &fill_dir_params, Polylines &polylines_out) { - myassert(params.density > 0.0001f && params.density <= 1.f); + assert(params.density > 0.0001f && params.density <= 1.f); const float INFILL_OVERLAP_OVER_SPACING = 0.45f; - myassert(INFILL_OVERLAP_OVER_SPACING > 0 && INFILL_OVERLAP_OVER_SPACING < 0.5f); + assert(INFILL_OVERLAP_OVER_SPACING > 0 && INFILL_OVERLAP_OVER_SPACING < 0.5f); // On the polygons of poly_with_offset, the infill lines will be connected. FillRectilinear3_Internal::ExPolygonWithOffset poly_with_offset( diff --git a/xs/src/libslic3r/Fill/FillRectilinear3.hpp b/xs/src/libslic3r/Fill/FillRectilinear3.hpp index 5434c1ff6..2023a25b7 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear3.hpp +++ b/xs/src/libslic3r/Fill/FillRectilinear3.hpp @@ -1,5 +1,5 @@ -#ifndef slic3r_FillRectilinear2_hpp_ -#define slic3r_FillRectilinear2_hpp_ +#ifndef slic3r_FillRectilinear3_hpp_ +#define slic3r_FillRectilinear3_hpp_ #include "../libslic3r.h" @@ -80,4 +80,4 @@ protected: }; // namespace Slic3r -#endif // slic3r_FillRectilinear2_hpp_ +#endif // slic3r_FillRectilinear3_hpp_ diff --git a/xs/src/libslic3r/Int128.hpp b/xs/src/libslic3r/Int128.hpp index 7dcfed70d..e911a6e80 100644 --- a/xs/src/libslic3r/Int128.hpp +++ b/xs/src/libslic3r/Int128.hpp @@ -286,7 +286,7 @@ public: if (std::abs(det) > err) return ((det > 0) ? 1 : -1) * invert; } - return sign_determinant_2x2(p1, q1, p2, q2); + return sign_determinant_2x2(p1, q1, p2, q2) * invert; } // Exact orientation predicate, @@ -297,4 +297,11 @@ public: Slic3r::Vector v2(p3 - p1); return sign_determinant_2x2_filtered(v1.x, v1.y, v2.x, v2.y); } + + // Exact orientation predicate, + // returns +1: CCW, 0: collinear, -1: CW. + static int cross(const Slic3r::Point &v1, const Slic3r::Point &v2) + { + return sign_determinant_2x2_filtered(v1.x, v1.y, v2.x, v2.y); + } }; diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp index 977af2b67..f2d3a6e65 100644 --- a/xs/src/libslic3r/Point.hpp +++ b/xs/src/libslic3r/Point.hpp @@ -79,6 +79,7 @@ inline Point operator+(const Point& point1, const Point& point2) { return Point( inline Point operator-(const Point& point1, const Point& point2) { return Point(point1.x - point2.x, point1.y - point2.y); } inline Point operator*(double scalar, const Point& point2) { return Point(scalar * point2.x, scalar * point2.y); } inline int64_t cross(const Point &v1, const Point &v2) { return int64_t(v1.x) * int64_t(v2.y) - int64_t(v1.y) * int64_t(v2.x); } +inline int64_t dot(const Point &v1, const Point &v2) { return int64_t(v1.x) * int64_t(v2.x) + int64_t(v1.y) * int64_t(v2.y); } // To be used by std::unordered_map, std::unordered_multimap and friends. struct PointHash {