From 89f6df6da16e1b99bc6fba73ab7b6610007ca535 Mon Sep 17 00:00:00 2001 From: Filip Sykala - NTB T15p Date: Sat, 2 Jul 2022 09:27:27 +0200 Subject: [PATCH] Start using CGAL::clip verify it could be used as tool for difference a mdoel patch in AOI --- src/libslic3r/CutSurface.cpp | 520 ++++++++++++----------------------- 1 file changed, 182 insertions(+), 338 deletions(-) diff --git a/src/libslic3r/CutSurface.cpp b/src/libslic3r/CutSurface.cpp index 699089f572..5d0635232e 100644 --- a/src/libslic3r/CutSurface.cpp +++ b/src/libslic3r/CutSurface.cpp @@ -201,9 +201,11 @@ void set_skip_for_out_of_aoi(std::vector &skip_indicies, /// /// Model /// Flags that triangle should be skiped +/// When true triangle will flip normal /// CGAL mesh - half edge mesh CutMesh to_cgal(const indexed_triangle_set &its, - const std::vector &skip_indicies); + const std::vector &skip_indicies, + bool flip = false); /// /// Convert triangle mesh model to CGAL Surface_mesh @@ -714,11 +716,17 @@ SurfaceCut Slic3r::cut_surface(const ExPolygons &shapes, // for filttrate opposite triangles and a little more const float max_angle = 89.f; - priv::CutMeshes cgal_models; + priv::CutMeshes cgal_models; // source for patch + priv::CutMeshes cgal_neg_models; // model used for differenciate patches cgal_models.reserve(models.size()); for (const indexed_triangle_set &its : models) { std::vector skip_indicies(its.indices.size(), {false}); priv::set_skip_for_out_of_aoi(skip_indicies, its, projection, shapes_bb); + + // create model for differenciate cutted patches + bool flip = true; + cgal_neg_models.push_back(priv::to_cgal(its, skip_indicies, flip)); + // cut out opposit triangles // priv::set_skip_for_outward_projection(skip_indicies, model, projection); // cut out more than only opposit triangles @@ -731,7 +739,6 @@ SurfaceCut Slic3r::cut_surface(const ExPolygons &shapes, #endif // DEBUG_OUTPUT_DIR priv::CutMesh cgal_shape = priv::to_cgal(shapes, projection); - #ifdef DEBUG_OUTPUT_DIR CGAL::IO::write_OFF(DEBUG_OUTPUT_DIR + "shape.off", cgal_shape); // only debug #endif // DEBUG_OUTPUT_DIR @@ -739,8 +746,6 @@ SurfaceCut Slic3r::cut_surface(const ExPolygons &shapes, // create tool for convert index to shape Point adress and vice versa priv::ShapePoint2index s2i(shapes); - // create copy of source models for cut intersections - priv::CutMeshes cgal_models_copy = cgal_models; priv::VCutAOIs model_cuts; // cut shape from each cgal model for (priv::CutMesh &cgal_model : cgal_models) { @@ -773,8 +778,9 @@ SurfaceCut Slic3r::cut_surface(const ExPolygons &shapes, std::vector is_best_cut(m2i.get_count(), {false}); for (const priv::ProjectionDistance& d : best_projection) if (d.model_index != std::numeric_limits::max()) - is_best_cut[m2i.calc_index({d.model_index, d.aoi_index})] = true; - priv::diff_models(model_cuts, is_best_cut, m2i, cgal_models, cgal_models_copy); + is_best_cut[m2i.calc_index({d.model_index, d.aoi_index})] = true; + + priv::diff_models(model_cuts, is_best_cut, m2i, cgal_models, cgal_neg_models); // IMPROVE: create reduce map on demand - may be model do not need it (when it is not used for result) // Reduction prepare @@ -1070,6 +1076,7 @@ void priv::set_skip_for_out_of_aoi(std::vector &skip_indicies, // 2 .. above // 3 .. right size_t prev_i = 3; + // plane is defined by point and normal std::array, 4> point_normals; for (size_t i = 0; i < 4; i++) { const Vec3f &p1 = bb[i].first; @@ -1164,7 +1171,8 @@ priv::CutMesh priv::to_cgal(const indexed_triangle_set &its, size_t edges_count) } priv::CutMesh priv::to_cgal(const indexed_triangle_set &its, - const std::vector &skip_indicies) + const std::vector &skip_indicies, + bool flip) { const std::vector &vertices = its.vertices; const std::vector &indices = its.indices; @@ -1205,11 +1213,11 @@ priv::CutMesh priv::to_cgal(const indexed_triangle_set &its, CutMesh result; result.reserve(vertices_count, edges_count, faces_count); - std::vector to_filtrated_vertices_index(vertices.size()); + std::vector to_filtrated_vertices_index(vertices.size()); size_t filtrated_vertices_index = 0; for (size_t i = 0; i < vertices.size(); ++i) if (use_vetices[i]) { - to_filtrated_vertices_index[i] = filtrated_vertices_index; + to_filtrated_vertices_index[i] = VI(filtrated_vertices_index); ++filtrated_vertices_index; } @@ -1218,11 +1226,20 @@ priv::CutMesh priv::to_cgal(const indexed_triangle_set &its, result.add_vertex(CutMesh::Point{v.x(), v.y(), v.z()}); } - for (const stl_triangle_vertex_indices &f : indices) { - if (!use_indices[&f - &indices.front()]) continue; - result.add_face(static_cast(to_filtrated_vertices_index[f[0]]), - static_cast(to_filtrated_vertices_index[f[1]]), - static_cast(to_filtrated_vertices_index[f[2]])); + if (!flip) { + for (const stl_triangle_vertex_indices &f : indices) { + if (!use_indices[&f - &indices.front()]) continue; + result.add_face(to_filtrated_vertices_index[f[0]], + to_filtrated_vertices_index[f[1]], + to_filtrated_vertices_index[f[2]]); + } + } else { + for (const stl_triangle_vertex_indices &f : indices) { + if (!use_indices[&f - &indices.front()]) continue; + result.add_face(to_filtrated_vertices_index[f[2]], + to_filtrated_vertices_index[f[1]], + to_filtrated_vertices_index[f[0]]); + } } return result; @@ -2499,7 +2516,7 @@ priv::ProjectionDistances priv::choose_best_distance( return result; } -// functions to help 'merge_intersection' +// functions to help 'diff_model' namespace priv { const VI default_vi(std::numeric_limits::max()); @@ -2508,9 +2525,9 @@ struct Source HI hi; int sdim; }; -using Sources = std::vector; +using Sources = std::vector; const std::string vertex_source_map_name = "v:SourceIntersecting"; -using VertexSourceMap = CutMesh::Property_map; +using VertexSourceMap = CutMesh::Property_map; /// /// Corefine visitor @@ -2526,38 +2543,51 @@ struct IntersectionSources // keep sources from call intersection_point_detected // until call new_vertex_added - Sources m_sources; + Sources* sources; // count intersections - void intersection_point_detected(std::size_t i_id, int sdim, HI h_f, HI h_e, - const CutMesh &tm_f, const CutMesh &tm_e, bool is_target_coplanar, bool is_source_coplanar){ + void intersection_point_detected(std::size_t i_id, + int sdim, + HI h_f, + HI h_e, + const CutMesh &tm_f, + const CutMesh &tm_e, + bool is_target_coplanar, + bool is_source_coplanar) + { Source source; if (&tm_e == model) { - source = {h_e, sdim}; + source = {h_e, sdim}; // check other CGAL model that is patch assert(&tm_f == patch); - if (is_target_coplanar) vmap[tm_f.source(h_f)] = source; - if (is_source_coplanar) vmap[tm_f.target(h_f)] = source; + if (is_target_coplanar) { + assert(sdim == 0); + vmap[tm_f.source(h_f)] = source; + } + if (is_source_coplanar) { + assert(sdim == 0); + vmap[tm_f.target(h_f)] = source; + } - // clear source to be able check that this intersection source is not used any more + // clear source to be able check that this intersection source is + // not used any more if (is_source_coplanar || is_target_coplanar) source = {}; } else { source = {h_f, sdim}; assert(&tm_f == model && &tm_e == patch); assert(!is_target_coplanar); assert(!is_source_coplanar); - //if (is_target_coplanar) vmap[tm_e.source(h_e)] = source; - //if (is_source_coplanar) vmap[tm_e.target(h_e)] = source; - //if (sdim == 0) - // vmap[tm_e.target(h_e)] = source; + // if (is_target_coplanar) vmap[tm_e.source(h_e)] = source; + // if (is_source_coplanar) vmap[tm_e.target(h_e)] = source; + // if (sdim == 0) + // vmap[tm_e.target(h_e)] = source; } - // add source of intersection - m_sources.push_back(source); - // By documentation i_id is consecutive. // check id goes in a row, without skips - assert(m_sources.size() == i_id); + assert(sources->size() == i_id); + // add source of intersection + sources->push_back(source); } /// @@ -2566,14 +2596,15 @@ struct IntersectionSources /// Order number of intersection point /// New added vertex /// Affected mesh - void new_vertex_added(std::size_t i_id, VI v, const CutMesh &tm) { + void new_vertex_added(std::size_t i_id, VI v, const CutMesh &tm) + { // check that it is first insertation into item of vmap assert(!vmap[v].hi.is_valid()); // check valid addresing into sources - assert(i_id < m_sources.size()); + assert(i_id < sources->size()); // check that source has value - assert(m_sources[i_id].hi.is_valid()); - vmap[v] = m_sources[i_id]; + assert(sources->at(i_id).hi.is_valid()); + vmap[v] = sources->at(i_id); } // Not used visitor functions @@ -2595,275 +2626,41 @@ struct IntersectionSources /// Source of intersection /// Identify constrainde edge /// Convert tm1.face to type -void create_face_types(FaceTypeMap& map, const CutMesh &tm1,const CutMesh &tm2, const EcmType &ecm, const VertexSourceMap& sources); +void create_face_types(FaceTypeMap &map, + const CutMesh &tm1, + const CutMesh &tm2, + const EcmType &ecm, + const VertexSourceMap &sources); -/// -/// Create map1 and map2 -/// -/// First mesh -/// First map -/// Second mesh -/// Second map -/// Cvt vertex 1 to vertex 2 -/// Identify constrainde edge -//void create_face_types(const CutMesh &tm1, FaceTypeMap& map1, const CutMesh &tm2, const EcmType &ecm1); - -//// Convert vertex index to indexed_triangle_set::index (index of vertext) -//using V2I_map = CutMesh::Property_map; -// -//// Create its from merged CGAL models(without outline) -//indexed_triangle_set create_merged_its( -// const CutMesh &tm1, const FaceTypeMap &map1, V2I_map &vi1_to_res, -// const CutMesh &tm2, const FaceTypeMap &map2, V2I_map &vi2_to_res, const V2V_map &vi1_to_vi2); -} - -//priv::V2V_map priv::create_map_from_vi1_to_vi2( -// CutMesh &tm1, -// const Store_VI_pairs::Pairs &intersections, -// const std::string &map_name) -//{ -// // Create conversion map from tm1.vertex to tm2.vertex on constrained edge -// V2V_map vi2vi_map = tm1.add_property_map(map_name).first; -// // initialize to default value -// for (VI vi : tm1.vertices()) vi2vi_map[vi] = default_vi; -// // fill data by intersections -// for (const std::pair &intersection : intersections) { -// // weird intersection?? what does it mean ?? -// if (intersection.first == default_vi || -// intersection.second == default_vi) -// continue; -// -// // is intersection point used only once? -// assert(vi2vi_map[intersection.first] == default_vi); -// vi2vi_map[intersection.first] = intersection.second; -// } -// return vi2vi_map; -//} - -//void priv::create_face_types(const CutMesh &tm1, -// FaceTypeMap &map1, -// const CutMesh &tm2, -// const EcmType &ecm1) -//{ -// // initialize maps -// for (FI fi : tm1.faces()) map1[fi] = FaceType::not_constrained; -// for (EI ei1 : tm1.edges()) { -// if (!get(ecm1, ei1)) continue; -// -// // get faces from tm1 (f1a + f1b) -// HI hi1 = tm1.halfedge(ei1); -// assert(hi1.is_valid()); -// FI f1a = tm1.face(hi1); -// assert(f1a.is_valid()); -// HI hi_op = tm1.opposite(hi1); -// assert(hi_op.is_valid()); -// FI f1b = tm1.face(hi_op); -// assert(f1b.is_valid()); -// -// // get faces from tm2 (f2a + f2b) -// VI vi1_source = tm1.source(hi1); -// assert(vi1_source.is_valid()); -// VI vi1_target = tm1.target(hi1); -// assert(vi1_target.is_valid()); -// -// // Need to know source triangle of intersection-----------------------------<<<<<<<<<<<<<<< -// -// VI vi2_source = vi1_to_vi2[vi1_source]; -// assert(vi2_source != default_vi); -// assert(vi2_source.is_valid()); -// VI vi2_target = vi1_to_vi2[vi1_target]; -// assert(vi2_target != default_vi); -// assert(vi2_target.is_valid()); -// -// // target(halfedge(v)) == v -// HI hi2_target = tm2.halfedge(vi2_target); -// HI hi2; // half edge on tm2 in same position as hi -// for (HI hi : tm2.halfedges_around_target(hi2_target)) { -// if (tm2.source(hi) != vi2_source) continue; -// hi2 = hi; -// break; -// } -// -// assert(hi2.is_valid()); -// FI f2a = tm2.face(hi2); -// assert(f2a.is_valid()); -// HI hi2_op = tm2.opposite(hi2); -// assert(hi2_op.is_valid()); -// FI f2b = tm2.face(hi2_op); -// assert(f2a.is_valid()); -// -// // check orientation -// const P3 &a = tm1.point(vi1_source); -// const P3 &b = tm1.point(vi1_target); -// // triangle tip from face f1a -// VI vi1a_tip = tm1.target(tm1.next(hi1)); -// assert(vi1a_tip.is_valid()); -// const P3 &c = tm1.point(vi1a_tip); -// // triangle tip from face f2a -// VI vi2a_tip = tm2.target(tm2.next(hi2)); -// const P3 &p = tm2.point(vi2a_tip); -// -// // check if f1a is behinde f2a -// // inside mean it will be used -// // outside will be discarded -// if (CGAL::orientation(a, b, c, p) == CGAL::POSITIVE) { -// map1[f1a] = FaceType::outside; -// map1[f1b] = FaceType::inside; -// map2[f2a] = FaceType::inside; -// map2[f2b] = FaceType::outside; -// } else { -// map1[f1a] = FaceType::inside; -// map1[f1b] = FaceType::outside; -// map2[f2a] = FaceType::outside; -// map2[f2b] = FaceType::inside; -// } -// } -//} - -//indexed_triangle_set priv::create_merged_its( -// const CutMesh &tm1, const FaceTypeMap &map1, V2I_map &vi1_to_res, -// const CutMesh &tm2, const FaceTypeMap &map2, V2I_map &vi2_to_res, const V2V_map &vi1_to_vi2) -//{ -// // clear for sure -// const SurfaceCut::Index invalid = std::numeric_limits::max(); -// for (VI vi:tm1.vertices()) vi1_to_res[vi] = invalid; -// for (VI vi:tm2.vertices()) vi2_to_res[vi] = invalid; -// -// // count result triangles -// size_t indices_size = 0; -// for (FI fi : tm1.faces()) if (map1[fi] == FaceType::inside) ++indices_size; -// for (FI fi : tm2.faces()) if (map2[fi] == FaceType::inside) ++indices_size; -// -// // approx maximal count -// size_t vertices_count = 3 * indices_size; -// -// indexed_triangle_set result; -// result.indices.reserve(indices_size); -// result.vertices.reserve(vertices_count); -// -// // Start with tm2 because of convert map vi1_to_vi2 not vice versa -// for (FI fi : tm2.faces()) { -// if (map2[fi] != FaceType::inside) continue; -// Vec3i t; -// int i = 0; -// for (VI vi : tm2.vertices_around_face(tm2.halfedge(fi))) { -// SurfaceCut::Index &si = vi2_to_res[vi]; -// if (si == invalid) { -// si = result.vertices.size(); -// const P3 &p = tm2.point(vi); -// Vec3f p_(p.x(), p.y(), p.z()); -// result.vertices.push_back(p_); -// } -// t[i++] = si; -// } -// result.indices.push_back(t); -// } -// -// // convert tm1 without same points from tm2 defined in map vi1_to_vi2 -// for (FI fi : tm1.faces()) { -// if (map1[fi] != FaceType::inside) continue; -// Vec3i t; -// int i = 0; -// for (VI vi : tm1.vertices_around_face(tm1.halfedge(fi))) { -// SurfaceCut::Index &si = vi1_to_res[vi]; -// if (si == invalid) { -// // check if it is not already created from tm2 -// VI vi2 = vi1_to_vi2[vi]; -// if (vi2 == default_vi) { -// si = result.vertices.size(); -// const P3 &p = tm1.point(vi); -// Vec3f p_(p.x(), p.y(), p.z()); -// result.vertices.push_back(p_); -// } else { -// // constrained vertex copied from tm2 -// si = vi2_to_res[vi2]; -// assert(si != invalid); -// } -// } -// t[i++] = si; -// } -// result.indices.push_back(t); -// } -// // fix approx of vertices count -// result.vertices.shrink_to_fit(); -// return result; -//} -// -bool priv::merge_intersection(SurfaceCut &cut1, const SurfaceCut &cut2) { - return false; - //auto cut_to_cgal = [](const SurfaceCut &cut) { - // size_t count_edges = (cut.indices.size() * 3 + cut.contours.size()) / 2; - // return to_cgal(cut, count_edges); - //}; - - //CutMesh tm1 = cut_to_cgal(cut1); - //CutMesh tm2 = cut_to_cgal(cut2); - - ////Store_VI_pairs::Pairs intersections; - //Store_Source visitor = {&tm1, &tm2}; - - //// bool map for affected edge - //EcmType ecm1 = get(DynamicEdgeProperty(), tm1); - //const auto &p = CGAL::parameters::visitor(visitor) - // .edge_is_constrained_map(ecm1) - // .throw_on_self_intersection(false); - //const auto &q = CGAL::parameters::throw_on_self_intersection(false); - - //CGAL::Polygon_mesh_processing::corefine(tm1, tm2, p, q); - //// when no intersection detected than no result surface cut - //if (intersections.empty()) return false; - - //// Create conversion map from tm1.vertex to tm2.vertex on constrained edge - //std::string vi1_to_vi2_name = "v:vi1_to_vi2"; - //V2V_map vi1_to_vi2 = create_map_from_vi1_to_vi2(tm1, intersections, vi1_to_vi2_name); - - //std::string face_type_map_name = "f:side"; - //FaceTypeMap face_type_map1 = tm1.add_property_map(face_type_map_name).first; - //FaceTypeMap face_type_map2 = tm2.add_property_map(face_type_map_name).first; - //create_face_types(tm1, face_type_map1, tm2, face_type_map2, vi1_to_vi2, ecm1); - // - //std::string dir = "C:/data/temp/out/"; - //store(tm1, face_type_map1, dir + "tm1_constrained.off"); - //store(tm2, face_type_map2, dir + "tm2_constrained.off"); - //flood_fill_inner(tm1, face_type_map1); - //flood_fill_inner(tm2, face_type_map2); - //store(tm1, face_type_map1, dir + "tm1_filled.off"); - //store(tm2, face_type_map2, dir + "tm2_filled.off"); - - //std::string vi_to_res_name = "v:vertex_to_result"; - //V2I_map vi1_to_res = tm1.add_property_map(vi_to_res_name).first; - //V2I_map vi2_to_res = tm2.add_property_map(vi_to_res_name).first; - //indexed_triangle_set its = create_merged_its( - // tm1, face_type_map1, vi1_to_res, - // tm2, face_type_map2, vi2_to_res, vi1_to_vi2); - //its_write_obj(its, (dir + "merged_result.obj").c_str()); - - //// calculate contours: - // - - - //// set result into cut1 - //cut1.indices = std::move(its.indices); - //cut1.vertices = std::move(its.vertices); - //return true; -} - -namespace priv { -struct ExtendAOI{ +// To track what was cutted of +struct ExtendAOI +{ // source for extend const CutAOI *source; // converted cut to CGAL mesh CutMesh mesh; }; -void diff_model(ExtendAOI &cut, /*const*/ CutMesh &another_model); - - +/// +/// Implement 'cut' Minus 'clipper', where clipper is reverse input Volume +/// NOTE: clipper will be modified (corefined by cut) !!! +/// +/// differ from +/// differ what +void clip_cut(ExtendAOI &cut, CutMesh clipper); BoundingBoxf3 bounding_box(const CutAOI &cut, const CutMesh &mesh); BoundingBoxf3 bounding_box(const ExtendAOI &ecut); ExtendAOI create_extend_aoi(CutAOI &cut, const CutMesh &mesh); + +} // namespace priv + +bool priv::merge_intersection(SurfaceCut &cut1, const SurfaceCut &cut2) { + return false; +} + +namespace priv { } // namespace priv void priv::create_face_types(FaceTypeMap &map, @@ -2903,6 +2700,10 @@ void priv::create_face_types(FaceTypeMap &map, return fi_around_hi1; } } + + // should never rich it + // Exist case when do not know source triangle for decide side of intersection + assert(false); return FI(); }; @@ -2926,10 +2727,13 @@ void priv::create_face_types(FaceTypeMap &map, VI vi1_target = tm1.target(hi1); assert(vi1_target.is_valid()); - // Need to know source triangle of intersection-----------------------------<<<<<<<<<<<<<<< const Source &s_s = sources[vi1_source]; const Source &s_t = sources[vi1_target]; FI fi2 = get_intersection_source(s_s, s_t); + + // in release solve situation that face was NOT deduced + if (!fi2.is_valid()) continue; + HI hi2 = tm2.halfedge(fi2); std::array t; size_t ti =0; @@ -2945,68 +2749,108 @@ void priv::create_face_types(FaceTypeMap &map, // inside mean it will be used // outside will be discarded if (CGAL::orientation(*t[0], *t[1], *t[2], p) == CGAL::POSITIVE) { - map[f1a] = FaceType::outside; - map[f1b] = FaceType::inside; - } else { map[f1a] = FaceType::inside; map[f1b] = FaceType::outside; + } else { + map[f1a] = FaceType::outside; + map[f1b] = FaceType::inside; } } } - -void priv::diff_model(ExtendAOI &cut, CutMesh &another_model) +#include +#include +void priv::clip_cut(ExtendAOI &cut, CutMesh clipper) { - CutMesh& tm1 = cut.mesh; - CutMesh &tm2 = another_model; + // create backup for case that there is no intersection + CutMesh backup_copy = cut.mesh; + class ExistIntersectionClipVisitor: public CGAL::Polygon_mesh_processing::Corefinement::Default_visitor + { + bool* exist_intersection; + public: + ExistIntersectionClipVisitor(bool *exist_intersection): exist_intersection(exist_intersection){} + void intersection_point_detected(std::size_t, int , HI, HI, const CutMesh&, const CutMesh&, bool, bool) + { *exist_intersection = true;} + }; + bool exist_intersection = false; + ExistIntersectionClipVisitor visitor{&exist_intersection}; + + // namep parameters for model tm and function clip + const auto &np_tm = CGAL::parameters::visitor(visitor) + .throw_on_self_intersection(false); + + // name parameters for model clipper and function clip + // Can't use 'do_not_modify' need clipper to be closed + //const auto &np_c = CGAL::parameters::do_not_modify(true); + // .throw_on_self_intersection(false); is set automaticaly by param 'do_not_modify' + // .clip_volume(false); is set automaticaly by param 'do_not_modify' + + std::string dir = "C:/data/temp/out/"; + static int i = 0; + CGAL::IO::write_OFF(dir + "in_patch"+std::to_string(i)+".off", cut.mesh); + CGAL::IO::write_OFF(dir + "in_model"+std::to_string(i)+".off", clipper); + bool suc = CGAL::Polygon_mesh_processing::clip(cut.mesh, clipper, np_tm); + CGAL::IO::write_OFF(dir + "out_patch"+std::to_string(i)+".off", cut.mesh); + CGAL::IO::write_OFF(dir + "out_model"+std::to_string(i++)+".off", clipper); + + // true if the output surface mesh is manifold. + // If false is returned tm and clipper are only corefined. + assert(suc); + // decide what TODO when can't clip source object !?! + if (!exist_intersection || !suc) { + // TODO: test if cut is fully in or fully out!! + cut.mesh = backup_copy; + return; + } + + // TODO: fix outlines list + + return; //Store_VI_pairs::Pairs intersections; - std::string vertex_source_map_name = "v:source_intersections"; - VertexSourceMap vmap = tm1.add_property_map(vertex_source_map_name).first; - IntersectionSources visitor = {&tm1, &tm2, vmap}; - - //// bool map for affected edge - EcmType ecm = get(DynamicEdgeProperty(), tm1); - const auto &p = CGAL::parameters::visitor(visitor) - .edge_is_constrained_map(ecm) - .throw_on_self_intersection(false); - const auto &q = CGAL::parameters::do_not_modify(true) - .throw_on_self_intersection(false); - CGAL::Polygon_mesh_processing::corefine(tm1, tm2, p, q); - + //std::string vertex_source_map_name = "v:source_intersections"; + //VertexSourceMap vmap = tm1.add_property_map(vertex_source_map_name).first; + //Sources sources; + //IntersectionSources visitor = {&tm1, &tm2, vmap, &sources}; + ////// bool map for affected edge + //EcmType ecm = get(DynamicEdgeProperty(), tm1); + //const auto &p = CGAL::parameters::visitor(visitor) + // .edge_is_constrained_map(ecm) + // .throw_on_self_intersection(false); + //const auto &q = CGAL::parameters::do_not_modify(true) + // .throw_on_self_intersection(false); + //CGAL::Polygon_mesh_processing::corefine(tm1, tm2, p, q); + // //// when no intersection detected than no result surface cut - //if (intersections.empty()) return; + //if (sources.empty()) return; + //// TODO: check patch is all inside? - //// Create conversion map from tm1.vertex to tm2.vertex on constrained edge - //std::string vi1_to_vi2_name = "v:vi1_to_vi2"; - //V2V_map vi1_to_vi2 = create_map_from_vi1_to_vi2(tm1, intersections, vi1_to_vi2_name); - - ////std::string face_type_map_name = "f:side"; //FaceTypeMap face_type_map = tm1.add_property_map(face_type_map_name).first; - //create_face_types(tm1, face_type_map, tm2, ecm); + //create_face_types(face_type_map, tm1, tm2, ecm, vmap); - //std::string dir = "C:/data/temp/out/"; - //store(tm1, face_type_map, dir + "constrained.off"); + // + //store(tm1, face_type_map, dir + std::to_string(i) + "constrained.off"); //flood_fill_inner(tm1, face_type_map); - //store(tm1, face_type_map, dir + "filled.off"); + //store(tm1, face_type_map, dir + std::to_string(i) +"filled.off"); + //++i; //std::string vi_to_res_name = "v:vertex_to_result"; - //V2I_map vi1_to_res = tm1.add_property_map(vi_to_res_name).first; + ////V2I_map vi1_to_res = tm1.add_property_map(vi_to_res_name).first; - // create result Surface cut - - //indexed_triangle_set its = create_merged_its(tm1, face_type_map1, - // vi1_to_res, tm2, - // face_type_map2, vi2_to_res, - // vi1_to_vi2); - //its_write_obj(its, (dir + "merged_result.obj").c_str()); + //// create result Surface cut + // + ////indexed_triangle_set its = create_merged_its(tm1, face_type_map1, + //// vi1_to_res, tm2, + //// face_type_map2, vi2_to_res, + //// vi1_to_vi2); + ////its_write_obj(its, (dir + "merged_result.obj").c_str()); - // calculate contours: + //// calculate contours: - // set result into cut1 - //cut1.indices = std::move(its.indices); - //cut1.vertices = std::move(its.vertices); + //// set result into cut1 + ////cut1.indices = std::move(its.indices); + ////cut1.vertices = std::move(its.vertices); } BoundingBoxf3 priv::bounding_box(const CutAOI &cut, const CutMesh &mesh) { @@ -3133,7 +2977,7 @@ void priv::diff_models(VCutAOIs &cuts, for (size_t cut_index2 = 0; cut_index2 < count_cuts; ++cut_index2, ++index2){ const BoundingBoxf3 &bb = bbs[index2]; if (!bb.intersects(result_bb)) continue; - priv::diff_model(*ecut, models[model_index2]); + priv::clip_cut(*ecut, models[model_index2]); differenced[model_index2] = true; if ((model_index2+1) < models.size()) index2 = m2i.calc_index({uint32_t(model_index2 + 1), 0});