Cura: [3.6.0] Inefficient small gap filling between walls

Created on 24 Nov 2018  Â·  30Comments  Â·  Source: Ultimaker/Cura

Application Version
3.6.0

Platform
MacOS Mojave

Printer
Creality CR-10 with defaults (the printer doesn't seem to matter, it happened with an Ender 3 Pro, too.

Steps to Reproduce
Slice a part that has a 2mm thick solid wall using a 0.4mm nozzle and 0.4mm wall thickness. Set wall-count to 2.

Actual Results
The whole part is 5 walls thick. That leaves 0.4mm in the middle, which should be filled with a single extruded line. In 3.5.1 this works as expected, but in 3.6.0 the gap is filled with a diagonal pattern instead, which leads to longer print times (and potentially less strength in the resulting part).

Additionally, parts that are 1.2mm / 3 lines wide get the same infill instead of a proper wall. If I change the line width to 0.399mm, then those get a single inner wall line inside, but the inside of a 5 line wide wall will still stay the same. Reducing the line width to 0.39mm causes the inside of the 5 line wide wall to become empty / standard infill pattern, like it wasn't considered a "gap" to be filled anymore.

Turning off "Fill Gaps Between Walls" leaves the whole space unfilled in either case.

Expected results
See above, like in 3.5.1 the gap should be filled with a single extrusion.

Additional Information

This is how it looks in 3.6.0. Note how the part on the left hand side and the left wall of the lower two have a diagonal filling.

cura 3 6 0

This is how it looks with the width set to 3.99mm. Both lower walls now have a single line inside, but the left wall still doesn't.
cura 3 6 0 reduced width

This is how it looks in 3.5.1 (3.4.1 too), which makes me believe that this is a regression.
cura 3 5 1

Edit: Here is the STL file that I used, please let me know if you need the Fusion 360 model, too.

Element.stl.zip

Most helpful comment

Capture2
Capture

Just adding some context since it appears this issue is still causing some problems. The pic with the infill inside the thin wall is Cura and the other is from Slic3r. With Slic3r I can almost set wall count or width to anything except 1 and it will fill the thin wall with a line. In Cura no matter what I did, I could not get it to fill with a line.

All 30 comments

Hello @lekv , I have recently developed a new implementation of the wall gap filling that should work much more like you expect. If you wish to try it out you can do so by installing one of my master++ releases that can be found at https://www.dropbox.com/sh/s43vqzmi4d2bqe2/AAADdYdSu9iwcKa0Knqgurm4a?dl=0. If you do try it out, I would be interested to know if it works OK for you or not.

It is a feature of my implementation that some gap fill lines are only drawn every other layer. That is normal!

screenshot_2018-11-24_07-37-12

Thank you for the help, I would love to give it a try. Can you point me to instructions to build your branch/patchset myself? I'm somewhat reluctant to run binaries from Dropbox. :)

Do you know why this regressed from 3.5.1 to 3.6.0?

Can you build Cura now using cura-build-environment and cura-build repos? Once you can do that it's not difficult to switch to using my repos for the parts that I have changed.

I don't know why it has regressed but, then again, I do not track what the Cura devs do other than to react to the bugs when I find them!

I am now using my replacement gap filling implementation to also fill the outline gaps that occur when printing thin walls. Needs more testing but it seems to work OK. My next release (later today) will contain that also.

I think this is related/the same as the issue I posted around a month back.

Hi @JohnEdwa , yes you're right it's the same problem.

@smartavionics I tested your master build and can confirm that it fixes issue #4685.
I have around 15 copies of a print I need to do for christmas and this fix dropped the time in half, so I'll keep using and testing it, thank you!

I'm glad it's been useful for you - my gap filling and thin line code appears to produce nice quality output but I think it can be slow to slice if the model has a lot of gaps and/or thin walls. For me, print quality and time is far more important than slicing time. Cheers!

@smartavionics which PR are you referring to?

Hello Tim. My new gap filling code isn't yet in a PR. It's still under development.

BTW, I have completely disabled the call to optimizePaths() as I believe it is the root cause of lots of evil. It seems to break various infills, ironed skin and also can't do a decent job of converting the zig-zag gap fill and thin wall regions into plausible single extrusions. To be honest, I think that approach (printing the gaps as zig-zag infill and then hoping that the paths can be optimized into variable width single extrusions) is not the way to go which is why I have come up with an alternative implementation.

I was planning on solving it in a very principled and complicated manner
over the next year or so.

I'm curious: what's your approach?

On Tue, Dec 4, 2018 at 10:32 AM Mark Burton notifications@github.com
wrote:

BTW, I have completely disabled the call to optimizePaths() as I believe
it is the root cause of lots of evil. It seems to break various infills,
ironed skin and also can't do a decent job of converting the zig-zag gap
fill and thin wall regions into plausible single extrusions. To be honest,
I think that approach (printing the gaps as zig-zag infill and then hoping
that the paths can be optimized into variable width single extrusions) is
not the way to go which is why I have come up with an alternative
implementation.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/Ultimaker/Cura/issues/4871#issuecomment-444032319,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AIe9EfOHTN3HCjQ4ZgdgfJQiAvmrewNaks5u1kEbgaJpZM4YxMN6
.

--

Kind regards,

Tim Kuipers

Ultimaker BV

www.ultimaker.com

Hi Tim, the inter-wall gap filling and thin wall printing come down to the same basic problem, filling a thin polygon. I use the same code for both jobs. I show the entire code below.

There's basically two parts to the code, the first part is straightforward and that simply looks at the polygons and from the vertices generates a new set of points that approximate the centreline of the gap. Those are held in the vector mid_points. I also generate a rectangular polygon that approximates the area that would be filled for each line segment. The corner points of that rectangle are stored in begin_points and end_points.

The second part of the code iterates through mid_points and for each line segment prints out a line of suitable width. The hard part here is to track which line segments have been printed so that subsequent line segments can be omitted if they would overlap with the already printed line segments.

It's not hard conceptually but it's hard to get an efficient implementation. I tried using a sparse point array to take advantage of locality but the code was more complex and no more efficient than the current implementation which simply keeps track of which line segments have been printed by unioning their area rectangles together to form a polygon which can then be intersected with the area rectangle for each line segment that may yet be printed.

I will continue to fiddle with it to see if I can up the efficiency but as it is producing (so far) very nice results and I personally don't print huge complex models I'm pretty happy with how it is right now.

````
void FffGcodeWriter::fillNarrowGaps(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const Polygons& gaps, const GCodePathConfig& gap_config, bool& added_something) const
{
const Ratio min_flow = std::max(Ratio(0.2), mesh.settings.get("wall_min_flow"));

Polygons all_filled_segments;

if (!gaps.polyLineLength())
{
    return;
}

coord_t avg_width = 2 * gaps.area() / gaps.polygonLength();

if ((float)avg_width / gap_config.getLineWidth() < min_flow)
{
    return;
}

Polygons gap_polygons(gaps);
unsigned next_poly_index = 0;

while (gap_polygons.size() > 0)
{
    ConstPolygonRef poly = gap_polygons[next_poly_index];

    if (std::abs(poly.area()) > (500 * 500))
    {
        // fill areas greater than 0.25 mm^2

        std::vector<Point> begin_points;
        std::vector<Point> end_points;
        std::vector<Point> mid_points;
        std::vector<coord_t> widths;
        for (unsigned n = 0; n < poly.size(); ++n)
        {
            Polygons lines;
            Point point_inside(PolygonUtils::getBoundaryPointWithOffset(poly, n, -avg_width * 2));
            // adjust the width when point_inside isn't normal to the direction of the next line segment
            // if we don't do this, the resulting line width is too big where the gap polygon has sharp(ish) corners
            const double len_scale = std::abs(std::sin(LinearAlg2D::getAngleLeft(point_inside, poly[n], poly[(n + 1) % poly.size()])));
            point_inside = poly[n] + normal(point_inside - poly[n], std::min(avg_width * (1 / (len_scale + 0.01)), 1.414 * avg_width));
            lines.addLine(poly[n], point_inside);
            lines = gaps.intersectionPolyLines(lines);
            if (lines.size() > 0)
            {
#if 0
                gcode_layer.addTravel(lines[0][0]);
                gcode_layer.addExtrusionMove(lines[0][1], gap_config, SpaceFillType::Lines);
#else
                const coord_t line_len = vSize(lines[0][1] - lines[0][0]) * len_scale;
                widths.push_back(line_len);
                begin_points.emplace_back(poly[n]);
                end_points.emplace_back(poly[n] + normal(turn90CCW(poly[(n + 1) % poly.size()] - poly[n]), line_len));
                mid_points.emplace_back((lines[0][0] + lines[0][1]) / 2);
#endif
            }
        }
        if (mid_points.size() > 1)
        {
            std::vector<Polygon> areas;
            for (unsigned point_index = 0; point_index < begin_points.size(); ++point_index)
            {
                const unsigned next_point_index = (point_index + 1) % begin_points.size();
                areas.emplace_back();
                areas.back().add(begin_points[point_index]);
                areas.back().add(begin_points[next_point_index]);
                // add the next mid point if it makes the area bigger
                if (LinearAlg2D::getAngleLeft(begin_points[point_index], begin_points[next_point_index], mid_points[next_point_index]) > M_PI * 0.55)
                {
                    areas.back().add(mid_points[next_point_index]);
                }
                Point next_end_point(begin_points[next_point_index] + (end_points[point_index] - begin_points[point_index]));
                areas.back().add(next_end_point);
                areas.back().add(end_points[point_index]);
                // add the current mid point if it makes the area bigger
                if (LinearAlg2D::getAngleLeft(next_end_point, end_points[point_index], mid_points[point_index]) > M_PI * 0.55)
                {
                    areas.back().add(mid_points[point_index]);
                }
            }

            added_something = true;
            setExtruder_addPrime(storage, gcode_layer, extruder_nr);
            gcode_layer.setIsInside(true); // going to print stuff inside print object

            const Point origin(gcode_layer.getLastPlannedPositionOrStartingPosition());
            coord_t min_dist2 = vSize2(origin - mid_points[0]);
            unsigned start_point_index = 0;
            for (unsigned n = 1; n < mid_points.size(); ++n)
            {
                coord_t dist2 = vSize2(origin - mid_points[n]);
                if (dist2 < min_dist2)
                {
                    min_dist2 = dist2;
                    start_point_index = n;
                }
            }

            Point start(mid_points[start_point_index]);
            bool travel_needed = true;

            for (unsigned n = 0; n < mid_points.size(); ++n)
            {
                const unsigned point_index = (start_point_index + n) % mid_points.size();
                const unsigned next_point_index = (point_index + 1) % mid_points.size();
                const Point& next_mid_point(mid_points[next_point_index]);

                Polygons segment;
                segment.add(areas[point_index]);
                Polygons overlap(segment.intersection(all_filled_segments));

#if 0
                if (gcode_layer.getLayerNr() == 0)
                {
                    std::cerr << point_index << ": overlap % = " << 100 * overlap.area() / segment.area() << "\n";
                }
#endif

                if (overlap.size() > 0 && overlap.area() > segment.area() * 0.3)
                {
                    start = next_mid_point;
                    travel_needed = true;
                    continue;
                }

                // consider the segment filled even if the flow is too low to actually do the fill
                all_filled_segments = all_filled_segments.unionPolygons(segment);

                const float flow = (widths[point_index] + widths[next_point_index]) / (2.0f * gap_config.getLineWidth());
                if (flow > min_flow)
                {
                    if (travel_needed)
                    {
                        gcode_layer.addTravel(start);
                        travel_needed = false;
                    }
                    gcode_layer.addExtrusionMove(next_mid_point, gap_config, SpaceFillType::Lines, flow);
                }
                else
                {
                    travel_needed = true;
                }
                start = next_mid_point;
            }
        }
    }

    gap_polygons.remove(next_poly_index);
    next_poly_index = 0;

    if (gap_polygons.size() > 1)
    {
        ClosestPolygonPoint cpp = PolygonUtils::findClosest(gcode_layer.getLastPlannedPositionOrStartingPosition(), gap_polygons);
        if (cpp.isValid())
        {
            next_poly_index = cpp.poly_idx;
        }
    }
}

}
````

Sounds like your idea is definitely more accurate than the current
implementation.

Perhaps you should make a PR and discuss the implementation and improvement
ideas with the Cura team.

On Tue, Dec 4, 2018 at 4:28 PM Mark Burton notifications@github.com wrote:

Hi Tim, the inter-wall gap filling and thin wall printing come down to the
same basic problem, filling a thin polygon. I use the same code for both
jobs. I show the entire code below.

There's basically two parts to the code, the first part is straightforward
and that simply looks at the polygons and from the vertices generates a new
set of points that approximate the centreline of the gap. Those are held in
the vector mid_points. I also generate a rectangular polygon that
approximates the area that would be filled for each line segment. The
corner points of that rectangle are stored in begin_points and end_points.

The second part of the code iterates through mid_points and for each line
segment prints out a line of suitable width. The hard part here is to track
which line segments have been printed so that subsequent line segments can
be omitted if they would overlap with the already printed line segments.

It's not hard conceptually but it's hard to get an efficient
implementation. I tried using a sparse point array to take advantage of
locality but the code was more complex and no more efficient than the
current implementation which simply keeps track of which line segments have
been printed by unioning their area rectangles together to form a polygon
which can then be intersected with the area rectangle for each line segment
that may yet be printed.

I will continue to fiddle with it to see if I can up the efficiency but as
it is producing (so far) very nice results and I personally don't print
huge complex models I'm pretty happy with how it is right now.

void FffGcodeWriter::fillNarrowGaps(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const Polygons& gaps, const GCodePathConfig& gap_config, bool& added_something) const
{
const Ratio min_flow = std::max(Ratio(0.2), mesh.settings.get("wall_min_flow"));

Polygons all_filled_segments;

if (!gaps.polyLineLength())
{
    return;
}

coord_t avg_width = 2 * gaps.area() / gaps.polygonLength();

if ((float)avg_width / gap_config.getLineWidth() < min_flow)
{
    return;
}

Polygons gap_polygons(gaps);
unsigned next_poly_index = 0;

while (gap_polygons.size() > 0)
{
    ConstPolygonRef poly = gap_polygons[next_poly_index];

    if (std::abs(poly.area()) > (500 * 500))
    {
        // fill areas greater than 0.25 mm^2

        std::vector<Point> begin_points;
        std::vector<Point> end_points;
        std::vector<Point> mid_points;
        std::vector<coord_t> widths;
        for (unsigned n = 0; n < poly.size(); ++n)
        {
            Polygons lines;
            Point point_inside(PolygonUtils::getBoundaryPointWithOffset(poly, n, -avg_width * 2));
            // adjust the width when point_inside isn't normal to the direction of the next line segment
            // if we don't do this, the resulting line width is too big where the gap polygon has sharp(ish) corners
            const double len_scale = std::abs(std::sin(LinearAlg2D::getAngleLeft(point_inside, poly[n], poly[(n + 1) % poly.size()])));
            point_inside = poly[n] + normal(point_inside - poly[n], std::min(avg_width * (1 / (len_scale + 0.01)), 1.414 * avg_width));
            lines.addLine(poly[n], point_inside);
            lines = gaps.intersectionPolyLines(lines);
            if (lines.size() > 0)
            {
#if 0
                gcode_layer.addTravel(lines[0][0]);
                gcode_layer.addExtrusionMove(lines[0][1], gap_config, SpaceFillType::Lines);
#else
                const coord_t line_len = vSize(lines[0][1] - lines[0][0]) * len_scale;
                widths.push_back(line_len);
                begin_points.emplace_back(poly[n]);
                end_points.emplace_back(poly[n] + normal(turn90CCW(poly[(n + 1) % poly.size()] - poly[n]), line_len));
                mid_points.emplace_back((lines[0][0] + lines[0][1]) / 2);
#endif
            }
        }
        if (mid_points.size() > 1)
        {
            std::vector<Polygon> areas;
            for (unsigned point_index = 0; point_index < begin_points.size(); ++point_index)
            {
                const unsigned next_point_index = (point_index + 1) % begin_points.size();
                areas.emplace_back();
                areas.back().add(begin_points[point_index]);
                areas.back().add(begin_points[next_point_index]);
                // add the next mid point if it makes the area bigger
                if (LinearAlg2D::getAngleLeft(begin_points[point_index], begin_points[next_point_index], mid_points[next_point_index]) > M_PI * 0.55)
                {
                    areas.back().add(mid_points[next_point_index]);
                }
                Point next_end_point(begin_points[next_point_index] + (end_points[point_index] - begin_points[point_index]));
                areas.back().add(next_end_point);
                areas.back().add(end_points[point_index]);
                // add the current mid point if it makes the area bigger
                if (LinearAlg2D::getAngleLeft(next_end_point, end_points[point_index], mid_points[point_index]) > M_PI * 0.55)
                {
                    areas.back().add(mid_points[point_index]);
                }
            }

            added_something = true;
            setExtruder_addPrime(storage, gcode_layer, extruder_nr);
            gcode_layer.setIsInside(true); // going to print stuff inside print object

            const Point origin(gcode_layer.getLastPlannedPositionOrStartingPosition());
            coord_t min_dist2 = vSize2(origin - mid_points[0]);
            unsigned start_point_index = 0;
            for (unsigned n = 1; n < mid_points.size(); ++n)
            {
                coord_t dist2 = vSize2(origin - mid_points[n]);
                if (dist2 < min_dist2)
                {
                    min_dist2 = dist2;
                    start_point_index = n;
                }
            }

            Point start(mid_points[start_point_index]);
            bool travel_needed = true;

            for (unsigned n = 0; n < mid_points.size(); ++n)
            {
                const unsigned point_index = (start_point_index + n) % mid_points.size();
                const unsigned next_point_index = (point_index + 1) % mid_points.size();
                const Point& next_mid_point(mid_points[next_point_index]);

                Polygons segment;
                segment.add(areas[point_index]);
                Polygons overlap(segment.intersection(all_filled_segments));

#if 0
                if (gcode_layer.getLayerNr() == 0)
                {
                    std::cerr << point_index << ": overlap % = " << 100 * overlap.area() / segment.area() << "\n";
                }
#endif

                if (overlap.size() > 0 && overlap.area() > segment.area() * 0.3)
                {
                    start = next_mid_point;
                    travel_needed = true;
                    continue;
                }

                // consider the segment filled even if the flow is too low to actually do the fill
                all_filled_segments = all_filled_segments.unionPolygons(segment);

                const float flow = (widths[point_index] + widths[next_point_index]) / (2.0f * gap_config.getLineWidth());
                if (flow > min_flow)
                {
                    if (travel_needed)
                    {
                        gcode_layer.addTravel(start);
                        travel_needed = false;
                    }
                    gcode_layer.addExtrusionMove(next_mid_point, gap_config, SpaceFillType::Lines, flow);
                }
                else
                {
                    travel_needed = true;
                }
                start = next_mid_point;
            }
        }
    }

    gap_polygons.remove(next_poly_index);
    next_poly_index = 0;

    if (gap_polygons.size() > 1)
    {
        ClosestPolygonPoint cpp = PolygonUtils::findClosest(gcode_layer.getLastPlannedPositionOrStartingPosition(), gap_polygons);
        if (cpp.isValid())
        {
            next_poly_index = cpp.poly_idx;
        }
    }
}

}

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/Ultimaker/Cura/issues/4871#issuecomment-444140586,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AIe9EUHfKYzr3We-nr8M7T4ve5DapUGzks5u1pSNgaJpZM4YxMN6
.

--

Kind regards,

Tim Kuipers

Ultimaker BV

www.ultimaker.com

This is brilliant. This slicer benefits extreme with your implementation of filling small gaps! I appreciate your work.

Thanks @TimoErdmann. It's good to know that it is working well for you.

Here's an extreme stress test for thin walls and gaps:
thin_walls_stress_test.svg_1mm.stl.zip

Try different line widths to test this model.

image

Thanks for that @BagelOrb. It doesn't handle that very well right now, I will see if I can improve it.

screenshot_2018-12-06_11-11-20

Getting better...

screenshot_2018-12-06_14-38-12

@smartavionics Just a heads up, in Master 20181210 the "Minimum Infill Area" function has broken again Not sure if it was on earlier builds as well and might not have anything to do with your changes but I don't think creating new issues for these builds in this repo is really appropriate either.

Values above 0 but below the size it would activate don't generate bottom layers.
Minimum Infill Area: 0
Minimum Infill Area: 50
Minimum Infill Area: 750

Hi @JohnEdwa , could you please share that project so I can have a play. Thanks.

@smartavionics Sure, it's a slightly modified one as I added a sacrificial bridge and don't have the old file, but it still clearly shows the issue on layer 51 when you change Minimum Infill Area.

CE3_Component4.zip

Thanks for the project. I had a play with it and it does seem screwy. I think I was the original creator of that setting but it subsequently got reworked by the Cura team. I don't actually use it anymore because I tend to use the skin shrink and expand settings instead.

The min infill area feature does appear to act weird - it is affected by the use of skin removal width. Your profile has a value of 0.8mm for that. If you reduce it to zero then that central region of skin on layer 51 doesn't look too bad with a min infill area value of 30 but does go wrong when the min infill area is increased to 50. To be honest, I can't really be bothered to find out what they have broken exactly, life's too short!

@smartavionics ,
thanks for this feature. I finally managed to print this led armature in clear PET without ugly scars from unnecesary movcements. Had to look hard for this option though. So for others who find this thread I will share the breadcrumbtrail here.

I added options in section: "_shell_" --> "_compensate wall overlaps_" and "_minimum wall flow_"
I checked _compensate wall overlaps_ and set _minimum wall flow_ to 15% .

capture

I'm just curious: can you take a picture of the assembled product?

On Thu, Jan 3, 2019 at 12:57 AM Diederik van der Pant <
[email protected]> wrote:

@smartavionics https://github.com/smartavionics ,
thanks for this feature. I finally managed to print this led armature in
clear PET without ugly scars from unnecesary movcements. Had to look hard
for this option though. So for others who find this thread I will share the
breadcrumbtrail here.

I added options in section: "shell" --> "compensate wall overlaps"
and "minimum wall flow"
I checked compensate wall overlaps and set minimum wall flow to 15% .

[image: capture]
https://user-images.githubusercontent.com/9283150/50618209-a2a2db80-0ef1-11e9-8d15-7549acd5c8ab.PNG

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Ultimaker/Cura/issues/4871#issuecomment-451022194,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AIe9EQLDC4WtDX2iRK3MrQXCBgs9IsK6ks5u_UdrgaJpZM4YxMN6
.

--

Kind regards,

Tim Kuipers

Ultimaker BV

www.ultimaker.com

@smartavionics

@BagelOrb was curious of the product. And today I got the fadecandy ledcontroller and the rpi working. So I made some nice pics. Credits for the nice glowing effect go to the creator of fadecandy.
https://github.com/scanlime/fadecandy.

img_2175
img_2176
img_2189

Cool!

Thanks!

On Sat, 5 Jan 2019, 00:56 Diederik van der Pant <[email protected]
wrote:

@smartavionics https://github.com/smartavionics

@BagelOrb https://github.com/BagelOrb was curious of the product. And
today I got the fadecandy ledcontroller and the rpi working. So I made some
nice pics. Credits for the nice glowing effect go to the creator of
fadecandy.
https://github.com/scanlime/fadecandy.

[image: img_2175]
https://user-images.githubusercontent.com/9283150/50716920-50de8a80-1084-11e9-8e0a-69339c1e74b1.JPG
[image: img_2176]
https://user-images.githubusercontent.com/9283150/50716929-5a67f280-1084-11e9-965e-98259dc48307.JPG
[image: img_2189]
https://user-images.githubusercontent.com/9283150/50716933-5d62e300-1084-11e9-94d9-129d9a40da9f.JPG

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Ultimaker/Cura/issues/4871#issuecomment-451604190,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AIe9EXFn1h7xv0AXm-zUmmJfN3C8NnGAks5u_-pIgaJpZM4YxMN6
.

Capture2
Capture

Just adding some context since it appears this issue is still causing some problems. The pic with the infill inside the thin wall is Cura and the other is from Slic3r. With Slic3r I can almost set wall count or width to anything except 1 and it will fill the thin wall with a line. In Cura no matter what I did, I could not get it to fill with a line.

Was this page helpful?
0 / 5 - 0 ratings