diff --git a/src/libslic3r/CutSurface.cpp b/src/libslic3r/CutSurface.cpp
index 07eb0949e9..e8f2f3caf6 100644
--- a/src/libslic3r/CutSurface.cpp
+++ b/src/libslic3r/CutSurface.cpp
@@ -455,42 +455,6 @@ 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.
-///
-/// AOIs
-/// triangle model
-/// 2d cutted shapes
-/// 2d cutted shapes
-/// Projection from 2d to 3d
-/// Identify source of intersection
-void filter_cuts(CutAOIs &cuts,
- const CutMesh &mesh,
- const ExPolygons &shapes,
- const ShapePoint2index &shape_point_2_index,
- const Project &projection,
- const VertexShapeMap &vert_shape_map);
-
using ConvertMap = CutMesh::Property_map;
///
/// Create surface cuts from mesh model
@@ -509,7 +473,6 @@ SurfaceCuts create_surface_cuts(const CutAOIs &cutAOIs,
const ReductionMap &reduction_map,
ConvertMap &convert_map);
-
///
/// Collect connected inside faces
/// Collect outline half edges
@@ -602,6 +565,23 @@ SurfaceCut::CutContour create_cut(const std::vector &outlines,
const ReductionMap &reduction_map,
const ConvertMap &v2v);
+///
+/// Self Intersection of surface cuts are made by
+/// damaged models OR multi volumes emboss
+///
+/// Surface cuts to merge
+/// NOTE: Merge process move data from cuts to result
+/// Merged all surface cuts into one
+SurfaceCut merge_intersections(SurfaceCuts &cuts);
+
+///
+/// Merge 2 Cuts when has intersection
+///
+/// In/Out cut to merge into
+/// Cut to merge from
+/// Has intersection
+bool merge_intersection(SurfaceCut &cut1, const SurfaceCut &cut2);
+
#ifdef DEBUG_OUTPUT_DIR
indexed_triangle_set create_indexed_triangle_set(const std::vector &faces,
const CutMesh &mesh);
@@ -757,31 +737,31 @@ SurfaceCut Slic3r::cut_surface(const indexed_triangle_set &model,
cutAOIs.erase(cutAOIs.begin() + index);
}
-// 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);
-
// conversion map between vertex index in cgal_model and indices in result
// used instead of std::map
std::string vertec_convert_map_name = "v:convert";
priv::ConvertMap vertex_convert_map = cgal_model.add_property_map(vertec_convert_map_name).first;
- SurfaceCuts result = priv::create_surface_cuts(cutAOIs, cgal_model, vertex_reduction_map, vertex_convert_map);
-
+ SurfaceCuts result = priv::create_surface_cuts(cutAOIs, cgal_model, vertex_reduction_map, vertex_convert_map);
#ifdef DEBUG_OUTPUT_DIR
priv::store(result, DEBUG_OUTPUT_DIR + "cuts/"); // only debug
#endif // DEBUG_OUTPUT_DIR
+ // Self Intersection of surface cuts
+ // It is made by damaged models and multi volumes
+
+ priv::merge_intersections(result);
+
+ // 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
+
// TODO: fill skipped source triangles to surface of cut
return merge(std::move(result));
}
@@ -2327,66 +2307,43 @@ 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
-
+bool priv::merge_intersection(SurfaceCut &cut1, const SurfaceCut &cut2) {
return false;
}
-void priv::merge_cuts(CutAOIs &cuts,
- const CutMesh &mesh,
- const std::vector &use_cut_indices)
+SurfaceCut priv::merge_intersections(SurfaceCuts &cuts)
{
- 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
+ bbs.reserve(cuts.size());
+ for (const SurfaceCut &cut : cuts) bbs.push_back(bounding_box(cut));
- std::vector> merge_order;
- std::vector del_cuts(cuts.size(), {true});
- for (size_t cut_index : use_cut_indices) del_cuts[cut_index] = false;
+ // extend used bb by intersecting bb
+ // NOTE: after merge 2 cuts could appears
+ // new intersection on surface of merged in
+
+ std::vector finished(cuts.size(), {true});
// 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];
+ for (size_t cut_index = 0; cut_index < cuts.size(); ++cut_index)
+ {
+ if (finished[cut_index]) continue;
+ BoundingBoxf3 &result_bb = bbs[cut_index];
+ SurfaceCut &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;
+ // while exist bb intersection
do {
exist_new_extension = false;
new_merged = std::vector(cuts.size(), {false});
+ // check when exist intersection with result_bb
for (const BoundingBoxf3 &bb : bbs) {
size_t bb_index = &bb - &bbs.front();
// do not merge itself
@@ -2398,147 +2355,33 @@ void priv::merge_cuts(CutAOIs &cuts,
for (size_t i = 0; i < cuts.size(); i++) {
if (!new_merged[i]) continue;
if (!bbs[i].intersects(bb)) continue;
+ // TODO: check that really intersect by merging
has_new_intersection = true;
}
if (!has_new_intersection) continue;
}
- if(!merge_cut(cut, cuts[bb_index], mesh)) continue;
- result_bb = create_bb(cut);
+ if (!merge_intersection(cut, cuts[bb_index])) continue;
+
+ result_bb = bounding_box(cut);
merged[bb_index] = true;
- del_cuts[bb_index] = true;
+ finished[bb_index] = true;
new_merged[bb_index] = true;
- // extend result_bb
- exist_new_extension = true;
+ exist_new_extension = true;
}
is_first = false;
- } while (exist_new_extension);
+ } 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);
+ // Cuts merged in are signed in finished vector as TRUE
+ // All rest cuts must be merged simple way
+ SurfaceCut result;
+ for (size_t cut_index = 0; cut_index < cuts.size(); ++cut_index) {
+ if (finished[cut_index]) continue;
+ append(result, std::move(cuts[cut_index]));
}
+ return result;
}
-void priv::filter_cuts(CutAOIs &cuts,
- const CutMesh &mesh,
- const ExPolygons &shapes,
- const ShapePoint2index &shape_point_2_index,
- const Project &projection,
- const VertexShapeMap &vert_shape_map)
-{
- auto get_point = [&shapes, &shape_point_2_index]
- (const IntersectingElement &intersection) -> Point {
- assert(intersection.shape_point_index != std::numeric_limits::max());
- ShapePointId point_id = shape_point_2_index.calc_id(intersection.shape_point_index);
- const ExPolygon& shape = shapes[point_id.expolygons_index];
- const Polygon &p = (point_id.polygon_index == 0) ?
- shape.contour :
- shape.holes[point_id.polygon_index - 1];
- return p[point_id.point_index];
- };
-
- struct CutIndex
- {
- // index in vector into cuts
- size_t cut_index = std::numeric_limits::max();
- // vertex index inside of mesh
- VI vi;
- };
- size_t count = count_points(shapes);
- // each source point from shapes could has only one nearest projection
- std::vector indices(count);
-
- // flags which cut is not first
- std::vector del_cuts(cuts.size(), false);
-
- // check whether vertex is behind another cut
- auto is_behind = [&vert_shape_map, &indices, &del_cuts, &get_point,
- &projection, &mesh]
- (VI vi, size_t cut_index) -> bool {
- const IntersectingElement *i = vert_shape_map[vi];
-
- // Is vertex made by corefine?
- if (i == nullptr) return false;
-
- assert(i->shape_point_index != std::numeric_limits::max());
- assert(i->attr != (unsigned char)IntersectingElement::Type::undefined);
-
- // Use only straigh edge
- if (i->get_type() != IntersectingElement::Type::edge_1)
- return false;
-
- CutIndex &ci = indices[i->shape_point_index];
-
- // is first cut for vertex OR
- // is remembred cut is deleted?
- if (ci.cut_index == std::numeric_limits::max() ||
- del_cuts[ci.cut_index] ) {
- ci.cut_index = cut_index;
- ci.vi = vi;
- return false;
- }
-
- if (ci.cut_index == cut_index) {
- // In one connected triangles area are more points
- // with same source point from text contour
- //assert(ci.vi == vi);
- return false;
- }
-
- // compare distances of vertices
- Point p = get_point(*i);
- Vec3f source_point = projection.create_front_back(p).first;
- const auto &prev = mesh.point(ci.vi);
- Vec3f prev_point(prev.x(), prev.y(), prev.z());
- float prev_sq_norm = (source_point - prev_point).squaredNorm();
-
- const auto &act = mesh.point(vi);
- Vec3f act_point(act.x(), act.y(), act.z());
- float act_sq_norm = (source_point - act_point).squaredNorm();
-
- if (act_sq_norm < prev_sq_norm) {
- del_cuts[cut_index] = true;
- return true;
- }
-
- // previous cut is behind actual one
- del_cuts[ci.cut_index] = true;
- ci.cut_index = cut_index;
- ci.vi = vi;
- return false;
- };
-
- // filter small pieces
- for (const CutAOI &cut : cuts) {
- if (!has_minimal_contour_points(cut.second, vert_shape_map, mesh)) {
- size_t index = &cut - &cuts.front();
- del_cuts[index] = true;
- }
- }
-
- // filter top one cuts
- for (const CutAOI &cut : cuts) {
- size_t cut_index = &cut - &cuts.front();
- if (del_cuts[cut_index]) continue;
- const std::vector &outlines = cut.second;
- for (HI hi : outlines) {
- if (is_behind(mesh.source(hi), cut_index) ||
- is_behind(mesh.target(hi), cut_index))
- break;
- }
- }
-
- // 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);
- }
-}
-
-
SurfaceCuts priv::create_surface_cuts(const CutAOIs &cuts,
const CutMesh &mesh,
const ReductionMap &reduction_map,