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); }
/* * 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; } }
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 }
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; } } }