From e8d8ec19908fa5e3373f9e2102c3bbabbb122ff4 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Fri, 10 Jun 2022 18:38:05 +0200 Subject: [PATCH] Merge cuts first part --- src/libslic3r/CutSurface.cpp | 170 +++++++++++++++++++++++++++-------- 1 file changed, 132 insertions(+), 38 deletions(-) diff --git a/src/libslic3r/CutSurface.cpp b/src/libslic3r/CutSurface.cpp index 1283474755..412eaa42e2 100644 --- a/src/libslic3r/CutSurface.cpp +++ b/src/libslic3r/CutSurface.cpp @@ -455,6 +455,25 @@ ProjectionDistances choose_best_distance( const BoundingBox &shapes_bb, const ShapePoint2index &shape_point_2_index); +/// +/// Merge 2 cuts together, cut off inner part +/// +/// [In/Out] surface cut +/// Cut to intersect with +/// Source of surface +/// True when merge otherwise False +bool merge_cut(CutAOI &cut1, const CutAOI &cut2, const CutMesh &mesh); + +/// +/// Merge cuts together +/// +/// [In/Out] cutted surface of model +/// Source of surface +/// Filtered indicies of Cut from best projection distances +void merge_cuts(CutAOIs &cuts, + const CutMesh &mesh, + const std::vector &use_cut_indices); + /// /// Filter out cuts which are behind another. /// Prevent overlapping embossed shape in space. @@ -707,6 +726,9 @@ SurfaceCut Slic3r::cut_surface(const indexed_triangle_set &model, // for each point collect all projection distances std::vector distances = priv::create_distances(cutAOIs, cgal_model, shapes_points, cgal_shape, projection_ratio, vert_shape_map); + + // NOTE: it will be fine to calc AOIs range, + // not only outline but all vertices in direction of emboss - faster check on intersection #ifdef DEBUG_OUTPUT_DIR auto [front,back] = projection.create_front_back(shapes_bb.center()); @@ -722,6 +744,20 @@ SurfaceCut Slic3r::cut_surface(const indexed_triangle_set &model, priv::store(best_projection, cutAOIs, cgal_model, DEBUG_OUTPUT_DIR + "best_projection.obj"); // only debug #endif // DEBUG_OUTPUT_DIR + std::vector is_best_cut(cutAOIs.size(), {false}); + for (const priv::ProjectionDistance &d : best_projection) + is_best_cut[d.aoi_index] = true; + std::vector best_cut_indices; + for (size_t i = 0; i < cutAOIs.size(); ++i) + if (is_best_cut[i]) best_cut_indices.push_back(i); + + // cut off part + filtrate cutAOIs + priv::merge_cuts(cutAOIs, cgal_model, best_cut_indices); +#ifdef DEBUG_OUTPUT_DIR + priv::store(cutAOIs, cgal_model, DEBUG_OUTPUT_DIR + "merged-aois/"); + // only debug +#endif // DEBUG_OUTPUT_DIR + // Filter out NO top one cuts priv::filter_cuts(cutAOIs, cgal_model, shapes, shape_point_2_index, projection, vert_shape_map); @@ -1877,14 +1913,13 @@ std::vector priv::create_distances( for (size_t i = 0; i < 3; i++) { float val = start[i] - end[i]; // abs value - if (val < 0.f) val *= -1; + if (val < 0.f) val *= -1.f; if (max_val < val) { max_val = val; max_i = i; } } - float ratio = (p[max_i] - start[max_i]) / max_val; - return (ratio - projection_ratio) * max_val; + return (p[max_i] - start[max_i]) - projection_ratio * (end[max_i] - start[max_i]); }; std::vector distances(shapes_points); @@ -1902,17 +1937,6 @@ std::vector priv::create_distances( ProjectionDistance pd; pd.aoi_index = &cut - &cuts.front(); pd.hi_index = &hi - &cut.second.front(); - // Option to not calculate distance when exist only one AOI - //if (pds.empty()) { - // // first is without calc of distance - // pds.push_back(std::move(pd)); - // continue; - //} else if (pds.size() == 1) { - // // calculate distance first item - // ProjectionDistance &prev = pds.front(); - // HI hi = cuts[prev.aoi_index].second[prev.hi_index]; - // prev.distance = calc_distance(pi, mesh.source(hi)); - //} pd.distance = calc_distance(pi, vi); pds.push_back(std::move(pd)); } @@ -1920,30 +1944,6 @@ std::vector priv::create_distances( return distances; } -//uint32_t get_closest_point_id(const ExPolygons &shapes, const Point &p) { -// float distance_sq = std::numeric_limits::max(); -// uint32_t closest_id{0}; -// uint32_t id{0}; -// auto get_closest = [&p, &id, &closest_id, &distance_sq](const Points &pts) { -// for (const Point &p_ : pts) { -// Point dp = p - p_; -// float d = dp.x() * dp.x() + dp.y() * dp.y(); -// if (distance_sq > d) { -// distance_sq = d; -// closest_id = id; -// } -// ++id; -// } -// }; -// -// for (const ExPolygon &shape : shapes) { -// get_closest(shape.contour.points); -// for (const Polygon &hole : shape.holes) -// get_closest(hole.points); -// } -// return closest_id; -//} - priv::ProjectionDistances priv::choose_best_distance( const std::vector &distances, const ExPolygons &shapes, @@ -2317,6 +2317,100 @@ void priv::store(const Vec3f &vertex, its_write_obj(its, file.c_str()); } +bool priv::merge_cut(CutAOI &cut1, const CutAOI &cut2, const CutMesh &mesh) +{ + // create cgal model and merge it together + + return false; +} + +void priv::merge_cuts(CutAOIs &cuts, + const CutMesh &mesh, + const std::vector &use_cut_indices) +{ + auto create_bb = [&mesh](const CutAOI &cut) -> BoundingBoxf3 { + Vec3f min(std::numeric_limits::min(), + std::numeric_limits::min(), + std::numeric_limits::min()); + Vec3f max(std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()); + for (const FI &fi : cut.first) { + HI hi = mesh.halfedge(fi); + for (VI vi : {mesh.source(hi), mesh.target(hi), + mesh.target(mesh.next(hi))}) { + const P3 &p = mesh.point(vi); + for (size_t i = 0; i < 3; i++) { + if (min[i] > p[i]) min[i] = p[i]; + if (max[i] < p[i]) max[i] = p[i]; + } + } + } + return BoundingBoxf3(min.cast(), max.cast()); + }; + + // create bounding boxes for cuts + std::vector bbs; + bbs.reserve(cuts.size()); + for (const CutAOI &cut : cuts) + bbs.push_back(create_bb(cut)); + // extend used bb by intersecting bb + // NOTE: after merge 2 cuts could appear new intersection on surface of merged in + + std::vector> merge_order; + std::vector del_cuts(cuts.size(), {true}); + for (size_t cut_index : use_cut_indices) del_cuts[cut_index] = false; + + // find intersection of cuts by Bounding boxes intersection + for (size_t cut_index : use_cut_indices) { + // check if cut is merged into another one + if (del_cuts[cut_index]) continue; + BoundingBoxf3& result_bb = bbs[cut_index]; + CutAOI &cut = cuts[cut_index]; + // all merged cuts into cut_index + std::vector merged(cuts.size(), {false}); + + // merged in last iteration + std::vector new_merged; + bool exist_new_extension; + bool is_first = true; + do { + exist_new_extension = false; + new_merged = std::vector(cuts.size(), {false}); + for (const BoundingBoxf3 &bb : bbs) { + size_t bb_index = &bb - &bbs.front(); + // do not merge itself + if (cut_index == bb_index) continue; + if (!is_first && merged[cut_index]) continue; + if (!bb.intersects(result_bb)) { + if (is_first) continue; + bool has_new_intersection = false; + for (size_t i = 0; i < cuts.size(); i++) { + if (!new_merged[i]) continue; + if (!bbs[i].intersects(bb)) continue; + has_new_intersection = true; + } + if (!has_new_intersection) continue; + } + if(!merge_cut(cut, cuts[bb_index], mesh)) continue; + result_bb = create_bb(cut); + merged[bb_index] = true; + del_cuts[bb_index] = true; + new_merged[bb_index] = true; + // extend result_bb + exist_new_extension = true; + } + is_first = false; + } while (exist_new_extension); + } + + // remove flagged cuts + for (size_t i = del_cuts.size(); i > 0; --i) { + size_t index = i - 1; + if (del_cuts[index]) cuts.erase(cuts.begin() + index); + } +} + void priv::filter_cuts(CutAOIs &cuts, const CutMesh &mesh, const ExPolygons &shapes,