Skip to content

Commit

Permalink
Changed the logic of the "ensure vertical wall thickness" feature
Browse files Browse the repository at this point in the history
slightly by inflating the projected top/bottom/bottom bridge surfaces
before they are added into a surface. This ensures, that the possible
projected infill areas merge with the perimeter supporting areas,
but the perimeter supporting areas will not be inflated on their own,
if there is no touching projection of a top/bottom/bottom bridge
surface.
  • Loading branch information
bubnikv committed Nov 11, 2016
1 parent 4460b5c commit c2d5b32
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 13 deletions.
4 changes: 2 additions & 2 deletions xs/src/libslic3r/Fill/FillBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
assert(width >= 0);
assert(distance > 0);
// floor(width / distance)
coord_t number_of_intervals = width / distance;
coord_t number_of_intervals = (width - EPSILON) / distance;
coord_t distance_new = (number_of_intervals == 0) ?
distance :
(width / number_of_intervals);
((width - EPSILON) / number_of_intervals);
const coordf_t factor = coordf_t(distance_new) / coordf_t(distance);
assert(factor > 1. - 1e-5);
// How much could the extrusion width be increased? By 20%.
Expand Down
87 changes: 81 additions & 6 deletions xs/src/libslic3r/Fill/FillRectilinear2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,74 @@ static inline void emit_perimeter_segment_on_vertical_line(
out.points.push_back(Point(il.pos, itsct2.pos()));
}

//TBD: For precise infill, measure the area of a slab spanned by an infill line.
/*
static inline float measure_outer_contour_slab(
const ExPolygonWithOffset &poly_with_offset,
const std::vector<SegmentedIntersectionLine> &segs,
size_t i_vline,
size_t iIntersection)
{
const SegmentedIntersectionLine &il = segs[i_vline];
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);
if (! itsct.is_outer() || ! itsct2.is_outer() || itsct.type == itsct2.type || itsct.iContour != itsct2.iContour)
// Error, return zero area.
return 0.f;
// Find possible connection points on the previous / next vertical line.
int iPrev = intersection_on_prev_vertical_line(poly_with_offset, segs, i_vline, itsct.iContour, i_intersection);
int iNext = intersection_on_next_vertical_line(poly_with_offset, segs, i_vline, itsct.iContour, i_intersection);
// Find possible connection points on the same vertical line.
int iAbove = iBelow = -1;
// Does the perimeter intersect the current vertical line above intrsctn?
for (size_t i = i_intersection + 1; i + 1 < seg.intersections.size(); ++ i)
if (seg.intersections[i].iContour == itsct.iContour)
{ iAbove = i; break; }
// Does the perimeter intersect the current vertical line below intrsctn?
for (int i = int(i_intersection) - 1; i > 0; -- i)
if (seg.intersections[i].iContour == itsct.iContour)
{ iBelow = i; break; }
if (iSegAbove != -1 && seg.intersections[iAbove].type == SegmentIntersection::OUTER_HIGH) {
// Invalidate iPrev resp. iNext, if the perimeter crosses the current vertical line earlier than iPrev resp. iNext.
// The perimeter contour orientation.
const Polygon &poly = poly_with_offset.contour(itsct.iContour);
{
int d_horiz = (iPrev == -1) ? std::numeric_limits<int>::max() :
distance_of_segmens(poly, segs[i_vline-1].intersections[iPrev].iSegment, itsct.iSegment, true);
int d_down = (iBelow == -1) ? std::numeric_limits<int>::max() :
distance_of_segmens(poly, iSegBelow, itsct.iSegment, true);
int d_up = (iAbove == -1) ? std::numeric_limits<int>::max() :
distance_of_segmens(poly, iSegAbove, itsct.iSegment, true);
if (intrsctn_type_prev == INTERSECTION_TYPE_OTHER_VLINE_OK && d_horiz > std::min(d_down, d_up))
// The vertical crossing comes eralier than the prev crossing.
// Disable the perimeter going back.
intrsctn_type_prev = INTERSECTION_TYPE_OTHER_VLINE_NOT_FIRST;
if (d_up > std::min(d_horiz, d_down))
// The horizontal crossing comes earlier than the vertical crossing.
vert_seg_dir_valid_mask &= ~DIR_BACKWARD;
}
{
int d_horiz = (iNext == -1) ? std::numeric_limits<int>::max() :
distance_of_segmens(poly, itsct.iSegment, segs[i_vline+1].intersections[iNext].iSegment, true);
int d_down = (iSegBelow == -1) ? std::numeric_limits<int>::max() :
distance_of_segmens(poly, itsct.iSegment, iSegBelow, true);
int d_up = (iSegAbove == -1) ? std::numeric_limits<int>::max() :
distance_of_segmens(poly, itsct.iSegment, iSegAbove, true);
if (d_up > std::min(d_horiz, d_down))
// The horizontal crossing comes earlier than the vertical crossing.
vert_seg_dir_valid_mask &= ~DIR_FORWARD;
}
}
}
*/

enum DirectionMask
{
DIR_FORWARD = 1,
Expand Down Expand Up @@ -826,7 +894,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
// Intersect a set of euqally spaced vertical lines wiht expolygon.
// n_vlines = ceil(bbox_width / line_spacing)
size_t n_vlines = (bounding_box.max.x - bounding_box.min.x + line_spacing - 1) / line_spacing;
coord_t x0 = bounding_box.min.x + line_spacing / 2;
coord_t x0 = bounding_box.min.x + (line_spacing + SCALED_EPSILON) / 2;

#ifdef SLIC3R_DEBUG
static int iRun = 0;
Expand Down Expand Up @@ -1111,13 +1179,20 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
svg.Close();
#endif /* SLIC3R_DEBUG */

// Mark an outer only chord as consumed, so there will be no tiny pieces emitted.
// For each outer only chords, measure their maximum distance to the bow of the outer contour.
// Mark an outer only chord as consumed, if the distance is low.
for (size_t i_vline = 0; i_vline < segs.size(); ++ i_vline) {
SegmentedIntersectionLine &seg = segs[i_vline];
for (size_t i = 0; i + 1 < seg.intersections.size(); ++ i) {
if (seg.intersections[i].type == SegmentIntersection::OUTER_LOW &&
seg.intersections[i+1].type == SegmentIntersection::OUTER_HIGH)
seg.intersections[i].consumed_vertical_up = true;
for (size_t i_intersection = 0; i_intersection + 1 < seg.intersections.size(); ++ i_intersection) {
if (seg.intersections[i_intersection].type == SegmentIntersection::OUTER_LOW &&
seg.intersections[i_intersection+1].type == SegmentIntersection::OUTER_HIGH) {
bool consumed = false;
// if (full_infill) {
// measure_outer_contour_slab(poly_with_offset, segs, i_vline, i_ntersection);
// } else
consumed = true;
seg.intersections[i_intersection].consumed_vertical_up = consumed;
}
}
}

Expand Down
10 changes: 5 additions & 5 deletions xs/src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ PrintObject::discover_vertical_shells()
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
ExPolygons shell_ex;
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
float min_perimeter_infill_spacing = float(infill_line_spacing) * 1.05f;
if (1)
{
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
Expand Down Expand Up @@ -531,13 +532,13 @@ PrintObject::discover_vertical_shells()
polygons_append(shell, neighbor_layer.perimeter_expolygons.expolygons);
if (n > int(idx_layer)) {
// Collect top surfaces.
polygons_append(shell, to_polygons(neighbor_region.slices.filter_by_type(stTop)));
polygons_append(shell, to_polygons(neighbor_region.fill_surfaces.filter_by_type(stTop)));
polygons_append(shell, offset(to_expolygons(neighbor_region.slices.filter_by_type(stTop)), min_perimeter_infill_spacing));
polygons_append(shell, offset(to_expolygons(neighbor_region.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing));
}
else if (n < int(idx_layer)) {
// Collect bottom and bottom bridge surfaces.
polygons_append(shell, to_polygons(neighbor_region.slices.filter_by_types(surfaces_bottom, 2)));
polygons_append(shell, to_polygons(neighbor_region.fill_surfaces.filter_by_types(surfaces_bottom, 2)));
polygons_append(shell, offset(to_expolygons(neighbor_region.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
polygons_append(shell, offset(to_expolygons(neighbor_region.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
}
}
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
Expand Down Expand Up @@ -615,7 +616,6 @@ PrintObject::discover_vertical_shells()
Polygons shell_before = shell;
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
#if 1
float min_perimeter_infill_spacing = float(infill_line_spacing) * 1.05f;
// Intentionally inflate a bit more than how much the region has been shrunk,
// so there will be some overlap between this solid infill and the other infill regions (mainly the sparse infill).
shell = offset2(shell, - 0.5f * min_perimeter_infill_spacing, 0.8f * min_perimeter_infill_spacing,
Expand Down
9 changes: 9 additions & 0 deletions xs/src/libslic3r/Surface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ inline Polygons to_polygons(const SurfacesPtr &src)
return polygons;
}

inline ExPolygons to_expolygons(const SurfacesPtr &src)
{
ExPolygons expolygons;
expolygons.reserve(src.size());
for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++it)
expolygons.push_back((*it)->expolygon);
return expolygons;
}

// Count a nuber of polygons stored inside the vector of expolygons.
// Useful for allocating space for polygons when converting expolygons to polygons.
inline size_t number_polygons(const Surfaces &surfaces)
Expand Down

0 comments on commit c2d5b32

Please sign in to comment.