reconstruction of polygon from vertical slices TODO

This commit is contained in:
Pavel Mikus 2023-02-10 20:15:12 +01:00 committed by PavelMikus
parent ebcedca211
commit a57f98961e

View file

@ -2,6 +2,7 @@
#include "BridgeDetector.hpp"
#include "ExPolygon.hpp"
#include "Exception.hpp"
#include "Flow.hpp"
#include "KDTreeIndirect.hpp"
#include "Point.hpp"
#include "Polygon.hpp"
@ -1533,7 +1534,9 @@ void PrintObject::bridge_over_infill()
{
BOOST_LOG_TRIVIAL(info) << "Bridge over infill - Start" << log_memory_info();
tbb::parallel_for(tbb::blocked_range<size_t>(0, this->layers().size()), [po = this](tbb::blocked_range<size_t> r) {
tbb::parallel_for(
tbb::blocked_range<size_t>(0, this->layers().size()),
[po = this](tbb::blocked_range<size_t> r) {
for (size_t lidx = r.begin(); lidx < r.end(); lidx++) {
const Layer *layer = po->get_layer(lidx);
@ -1543,7 +1546,7 @@ void PrintObject::bridge_over_infill()
std::unordered_map<const LayerSlice *, SurfacesPtr> bridging_surface_candidates;
std::unordered_map<const LayerSlice *, SurfacesPtr> expansion_space;
std::unordered_map<const LayerSlice *, float> max_bridge_flow_height;
std::unordered_map<const LayerSlice *, float> max_bridge_flow_width;
std::unordered_map<const Surface *, const LayerRegion *> surface_to_region;
for (const LayerSlice &slice : layer->lslices_ex) {
std::unordered_set<size_t> regions_to_check;
for (const LayerIsland &island : slice.islands) {
@ -1559,13 +1562,15 @@ void PrintObject::bridge_over_infill()
if (!region_internal_solids.empty()) {
max_bridge_flow_height[&slice] = std::max(max_bridge_flow_height[&slice],
region->bridging_flow(frSolidInfill).height());
max_bridge_flow_width[&slice] = std::max(max_bridge_flow_width[&slice],
region->bridging_flow(frSolidInfill).width());
}
bridging_surface_candidates[&slice].insert(bridging_surface_candidates[&slice].end(), region_internal_solids.begin(),
region_internal_solids.end());
for (const Surface *s : region_internal_solids) {
surface_to_region[s] = region;
}
bridging_surface_candidates[&slice].insert(bridging_surface_candidates[&slice].end(),
region_internal_solids.begin(), region_internal_solids.end());
auto region_sparse_infill = region->fill_surfaces().filter_by_type(stInternal);
expansion_space[&slice].insert(expansion_space[&slice].end(), region_sparse_infill.begin(), region_sparse_infill.end());
expansion_space[&slice].insert(expansion_space[&slice].end(), region_sparse_infill.begin(),
region_sparse_infill.end());
}
}
@ -1640,6 +1645,7 @@ void PrintObject::bridge_over_infill()
// bridging. These areas we then expand (within the surrounding sparse infill only!)
// to touch the infill polylines on previous layer.
for (const Surface *candidate : candidates.second) {
const Flow &flow = surface_to_region[candidate]->bridging_flow(frSolidInfill);
assert(candidate->surface_type == stInternalSolid);
Polygons bridged_area = to_polygons(candidate->expolygon);
bridged_area =
@ -1652,21 +1658,19 @@ void PrintObject::bridge_over_infill()
Polygons max_area = expand_area;
max_area.insert(max_area.end(), bridged_area.begin(), bridged_area.end());
closing(max_area, max_bridge_flow_width[candidates.first]);
closing(max_area, flow.scaled_width());
Polylines anchors = intersection_pl(lower_layer_polylines, max_area);
anchors = diff_pl(anchors, shrink(bridged_area, scale_(max_bridge_flow_width[candidates.first])));
anchors = diff_pl(anchors, shrink(bridged_area, flow.scaled_width()));
AABBTreeLines::LinesDistancer<Line> anchors_and_walls;
{
Lines tmp = to_lines(anchors);
Lines tmp2 = to_lines(max_area);
tmp.insert(tmp.end(), tmp.begin(), tmp.end());
anchors_and_walls = AABBTreeLines::LinesDistancer<Line>{tmp};
}
Lines anchors_and_walls = to_lines(anchors);
Lines tmp = to_lines(max_area);
tmp.insert(anchors_and_walls.end(), tmp.begin(), tmp.end());
double bridging_dir = 0;
double bridging_angle = 0;
{
AABBTreeLines::LinesDistancer<Line> lines_tree{anchors_and_walls};
std::vector<std::pair<double, double>> directions_with_distances;
for (const Polygon &p : bridged_area) {
for (int point_idx = 0; point_idx < int(p.points.size()) - 1; ++point_idx) {
@ -1679,8 +1683,8 @@ void PrintObject::bridge_over_infill()
float step_size = dist_to_next / lines_count;
for (int i = 0; i < lines_count; ++i) {
Point a(start + v * (i * step_size));
auto [distance, index, p] = anchors_and_walls.distance_from_lines_extra<false>(a);
const Line& l = anchors_and_walls.get_line(index);
auto [distance, index, p] = lines_tree.distance_from_lines_extra<false>(a);
const Line &l = lines_tree.get_line(index);
directions_with_distances.emplace_back(PI - l.direction(), unscaled(distance));
}
}
@ -1691,27 +1695,111 @@ void PrintObject::bridge_over_infill()
}
double acc = 0;
for (const auto &dir : directions_with_distances) {
bridging_dir += dir.first * (max_dist - dir.second);
bridging_angle += dir.first * (max_dist - dir.second);
acc += (max_dist - dir.second);
}
bridging_dir /= acc;
bridging_angle /= acc;
}
//TODO use get_extens_rotated on the bridged_area polygons, generate vertical lines of the box,
// OR maybe get extens of rotated max_area, then fill with vertical lines, make AABB tree rotated for anchors and walls and also
// TODO maybe get extens of rotated max_area, then fill with vertical lines, make AABB tree rotated for anchors and
// walls and also
// for bridged area
// then cut off the vertical lines, compose the final polygon, and rotate back
auto lines_rotate = [](Lines &lines, double cos_angle, double sin_angle) {
for (Line &l : lines) {
double ax = double(l.a.x());
double ay = double(l.a.y());
l.a.x() = coord_t(round(cos_angle * ax - sin_angle * ay));
l.a.y() = coord_t(round(cos_angle * ay + sin_angle * ax));
double bx = double(l.b.x());
double by = double(l.b.y());
l.b.x() = coord_t(round(cos_angle * bx - sin_angle * by));
l.b.y() = coord_t(round(cos_angle * by + sin_angle * bx));
}
};
Polygons expanded_bridged_area{};
{
polygons_rotate(bridged_area, bridging_angle);
lines_rotate(anchors_and_walls, cos(bridging_angle), sin(bridging_angle));
BoundingBox bb_x = get_extents(bridged_area);
BoundingBox bb_y = get_extents(anchors_and_walls);
const size_t n_vlines = (bb_x.max.x() - bb_x.min.x() + flow.scaled_spacing() - 1) / flow.scaled_spacing();
std::vector<Line> vertical_lines(n_vlines);
for (size_t i = 0; i < n_vlines; i++) {
coord_t x = bb_x.min.x() + i * flow.scaled_spacing();
coord_t y_min = bb_y.min.y() - flow.scaled_spacing();
coord_t y_max = bb_y.max.y() + flow.scaled_spacing();
vertical_lines[i].a = Point{x, y_min};
vertical_lines[i].b = Point{x, y_max};
}
auto anchors_and_walls_tree = AABBTreeLines::LinesDistancer<Line>{std::move(anchors_and_walls)};
auto bridged_area_tree = AABBTreeLines::LinesDistancer<Line>{to_lines(bridged_area)};
std::vector<std::vector<std::pair<Point, Point>>> polygon_sections(n_vlines);
for (size_t i = 0; i < n_vlines; i++) {
auto area_intersections = bridged_area_tree.intersections_with_line<true>(vertical_lines[i]);
if (area_intersections.size() < 2) {
if (area_intersections.size() > 0) {
polygon_sections[i].emplace_back(area_intersections[0].first, area_intersections[0].first);
}
continue;
}
auto anchors_intersections = anchors_and_walls_tree.intersections_with_line<true>(vertical_lines[i]);
for (const auto &intersection : area_intersections) {
auto high_b = std::upper_bound(anchors_intersections.begin(), anchors_intersections.end(), intersection,
[](const std::pair<Point, size_t> left,
const std::pair<Point, size_t> right) {
return left.first.y() > right.first.y();
});
Point low, high;
if (high_b == anchors_intersections.end()) {
assert(false); // should not happen
continue;
} else if (high_b == anchors_intersections.begin()) {
low = high_b->first;
high = (++high_b)->first;
} else {
low = (--high_b)->first;
high = high_b->first;
}
if (polygon_sections[i].size() > 0 && polygon_sections[i].back().second.y() >= low.y()) {
polygon_sections[i].back().second = high;
} else {
polygon_sections[i].emplace_back(low, high);
}
}
}
//reconstruct polygon from polygon sections
struct TracedPoly {
std::vector<Point> lows;
std::vector<Point> highs;
};
std::vector<TracedPoly> traced_polys;
for (const auto& layer : polygon_sections) {
for ()
}
}
}
} // surface iteration end
} // island iteration end
} // layer iteration end
});
);
BOOST_LOG_TRIVIAL(info) << "Bridge over infill - End" << log_memory_info();
} // void PrintObject::bridge_over_infill()
void a(){
void a()
{
std::vector<int> sparse_infill_regions;
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id)
if (const PrintRegion &region = this->printing_region(region_id); region.config().fill_density.value < 100)