Exemple #1
0
void Weaver::fillFloors(Polygons& supporting, Polygons& to_be_supported, int direction, int z, WeaveRoof& horizontals)
{
    std::vector<WeaveRoofPart>& outsets = horizontals.roof_insets;
    
    if (to_be_supported.size() == 0) return; // no parts to start the floor from!
    if (supporting.size() == 0) return; // no parts to start the floor from!
    
    Polygons floors = to_be_supported.difference(supporting);

    const coord_t roof_inset = Application::getInstance().current_slice->scene.current_mesh_group->settings.get<coord_t>("wireframe_roof_inset");
    floors = floors.offset(-roof_inset).offset(roof_inset);
    
    if (floors.size() == 0) return;
    
    
    std::vector<PolygonsPart> floor_parts = floors.splitIntoParts();
    
    Polygons floor_outlines;
    Polygons floor_holes;
    for (PolygonsPart& floor_part : floor_parts)
    {
        floor_outlines.add(floor_part[0]);
        for (unsigned int hole_idx = 1; hole_idx < floor_part.size(); hole_idx++)
        {
            floor_holes.add(floor_part[hole_idx]);
            //floor_holes.back().reverse();
        }
    }
    
    
    Polygons outset1;
    
    Polygons last_supported = supporting;
    
    for (Polygons outset0 = supporting; outset0.size() > 0; outset0 = outset1)
    {
        outset1 = outset0.offset(roof_inset * direction, ClipperLib::jtRound).intersection(floors);
        outset1 = outset1.remove(floor_holes); // throw away holes which appear in every intersection
        outset1 = outset1.remove(floor_outlines); // throw away holes which appear in every intersection
        
        
        outsets.emplace_back();
        
        connect(last_supported, z, outset1, z, outsets.back());
        
        outset1 = outset1.remove(floor_outlines);// throw away fully filled regions
        
        last_supported = outsets.back().supported; // chainified

    }
    
    
    horizontals.roof_outlines.add(floors);
}
Exemple #2
0
/*
 * This function is executed in a parallel region based on layer_nr.
 * When modifying make sure any changes does not introduce data races.
 *
 * generateSkinAreas reads data from mesh.layers[*].parts[*].insets and writes to mesh.layers[n].parts[*].skin_parts
 */
