mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-08 07:27:41 -06:00
NEW: enable lightning infill pattern for model and tree support
Change-Id: I6e2cbfdd30f8d222f88301ed0c8cc89e21cfdc24 (cherry picked from commit ddfee7c069cfc42685be509d48b8c609e1dc0cfc)
This commit is contained in:
parent
f331d5998e
commit
9cf95696a4
22 changed files with 1014 additions and 321 deletions
|
@ -11,6 +11,8 @@
|
|||
#include "I18N.hpp"
|
||||
#include <libnest2d/backends/libslic3r/geometries.hpp>
|
||||
|
||||
#include "Fill/FillBase.hpp"
|
||||
|
||||
#define _L(s) Slic3r::I18N::translate(s)
|
||||
|
||||
|
||||
|
@ -283,6 +285,49 @@ static void draw_layer_mst
|
|||
svg.draw(lines, "blue", coord_t(scale_(0.05)));
|
||||
svg.draw_outline(outline, "yellow");
|
||||
}
|
||||
|
||||
static void draw_two_overhangs_to_svg(TreeSupportLayer* ts_layer, const ExPolygons& overhangs1, const ExPolygons& overhangs2)
|
||||
{
|
||||
if (overhangs1.empty() && overhangs2.empty())
|
||||
return;
|
||||
BoundingBox bbox1 = get_extents(overhangs1);
|
||||
BoundingBox bbox2 = get_extents(overhangs2);
|
||||
bbox1.merge(bbox2);
|
||||
|
||||
SVG svg(get_svg_filename(std::to_string(ts_layer->print_z), "two_overhangs"), bbox1);
|
||||
if (!svg.is_opened()) return;
|
||||
|
||||
svg.draw(union_ex(overhangs1), "blue");
|
||||
svg.draw(union_ex(overhangs2), "red");
|
||||
}
|
||||
|
||||
static void draw_polylines(TreeSupportLayer* ts_layer, Polylines& polylines)
|
||||
{
|
||||
if (polylines.empty())
|
||||
return;
|
||||
BoundingBox bbox = get_extents(polylines);
|
||||
|
||||
SVG svg(get_svg_filename(std::to_string(ts_layer->print_z), "lightnings"), bbox);
|
||||
if (!svg.is_opened()) return;
|
||||
|
||||
int id = 0;
|
||||
for (Polyline& pline : polylines)
|
||||
{
|
||||
int i1, i2;
|
||||
for (size_t i = 0; i < pline.size() - 1; i++)
|
||||
{
|
||||
i1 = i;
|
||||
i2 = i + 1;
|
||||
svg.draw(Line(pline.points[i1], pline.points[i2]), "blue");
|
||||
svg.draw(pline.points[i1], "red");
|
||||
id++;
|
||||
svg.draw_text(pline.points[i1], std::to_string(id).c_str(), "black", 1);
|
||||
}
|
||||
svg.draw(pline.points[i2], "red");
|
||||
id++;
|
||||
svg.draw_text(pline.points[i2], std::to_string(id).c_str(), "black", 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Move point from inside polygon if distance>0, outside if distance<0.
|
||||
|
@ -641,7 +686,11 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
|
|||
m_raft_layers = slicing_params.base_raft_layers + slicing_params.interface_raft_layers;
|
||||
|
||||
SupportMaterialPattern support_pattern = m_object_config->support_base_pattern;
|
||||
m_support_params.base_fill_pattern = support_pattern == smpHoneycomb ? ipHoneycomb :
|
||||
m_support_params.base_fill_pattern =
|
||||
#if HAS_LIGHTNING_INFILL
|
||||
support_pattern == smpLightning ? ipLightning :
|
||||
#endif
|
||||
support_pattern == smpHoneycomb ? ipHoneycomb :
|
||||
m_support_params.support_density > 0.95 || m_support_params.with_sheath ? ipRectilinear :
|
||||
ipSupportBase;
|
||||
m_support_params.interface_fill_pattern = (m_support_params.interface_density > 0.95 ? ipRectilinear : ipSupportBase);
|
||||
|
@ -1507,7 +1556,7 @@ void TreeSupport::generate_toolpaths()
|
|||
ExtrusionRole role;
|
||||
Flow flow = (layer_id == 0 && m_raft_layers == 0) ? m_object->print()->brim_flow() :
|
||||
(m_support_params.base_fill_pattern == ipRectilinear && (layer_id % num_layers_to_change_infill_direction == 0) ? support_transition_flow(m_object) : support_flow);
|
||||
if (with_infill && layer_id > 0) {
|
||||
if (with_infill && layer_id > 0 && m_support_params.base_fill_pattern != ipLightning) {
|
||||
if (m_support_params.base_fill_pattern == ipRectilinear) {
|
||||
role = erSupportMaterial;// layer_id% num_layers_to_change_infill_direction == 0 ? erSupportTransition : erSupportMaterial;
|
||||
filler_support->angle = Geometry::deg2rad(object_config.support_angle.value);// obj_is_vertical* M_PI_2;// (obj_is_vertical + int(layer_id / num_layers_to_change_infill_direction))* M_PI_2;
|
||||
|
@ -1541,6 +1590,67 @@ void TreeSupport::generate_toolpaths()
|
|||
}
|
||||
}
|
||||
}
|
||||
if (with_infill && m_support_params.base_fill_pattern == ipLightning)
|
||||
{
|
||||
double print_z = ts_layer->print_z;
|
||||
if (printZ_to_lightninglayer.find(print_z) == printZ_to_lightninglayer.end())
|
||||
continue;
|
||||
//TODO:
|
||||
//1.the second parameter of convertToLines seems to decide how long the lightning should be trimmed from its root, so that the root wont overlap/detach the support contour.
|
||||
// whether current value works correctly remained to be tested
|
||||
//2.related to previous one, that lightning roots need to be trimed more when support has multiple walls
|
||||
//3.function connect_infill() and variable 'params' helps create connection pattern along contours between two lightning roots,
|
||||
// strengthen lightnings while it may make support harder. decide to enable it or not. if yes, proper values for params are remained to be tested
|
||||
auto& lightning_layer = generator->getTreesForLayer(printZ_to_lightninglayer[print_z]);
|
||||
|
||||
Flow flow = (layer_id == 0 && m_raft_layers == 0) ?
|
||||
m_object->print()->brim_flow() :
|
||||
(m_support_params.base_fill_pattern == ipRectilinear && (layer_id % num_layers_to_change_infill_direction == 0) ?
|
||||
support_transition_flow(m_object) :
|
||||
support_flow);
|
||||
ExPolygons areas = offset_ex(ts_layer->base_areas, -flow.scaled_spacing());
|
||||
|
||||
for (auto& area : areas)
|
||||
{
|
||||
Polylines polylines = lightning_layer.convertToLines(to_polygons(area), 0);
|
||||
for (auto itr = polylines.begin(); itr != polylines.end();)
|
||||
{
|
||||
if (itr->length() < scale_(1.0))
|
||||
itr = polylines.erase(itr);
|
||||
else
|
||||
itr++;
|
||||
}
|
||||
Polylines opt_polylines;
|
||||
#if 1
|
||||
//this wont create connection patterns along contours
|
||||
append(opt_polylines, chain_polylines(std::move(polylines)));
|
||||
#else
|
||||
//this will create connection patterns along contours
|
||||
FillParams params;
|
||||
params.anchor_length = float(Fill::infill_anchor * 0.01 * flow.spacing());
|
||||
params.anchor_length_max = Fill::infill_anchor_max;
|
||||
params.anchor_length = std::min(params.anchor_length, params.anchor_length_max);
|
||||
Fill::connect_infill(std::move(polylines), area, opt_polylines, flow.spacing(), params);
|
||||
#endif
|
||||
extrusion_entities_append_paths(ts_layer->support_fills.entities, opt_polylines, erSupportMaterial,
|
||||
float(flow.mm3_per_mm()), float(flow.width()), float(flow.height()));
|
||||
|
||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||
std::string prefix = "./SVG/";
|
||||
std::string suffix = ".svg";
|
||||
std::string name = prefix + "trees_polyline" + "_" + std::to_string(ts_layer->print_z) /*+ "_" + std::to_string(rand_num)*/ + suffix;
|
||||
BoundingBox bbox = get_extents(ts_layer->base_areas);
|
||||
SVG svg(name, bbox);
|
||||
|
||||
svg.draw(ts_layer->base_areas, "blue");
|
||||
svg.draw(generator->Overhangs()[printZ_to_lightninglayer[print_z]], "red");
|
||||
for (auto& line : opt_polylines)
|
||||
{
|
||||
svg.draw(line, "yellow");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// sort extrusions to reduce travel, also make sure walls go before infills
|
||||
chain_and_reorder_extrusion_entities(ts_layer->support_fills.entities);
|
||||
|
@ -1895,6 +2005,15 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
|||
const coordf_t line_width = config.support_line_width;
|
||||
const coordf_t line_width_scaled = scale_(line_width);
|
||||
|
||||
const bool with_lightning_infill = config.tree_support_with_infill.value && config.support_base_pattern.value == smpLightning;
|
||||
coordf_t support_extrusion_width = config.support_line_width.value > 0 ? config.support_line_width : config.line_width;
|
||||
const size_t wall_count = config.tree_support_wall_count.value;
|
||||
|
||||
const PrintObjectConfig& object_config = m_object->config();
|
||||
auto m_support_material_flow = support_material_flow(m_object, float(m_slicing_params.layer_height));
|
||||
coordf_t support_spacing = object_config.support_base_pattern_spacing.value + m_support_material_flow.spacing();
|
||||
coordf_t support_density = std::min(1., m_support_material_flow.spacing() / support_spacing);
|
||||
|
||||
// coconut: previously std::unordered_map in m_collision_cache is not multi-thread safe which may cause programs stuck, here we change to tbb::concurrent_unordered_map
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_object->layer_count()),
|
||||
|
@ -2060,100 +2179,167 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
|||
});
|
||||
|
||||
#if 1
|
||||
// move the holes to contour so they can be well supported
|
||||
if (!has_infill) {
|
||||
// check if poly's contour intersects with expoly's contour
|
||||
auto intersects_contour = [](Polygon poly, ExPolygon expoly, Point &pt_on_poly, Point &pt_on_expoly, Point &pt_far_on_poly, float dist_thresh = 0.01) {
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
float max_dist = 0;
|
||||
for (auto from : poly.points) {
|
||||
for (int i = 0; i < expoly.num_contours(); i++) {
|
||||
const Point *candidate = expoly.contour_or_hole(i).closest_point(from);
|
||||
double dist2 = vsize2_with_unscale(*candidate - from);
|
||||
if (dist2 < min_dist) {
|
||||
min_dist = dist2;
|
||||
pt_on_poly = from;
|
||||
pt_on_expoly = *candidate;
|
||||
}
|
||||
if (dist2 > max_dist) {
|
||||
max_dist = dist2;
|
||||
pt_far_on_poly = from;
|
||||
}
|
||||
if (dist2 < dist_thresh) { return true; }
|
||||
if (with_lightning_infill)
|
||||
{
|
||||
const bool global_lightning_infill = true;
|
||||
|
||||
std::vector<Polygons> contours;
|
||||
std::vector<Polygons> overhangs;
|
||||
for (int layer_nr = 1; layer_nr < m_object->layer_count(); layer_nr++) {
|
||||
if (print->canceled()) break;
|
||||
const std::vector<Node*>& curr_layer_nodes = contact_nodes[layer_nr];
|
||||
TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers);
|
||||
assert(ts_layer != nullptr);
|
||||
|
||||
// skip if current layer has no points. This fixes potential crash in get_collision (see jira BBL001-355)
|
||||
if (curr_layer_nodes.empty()) continue;
|
||||
if (ts_layer->height < EPSILON) continue;
|
||||
if (ts_layer->area_groups.empty()) continue;
|
||||
|
||||
ExPolygons& base_areas = ts_layer->base_areas;
|
||||
|
||||
int layer_nr_lower = layer_nr - 1;
|
||||
for (layer_nr_lower; layer_nr_lower >= 0; layer_nr_lower--) {
|
||||
if (!m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->area_groups.empty()) break;
|
||||
}
|
||||
TreeSupportLayer* lower_layer = m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers);
|
||||
ExPolygons& base_areas_lower = m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->base_areas;
|
||||
|
||||
ExPolygons overhang;
|
||||
|
||||
if (layer_nr_lower == 0)
|
||||
continue;
|
||||
|
||||
if (global_lightning_infill)
|
||||
{
|
||||
//search overhangs globally
|
||||
overhang = std::move(diff_ex(offset_ex(base_areas_lower, -2.0 * scale_(support_extrusion_width)), base_areas));
|
||||
}
|
||||
else
|
||||
{
|
||||
//search overhangs only on floating islands
|
||||
for (auto& base_area : base_areas)
|
||||
for (auto& hole : base_area.holes)
|
||||
{
|
||||
Polygon rev_hole = hole;
|
||||
rev_hole.make_counter_clockwise();
|
||||
ExPolygons ex_hole = to_expolygons(ExPolygon(rev_hole));
|
||||
for (auto& other_area : base_areas)
|
||||
//if (&other_area != &base_area)
|
||||
ex_hole = std::move(diff_ex(ex_hole, other_area));
|
||||
overhang = std::move(union_ex(overhang, ex_hole));
|
||||
}
|
||||
overhang = std::move(intersection_ex(overhang, offset_ex(base_areas_lower, -0.5 * scale_(support_extrusion_width))));
|
||||
}
|
||||
|
||||
overhangs.emplace_back(to_polygons(overhang));
|
||||
contours.emplace_back(to_polygons(base_areas_lower)); //cant guarantee for 100% success probability, infill fails sometimes
|
||||
printZ_to_lightninglayer[lower_layer->print_z] = overhangs.size() - 1;
|
||||
|
||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||
draw_two_overhangs_to_svg(m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers), base_areas_lower, to_expolygons(overhangs.back()));
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// polygon pointer: depth, direction, farPoint
|
||||
std::map<const Polygon *, std::tuple<int, Point, Point>> holePropagationInfos;
|
||||
for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) {
|
||||
if (print->canceled()) break;
|
||||
m_object->print()->set_status(66, (boost::format(_L("Support: fix holes at layer %d")) % layer_nr).str());
|
||||
generator = std::make_unique<FillLightning::Generator>(m_object, contours, overhangs, support_density);
|
||||
}
|
||||
|
||||
const std::vector<Node *> &curr_layer_nodes = contact_nodes[layer_nr];
|
||||
TreeSupportLayer * ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers);
|
||||
assert(ts_layer != nullptr);
|
||||
else if (!has_infill) {
|
||||
// move the holes to contour so they can be well supported
|
||||
|
||||
// skip if current layer has no points. This fixes potential crash in get_collision (see jira BBL001-355)
|
||||
if (curr_layer_nodes.empty()) continue;
|
||||
if (ts_layer->height < EPSILON) continue;
|
||||
if (ts_layer->area_groups.empty()) continue;
|
||||
|
||||
int layer_nr_lower = layer_nr - 1;
|
||||
for (layer_nr_lower; layer_nr_lower >= 0; layer_nr_lower--) {
|
||||
if (!m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->area_groups.empty()) break;
|
||||
}
|
||||
auto &area_groups_lower = m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->area_groups;
|
||||
|
||||
for (const auto &area_group : ts_layer->area_groups) {
|
||||
if (area_group.second != TreeSupportLayer::BaseType) continue;
|
||||
const auto area = area_group.first;
|
||||
for (const auto &hole : area->holes) {
|
||||
// auto hole_bbox = get_extents(hole).polygon();
|
||||
for (auto &area_group_lower : area_groups_lower) {
|
||||
if (area_group.second != TreeSupportLayer::BaseType) continue;
|
||||
auto &base_area_lower = *area_group_lower.first;
|
||||
Point pt_on_poly, pt_on_expoly, pt_far_on_poly;
|
||||
// if a hole doesn't intersect with lower layer's contours, add a hole to lower layer and move it slightly to the contour
|
||||
if (base_area_lower.contour.contains(hole.points.front()) && !intersects_contour(hole, base_area_lower, pt_on_poly, pt_on_expoly, pt_far_on_poly)) {
|
||||
Polygon hole_lower = hole;
|
||||
Point direction = normal(pt_on_expoly - pt_on_poly, line_width_scaled / 2);
|
||||
hole_lower.translate(direction);
|
||||
// note to expand a hole, we need to do negative offset
|
||||
auto hole_expanded = offset(hole_lower, -line_width_scaled / 4, ClipperLib::JoinType::jtSquare);
|
||||
if (!hole_expanded.empty()) {
|
||||
base_area_lower.holes.push_back(std::move(hole_expanded[0]));
|
||||
holePropagationInfos.insert({&base_area_lower.holes.back(), {25, direction, pt_far_on_poly}});
|
||||
// check if poly's contour intersects with expoly's contour
|
||||
auto intersects_contour = [](Polygon poly, ExPolygon expoly, Point& pt_on_poly, Point& pt_on_expoly, Point& pt_far_on_poly, float dist_thresh = 0.01) {
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
float max_dist = 0;
|
||||
for (auto from : poly.points) {
|
||||
for (int i = 0; i < expoly.num_contours(); i++) {
|
||||
const Point* candidate = expoly.contour_or_hole(i).closest_point(from);
|
||||
double dist2 = vsize2_with_unscale(*candidate - from);
|
||||
if (dist2 < min_dist) {
|
||||
min_dist = dist2;
|
||||
pt_on_poly = from;
|
||||
pt_on_expoly = *candidate;
|
||||
}
|
||||
break;
|
||||
} else if (holePropagationInfos.find(&hole) != holePropagationInfos.end() && std::get<0>(holePropagationInfos[&hole]) > 0 &&
|
||||
base_area_lower.contour.contains(std::get<2>(holePropagationInfos[&hole]))) {
|
||||
Polygon hole_lower = hole;
|
||||
auto && direction = std::get<1>(holePropagationInfos[&hole]);
|
||||
hole_lower.translate(direction);
|
||||
// note to shrink a hole, we need to do positive offset
|
||||
auto hole_expanded = offset(hole_lower, line_width_scaled / 2, ClipperLib::JoinType::jtSquare);
|
||||
Point farPoint = std::get<2>(holePropagationInfos[&hole]) + direction * 2;
|
||||
if (!hole_expanded.empty()) {
|
||||
base_area_lower.holes.push_back(std::move(hole_expanded[0]));
|
||||
holePropagationInfos.insert({&base_area_lower.holes.back(), {std::get<0>(holePropagationInfos[&hole]) - 1, direction, farPoint}});
|
||||
if (dist2 > max_dist) {
|
||||
max_dist = dist2;
|
||||
pt_far_on_poly = from;
|
||||
}
|
||||
break;
|
||||
if (dist2 < dist_thresh) { return true; }
|
||||
}
|
||||
}
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
// polygon pointer: depth, direction, farPoint
|
||||
std::map<const Polygon*, std::tuple<int, Point, Point>> holePropagationInfos;
|
||||
for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) {
|
||||
if (print->canceled()) break;
|
||||
m_object->print()->set_status(66, (boost::format(_L("Support: fix holes at layer %d")) % layer_nr).str());
|
||||
|
||||
const std::vector<Node*>& curr_layer_nodes = contact_nodes[layer_nr];
|
||||
TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers);
|
||||
assert(ts_layer != nullptr);
|
||||
|
||||
// skip if current layer has no points. This fixes potential crash in get_collision (see jira BBL001-355)
|
||||
if (curr_layer_nodes.empty()) continue;
|
||||
if (ts_layer->height < EPSILON) continue;
|
||||
if (ts_layer->area_groups.empty()) continue;
|
||||
|
||||
int layer_nr_lower = layer_nr - 1;
|
||||
for (layer_nr_lower; layer_nr_lower >= 0; layer_nr_lower--) {
|
||||
if (!m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->area_groups.empty()) break;
|
||||
}
|
||||
auto& area_groups_lower = m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->area_groups;
|
||||
|
||||
for (const auto& area_group : ts_layer->area_groups) {
|
||||
if (area_group.second != TreeSupportLayer::BaseType) continue;
|
||||
const auto area = area_group.first;
|
||||
for (const auto& hole : area->holes) {
|
||||
// auto hole_bbox = get_extents(hole).polygon();
|
||||
for (auto& area_group_lower : area_groups_lower) {
|
||||
if (area_group.second != TreeSupportLayer::BaseType) continue;
|
||||
auto& base_area_lower = *area_group_lower.first;
|
||||
Point pt_on_poly, pt_on_expoly, pt_far_on_poly;
|
||||
// if a hole doesn't intersect with lower layer's contours, add a hole to lower layer and move it slightly to the contour
|
||||
if (base_area_lower.contour.contains(hole.points.front()) && !intersects_contour(hole, base_area_lower, pt_on_poly, pt_on_expoly, pt_far_on_poly)) {
|
||||
Polygon hole_lower = hole;
|
||||
Point direction = normal(pt_on_expoly - pt_on_poly, line_width_scaled / 2);
|
||||
hole_lower.translate(direction);
|
||||
// note to expand a hole, we need to do negative offset
|
||||
auto hole_expanded = offset(hole_lower, -line_width_scaled / 4, ClipperLib::JoinType::jtSquare);
|
||||
if (!hole_expanded.empty()) {
|
||||
base_area_lower.holes.push_back(std::move(hole_expanded[0]));
|
||||
holePropagationInfos.insert({ &base_area_lower.holes.back(), {25, direction, pt_far_on_poly} });
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (holePropagationInfos.find(&hole) != holePropagationInfos.end() && std::get<0>(holePropagationInfos[&hole]) > 0 &&
|
||||
base_area_lower.contour.contains(std::get<2>(holePropagationInfos[&hole]))) {
|
||||
Polygon hole_lower = hole;
|
||||
auto&& direction = std::get<1>(holePropagationInfos[&hole]);
|
||||
hole_lower.translate(direction);
|
||||
// note to shrink a hole, we need to do positive offset
|
||||
auto hole_expanded = offset(hole_lower, line_width_scaled / 2, ClipperLib::JoinType::jtSquare);
|
||||
Point farPoint = std::get<2>(holePropagationInfos[&hole]) + direction * 2;
|
||||
if (!hole_expanded.empty()) {
|
||||
base_area_lower.holes.push_back(std::move(hole_expanded[0]));
|
||||
holePropagationInfos.insert({ &base_area_lower.holes.back(), {std::get<0>(holePropagationInfos[&hole]) - 1, direction, farPoint} });
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
// if roof1 interface is inside a hole, need to expand the interface
|
||||
for (auto &roof1 : ts_layer->roof_1st_layer) {
|
||||
for (auto& roof1 : ts_layer->roof_1st_layer) {
|
||||
//if (hole.contains(roof1.contour.points.front()) && hole.contains(roof1.contour.bounding_box().center()))
|
||||
bool is_inside_hole = std::all_of(roof1.contour.points.begin(), roof1.contour.points.end(), [&hole](Point &pt) { return hole.contains(pt); });
|
||||
bool is_inside_hole = std::all_of(roof1.contour.points.begin(), roof1.contour.points.end(), [&hole](Point& pt) { return hole.contains(pt); });
|
||||
if (is_inside_hole) {
|
||||
Polygon hole_reoriented = hole;
|
||||
if (roof1.contour.is_counter_clockwise())
|
||||
hole_reoriented.make_counter_clockwise();
|
||||
else if (roof1.contour.is_clockwise())
|
||||
hole_reoriented.make_clockwise();
|
||||
auto tmp = union_({roof1.contour}, {hole_reoriented});
|
||||
auto tmp = union_({ roof1.contour }, { hole_reoriented });
|
||||
if (!tmp.empty()) roof1.contour = tmp[0];
|
||||
|
||||
// make sure 1) roof1 and object 2) roof1 and roof, won't intersect
|
||||
|
@ -2163,38 +2349,38 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
|||
tmp1 = diff_ex(tmp1, ts_layer->roof_areas);
|
||||
if (!tmp1.empty()) {
|
||||
roof1.contour = std::move(tmp1[0].contour);
|
||||
roof1.holes = std::move(tmp1[0].holes);
|
||||
}
|
||||
roof1.holes = std::move(tmp1[0].holes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||
for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) {
|
||||
TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers);
|
||||
ExPolygons& base_areas = ts_layer->base_areas;
|
||||
ExPolygons& roof_areas = ts_layer->roof_areas;
|
||||
ExPolygons& roof_1st_layer = ts_layer->roof_1st_layer;
|
||||
ExPolygons& floor_areas = ts_layer->floor_areas;
|
||||
if (base_areas.empty() && roof_areas.empty() && roof_1st_layer.empty()) continue;
|
||||
char fname[10]; sprintf(fname, "%d_%.2f", layer_nr, ts_layer->print_z);
|
||||
draw_contours_and_nodes_to_svg(-1, base_areas, roof_areas, roof_1st_layer, {}, {}, get_svg_filename(fname, "circles"), {"base", "roof", "roof1st"});
|
||||
}
|
||||
for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) {
|
||||
TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers);
|
||||
ExPolygons& base_areas = ts_layer->base_areas;
|
||||
ExPolygons& roof_areas = ts_layer->roof_areas;
|
||||
ExPolygons& roof_1st_layer = ts_layer->roof_1st_layer;
|
||||
ExPolygons& floor_areas = ts_layer->floor_areas;
|
||||
if (base_areas.empty() && roof_areas.empty() && roof_1st_layer.empty()) continue;
|
||||
char fname[10]; sprintf(fname, "%d_%.2f", layer_nr, ts_layer->print_z);
|
||||
draw_contours_and_nodes_to_svg(-1, base_areas, roof_areas, roof_1st_layer, {}, {}, get_svg_filename(fname, "circles"), { "base", "roof", "roof1st" });
|
||||
}
|
||||
#endif
|
||||
|
||||
TreeSupportLayerPtrs& ts_layers = m_object->tree_support_layers();
|
||||
auto iter = std::remove_if(ts_layers.begin(), ts_layers.end(), [](TreeSupportLayer* ts_layer) { return ts_layer->height < EPSILON; });
|
||||
ts_layers.erase(iter, ts_layers.end());
|
||||
for (int layer_nr = 0; layer_nr < ts_layers.size(); layer_nr++) {
|
||||
ts_layers[layer_nr]->upper_layer = layer_nr != ts_layers.size() - 1 ? ts_layers[layer_nr + 1] : nullptr;
|
||||
ts_layers[layer_nr]->lower_layer = layer_nr > 0 ? ts_layers[layer_nr - 1] : nullptr;
|
||||
}
|
||||
TreeSupportLayerPtrs& ts_layers = m_object->tree_support_layers();
|
||||
auto iter = std::remove_if(ts_layers.begin(), ts_layers.end(), [](TreeSupportLayer* ts_layer) { return ts_layer->height < EPSILON; });
|
||||
ts_layers.erase(iter, ts_layers.end());
|
||||
for (int layer_nr = 0; layer_nr < ts_layers.size(); layer_nr++) {
|
||||
ts_layers[layer_nr]->upper_layer = layer_nr != ts_layers.size() - 1 ? ts_layers[layer_nr + 1] : nullptr;
|
||||
ts_layers[layer_nr]->lower_layer = layer_nr > 0 ? ts_layers[layer_nr - 1] : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue