From e5bf946008a40bfedbfe86106deed27df56163da Mon Sep 17 00:00:00 2001 From: Filip Sykala <filip.sykala@prusa3d.cz> Date: Tue, 3 May 2022 13:05:58 +0200 Subject: [PATCH] Fix filtering order of AOIs --- src/libslic3r/CutSurface.cpp | 127 ++++++++++++++++++++++++++++---- tests/libslic3r/test_emboss.cpp | 12 +-- 2 files changed, 119 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/CutSurface.cpp b/src/libslic3r/CutSurface.cpp index b236a2ae1..6c00ed33d 100644 --- a/src/libslic3r/CutSurface.cpp +++ b/src/libslic3r/CutSurface.cpp @@ -1,5 +1,18 @@ #include "CutSurface.hpp" +/// model.off - CGAL model created from index_triangle_set +/// shape.off - CGAL model created from shapes +/// constrained.off - Visualization of inside and outside triangles +/// Green - not along constrained edge +/// Red - sure that are inside +/// Purple - sure that are outside +/// filled.off - flood fill green triangles inside of red area +/// - Same meaning of color as constrained +/// reduction.off - Visualization of reduced and non-reduced Vertices +/// aois/cutAOI{N}.obj - Cuted Area of interest from corefined model +/// cuts/cut{N}.obj - Filtered surface cuts + Reduced vertices made by e2 (text_edge_2) +//#define DEBUG_OUTPUT_DIR std::string("C:/data/temp/") + using namespace Slic3r; void Slic3r::append(SurfaceCut &sc, SurfaceCut &&sc_add) @@ -401,6 +414,10 @@ SurfaceCut::CutContour create_cut(const std::vector<HI> &outlines, const ReductionMap &reduction_map, const ConvertMap &v2v); +#ifdef DEBUG_OUTPUT_DIR +indexed_triangle_set create_indexed_triangle_set(const std::vector<FI> &faces, + const CutMesh &mesh); + /// <summary> /// Debug purpose store of mesh with colored face by face type /// </summary> @@ -410,20 +427,30 @@ SurfaceCut::CutContour create_cut(const std::vector<HI> &outlines, /// <param name="file">File to store</param> void store(CutMesh &mesh, const FaceTypeMap &face_type_map, const std::string &file); void store(CutMesh &mesh, const ReductionMap &reduction_map, const std::string &file); -void store(const SurfaceCuts &cut, const std::string &file_prefix); +void store(const CutAOIs &aois, const CutMesh &mesh, const std::string &dir); +void store(const SurfaceCuts &cut, const std::string &dir); +#endif // DEBUG_OUTPUT_DIR + } // namespace privat + SurfaceCuts Slic3r::cut_surface(const indexed_triangle_set &model, const ExPolygons &shapes, const Emboss::IProject &projection) { priv::CutMesh cgal_model = priv::to_cgal(model); - CGAL::IO::write_OFF("C:/data/temp/model.off", cgal_model); // only debug + +#ifdef DEBUG_OUTPUT_DIR + CGAL::IO::write_OFF(DEBUG_OUTPUT_DIR + "model.off", cgal_model); // only debug +#endif // DEBUG_OUTPUT_DIR std::string edge_shape_map_name = "e:IntersectingElement"; std::string face_shape_map_name = "f:IntersectingElement"; - priv::CutMesh cgal_shape = priv::to_cgal(shapes, projection, edge_shape_map_name, face_shape_map_name); - CGAL::IO::write_OFF("C:/data/temp/shape.off", cgal_shape); // only debug + priv::CutMesh cgal_shape = priv::to_cgal(shapes, projection, edge_shape_map_name, face_shape_map_name); + +#ifdef DEBUG_OUTPUT_DIR + CGAL::IO::write_OFF(DEBUG_OUTPUT_DIR + "shape.off", cgal_shape); // only debug +#endif // DEBUG_OUTPUT_DIR auto edge_shape_map = cgal_shape.property_map<priv::EI, priv::IntersectingElement>(edge_shape_map_name).first; auto face_shape_map = cgal_shape.property_map<priv::FI, priv::IntersectingElement>(face_shape_map_name).first; @@ -453,19 +480,32 @@ SurfaceCuts Slic3r::cut_surface(const indexed_triangle_set &model, // Select inside and outside face in model priv::set_face_type(face_type_map, cgal_model, vert_shape_map, ecm, projection, cgal_shape); - priv::store(cgal_model, face_type_map, "C:/data/temp/constrained.off"); // only debug + +#ifdef DEBUG_OUTPUT_DIR + priv::store(cgal_model, face_type_map, DEBUG_OUTPUT_DIR + "constrained.off"); // only debug +#endif // DEBUG_OUTPUT_DIR // Seed fill the other faces inside the region. priv::flood_fill_inner(cgal_model, projection, face_type_map); - priv::store(cgal_model, face_type_map, "C:/data/temp/filled.off"); // only debug + +#ifdef DEBUG_OUTPUT_DIR + priv::store(cgal_model, face_type_map, DEBUG_OUTPUT_DIR + "filled.off"); // only debug +#endif // DEBUG_OUTPUT_DIR std::string vertex_reduction_map_name = "v:reduction"; priv::ReductionMap vertex_reduction_map = cgal_model.add_property_map<priv::VI, priv::VI>(vertex_reduction_map_name).first; priv::create_reduce_map(vertex_reduction_map, cgal_model, face_type_map, vert_shape_map); - priv::store(cgal_model, vertex_reduction_map, "C:/data/temp/reduction.off"); // only debug + +#ifdef DEBUG_OUTPUT_DIR + priv::store(cgal_model, vertex_reduction_map, DEBUG_OUTPUT_DIR + "reduction.off"); // only debug +#endif // DEBUG_OUTPUT_DIR priv::CutAOIs cutAOIs = create_cut_area_of_interests(cgal_model, shapes, face_type_map); +#ifdef DEBUG_OUTPUT_DIR + priv::store(cutAOIs, cgal_model, DEBUG_OUTPUT_DIR + "aois/"); // only debug +#endif // DEBUG_OUTPUT_DIR + // Filter out NO top one cuts priv::filter_cuts(cutAOIs, cgal_model, shapes, projection, vert_shape_map); @@ -474,8 +514,10 @@ SurfaceCuts Slic3r::cut_surface(const indexed_triangle_set &model, std::string vertec_convert_map_name = "v:convert"; priv::ConvertMap vertex_convert_map = cgal_model.add_property_map<priv::VI, SurfaceCut::Index>(vertec_convert_map_name).first; SurfaceCuts result = priv::create_surface_cuts(cutAOIs, cgal_model, vertex_reduction_map, vertex_convert_map); - - priv::store(result, "C:/data/temp/cut"); // only debug + +#ifdef DEBUG_OUTPUT_DIR + priv::store(result, DEBUG_OUTPUT_DIR + "cuts/"); // only debug +#endif // DEBUG_OUTPUT_DIR // TODO: Filter surfaceCuts to only the top most. return result; @@ -1355,7 +1397,7 @@ void priv::filter_cuts(CutAOIs &cuts, 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) { + if (act_sq_norm < prev_sq_norm) { del_cuts[cut_index] = true; return true; } @@ -1412,7 +1454,7 @@ SurfaceCuts priv::create_surface_cuts(const CutAOIs &cuts, return result; } -// only for debug +#ifdef DEBUG_OUTPUT_DIR void priv::store(CutMesh &mesh, const FaceTypeMap &face_type_map, const std::string& file) { auto face_colors = mesh.add_property_map<priv::FI, CGAL::Color>("f:color").first; @@ -1448,10 +1490,67 @@ void priv::store(CutMesh &mesh, const ReductionMap &reduction_map, const std::st mesh.remove_property_map(vertex_colors); } -void priv::store(const SurfaceCuts &cut, const std::string &file_prefix) { - for (auto &c : cut) { +indexed_triangle_set priv::create_indexed_triangle_set( + const std::vector<FI> &faces, const CutMesh &mesh) +{ + std::vector<VI> vertices; + vertices.reserve(faces.size() * 2); + + indexed_triangle_set its; + its.indices.reserve(faces.size()); + for (FI fi : faces) { + HI hi = mesh.halfedge(fi); + HI hi_end = hi; + + int ti = 0; + Vec3i t; + + do { + VI vi = mesh.source(hi); + auto res = std::find(vertices.begin(), vertices.end(), vi); + t[ti++] = res - vertices.begin(); + if (res == vertices.end()) vertices.push_back(vi); + hi = mesh.next(hi); + } while (hi != hi_end); + + its.indices.push_back(t); + } + + its.vertices.reserve(vertices.size()); + for (VI vi : vertices) { + const auto &p = mesh.point(vi); + its.vertices.emplace_back(p.x(), p.y(), p.z()); + } + return its; +} + +#include <filesystem> +static void prepare_dir(const std::string &dir) { + namespace fs = std::filesystem; + if (fs::exists(dir)) { + for (auto &path : fs::directory_iterator(dir)) + fs::remove_all(path); + } else { + fs::create_directories(dir); + } +} + +void priv::store(const CutAOIs &aois, const CutMesh &mesh, const std::string &dir) { + prepare_dir(dir); + for (const auto &aoi : aois) { + size_t index = &aoi - &aois.front(); + std::string file = dir + "aoi" + std::to_string(index) + ".obj"; + indexed_triangle_set its = create_indexed_triangle_set(aoi.first, mesh); + its_write_obj(its, file.c_str()); + // TODO: Store outline from half edge somehow + } +} + +void priv::store(const SurfaceCuts &cut, const std::string &dir) { + for (const auto &c : cut) { size_t index = &c - &cut.front(); - std::string file = file_prefix + std::to_string(index) + ".obj"; + std::string file = dir + "cut" + std::to_string(index) + ".obj"; its_write_obj(c, file.c_str()); } } +#endif // DEBUG_OUTPUT_DIR diff --git a/tests/libslic3r/test_emboss.cpp b/tests/libslic3r/test_emboss.cpp index a794c6e83..5ea785565 100644 --- a/tests/libslic3r/test_emboss.cpp +++ b/tests/libslic3r/test_emboss.cpp @@ -316,26 +316,26 @@ TEST_CASE("Cut surface", "[]") REQUIRE(!shape.empty()); Transform3d tr = Transform3d::Identity(); - tr.translate(Vec3d(0., 0., z_depth)); + tr.translate(Vec3d(0., 0., -z_depth)); tr.scale(Emboss::SHAPE_SCALE); - Emboss::OrthoProject cut_projection(tr, Vec3f(0.f, 0.f, -50)); + Emboss::OrthoProject cut_projection(tr, Vec3f(0.f, 0.f, z_depth)); auto object = its_make_cube(782 - 49 + 50, 724 + 10 + 50, 5); - its_translate(object, Vec3f(49 - 25, -10 - 25, 2.5)); + its_translate(object, Vec3f(49 - 25, -10 - 25, -40)); auto cube2 = object; // copy - its_translate(cube2, Vec3f(100, -40, 40)); + its_translate(cube2, Vec3f(100, -40, 7.5)); its_merge(object, std::move(cube2)); auto surfaces = cut_surface(object, shape, cut_projection); CHECK(!surfaces.empty()); - Emboss::OrthoProject projection(Transform3d::Identity(), Vec3f(0.f, 0.f, -10.f)); + Emboss::OrthoProject projection(Transform3d::Identity(), Vec3f(0.f, 0.f, 10.f)); for (auto &surface : surfaces) its_translate(surface, Vec3f(0.f, 0.f, 10)); indexed_triangle_set its = cuts2model(surfaces, projection); CHECK(!its.empty()); - its_write_obj(its, "C:/data/temp/projected.obj"); + //its_write_obj(its, "C:/data/temp/projected.obj"); }