void SkinInfillAreaComputation::generateSkinAndInfillAreas(SliceLayerPart& part)
{
    int min_infill_area = mesh.getSettingInMillimeters("min_infill_area");

    Polygons original_outline = part.insets.back().offset(-innermost_wall_line_width / 2);

    // make a copy of the outline which we later intersect and union with the resized skins to ensure the resized skin isn't too large or removed completely.
    Polygons upskin;
    if (top_layer_count > 0)
    {
        upskin = Polygons(original_outline);
    }
    Polygons downskin;
    if (bottom_layer_count > 0)
    {
        downskin = Polygons(original_outline);
    }

    calculateBottomSkin(part, min_infill_area, downskin);

    calculateTopSkin(part, min_infill_area, upskin);

    applySkinExpansion(original_outline, upskin, downskin);

    // now combine the resized upskin and downskin
    Polygons skin = upskin.unionPolygons(downskin);

    skin.removeSmallAreas(MIN_AREA_SIZE);

    if (process_infill)
    { // process infill when infill density > 0
        // or when other infill meshes want to modify this infill
        generateInfill(part, skin);
    }

    for (PolygonsPart& skin_area_part : skin.splitIntoParts())
    {
        part.skin_parts.emplace_back();
        part.skin_parts.back().outline = skin_area_part;
    }
}
Exemple #3
0
void Weaver::fillRoofs(Polygons& supporting, Polygons& to_be_supported, int direction, int z, WeaveRoof& horizontals)
{
    std::vector<WeaveRoofPart>& insets = horizontals.roof_insets;
    
    if (supporting.size() == 0) return; // no parts to start the roof from!
    
    Polygons roofs = supporting.difference(to_be_supported);
    
    roofs = roofs.offset(-roof_inset).offset(roof_inset);
    
    if (roofs.size() == 0) return;
    
    
    Polygons roof_outlines; 
    Polygons roof_holes;
    { // split roofs into outlines and holes
        std::vector<PolygonsPart> roof_parts = roofs.splitIntoParts();
        for (PolygonsPart& roof_part : roof_parts)
        {
            roof_outlines.add(roof_part[0]);
            for (unsigned int hole_idx = 1; hole_idx < roof_part.size(); hole_idx++)
            {
                roof_holes.add(roof_part[hole_idx]);
                roof_holes.back().reverse();
            }
        }
    }

    
    Polygons supporting_outlines;
    
    std::vector<PolygonsPart> supporting_parts = supporting.splitIntoParts();
    for (PolygonsPart& supporting_part : supporting_parts) 
        supporting_outlines.add(supporting_part[0]); // only add outlines, not the holes
    
    
    
    Polygons inset1;
    Polygons last_inset;
    Polygons last_supported = supporting;
    for (Polygons inset0 = supporting_outlines; inset0.size() > 0; inset0 = last_inset)
    {
        last_inset = inset0.offset(direction * roof_inset, ClipperLib::jtRound);
        inset1 = last_inset.intersection(roof_outlines); // stay within roof area
        inset1 = inset1.unionPolygons(roof_holes);// make insets go around holes

        if (inset1.size() == 0) break;
        
        insets.emplace_back();
        
        connect(last_supported, z, inset1, z, insets.back(), true);
        
        inset1 = inset1.remove(roof_holes); // throw away holes which appear in every intersection
        inset1 = inset1.remove(roof_outlines);// throw away fully filled regions
        
        last_supported = insets.back().supported; // chainified
        
    }
    

    
    horizontals.roof_outlines.add(roofs); // TODO just add the new lines, not the lines of the roofs which are already supported ==> make outlines into a connection from which we only print the top, not the connection
} 
Exemple #4
0
void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost_wall_line_width, int downSkinCount, int upSkinCount, int wall_line_count, bool no_small_gaps_heuristic)
{
    SliceLayer& layer = mesh.layers[layer_nr];
    
    if (downSkinCount == 0 && upSkinCount == 0)
    {
        return;
    }
    
    for(unsigned int partNr = 0; partNr < layer.parts.size(); partNr++)
    {
        SliceLayerPart& part = layer.parts[partNr];

        if (int(part.insets.size()) < wall_line_count)
        {
            continue; // the last wall is not present, the part should only get inter perimeter gaps, but no skin.
        }

        Polygons upskin = part.insets.back().offset(-innermost_wall_line_width / 2);
        Polygons downskin = (downSkinCount == 0) ? Polygons() : upskin;
        if (upSkinCount == 0) upskin = Polygons();

        auto getInsidePolygons = [&part, wall_line_count](SliceLayer& layer2)
            {
                Polygons result;
                for(SliceLayerPart& part2 : layer2.parts)
                {
                    if (part.boundaryBox.hit(part2.boundaryBox))
                    {
                        unsigned int wall_idx = std::max(0, std::min(wall_line_count, (int) part2.insets.size()) - 1);
                        result.add(part2.insets[wall_idx]);
                    }
                }
                return result;
            };
            
        if (no_small_gaps_heuristic)
        {
            if (static_cast<int>(layer_nr - downSkinCount) >= 0)
            {
                downskin = downskin.difference(getInsidePolygons(mesh.layers[layer_nr - downSkinCount])); // skin overlaps with the walls
            }
            
            if (static_cast<int>(layer_nr + upSkinCount) < static_cast<int>(mesh.layers.size()))
            {
                upskin = upskin.difference(getInsidePolygons(mesh.layers[layer_nr + upSkinCount])); // skin overlaps with the walls
            }
        }
        else 
        {
            if (layer_nr >= downSkinCount && downSkinCount > 0)
            {
                Polygons not_air = getInsidePolygons(mesh.layers[layer_nr - 1]);
                for (int downskin_layer_nr = layer_nr - downSkinCount; downskin_layer_nr < layer_nr - 1; downskin_layer_nr++)
                {
                    not_air = not_air.intersection(getInsidePolygons(mesh.layers[downskin_layer_nr]));
                }
                downskin = downskin.difference(not_air); // skin overlaps with the walls
            }
            
            if (layer_nr < static_cast<int>(mesh.layers.size()) - 1 - upSkinCount && upSkinCount > 0)
            {
                Polygons not_air = getInsidePolygons(mesh.layers[layer_nr + 1]);
                for (int upskin_layer_nr = layer_nr + 2; upskin_layer_nr < layer_nr + upSkinCount + 1; upskin_layer_nr++)
                {
                    not_air = not_air.intersection(getInsidePolygons(mesh.layers[upskin_layer_nr]));
                }
                upskin = upskin.difference(not_air); // skin overlaps with the walls
            }
        }
        
        Polygons skin = upskin.unionPolygons(downskin);
        
        skin.removeSmallAreas(MIN_AREA_SIZE);
        
        for (PolygonsPart& skin_area_part : skin.splitIntoParts())
        {
            part.skin_parts.emplace_back();
            part.skin_parts.back().outline = skin_area_part;
        }
    }
}