diff --git a/src/libslic3r/CutSurface.cpp b/src/libslic3r/CutSurface.cpp index 86dbc5342..b86aa102e 100644 --- a/src/libslic3r/CutSurface.cpp +++ b/src/libslic3r/CutSurface.cpp @@ -146,6 +146,16 @@ struct IntersectingElement bool is_last() const { return attr >= 16; } }; +/// +/// set true to skip map for indicies +/// +/// Flag to convert triangle to cgal +/// model +/// direction +void set_skip_for_outward_projection(std::vector &skip_indicies, + const indexed_triangle_set &its, + const Emboss::IProject3f &projection); + /// /// Convert triangle mesh model to CGAL Surface_mesh /// Filtrate out opposite triangles @@ -533,11 +543,15 @@ SurfaceCut Slic3r::cut_surface(const indexed_triangle_set &model, priv::FaceTypeMap face_type_map = cgal_model.add_property_map(face_type_map_name).first; // Select inside and outside face in model - priv::set_face_type(face_type_map, cgal_model, vert_shape_map, ecm, cgal_shape); - priv::set_almost_parallel_type(face_type_map, cgal_model, projection); + priv::set_face_type(face_type_map, cgal_model, vert_shape_map, ecm, cgal_shape); #ifdef DEBUG_OUTPUT_DIR priv::store(cgal_model, face_type_map, DEBUG_OUTPUT_DIR + "constrained.off"); // only debug #endif // DEBUG_OUTPUT_DIR + + priv::set_almost_parallel_type(face_type_map, cgal_model, projection); +#ifdef DEBUG_OUTPUT_DIR + priv::store(cgal_model, face_type_map, DEBUG_OUTPUT_DIR + "constrainedWithAlmostParallel.off"); // only debug +#endif // DEBUG_OUTPUT_DIR priv::flood_fill_inner(cgal_model, face_type_map); // Seed fill the other faces inside the region. @@ -763,11 +777,25 @@ bool priv::is_toward_projection(const Vec3f &a, CGAL::POSITIVE; } +void priv::set_skip_for_outward_projection(std::vector &skip_indicies, + const indexed_triangle_set &its, + const Emboss::IProject3f &projection) +{ + for (const auto &t : its.indices) { + size_t index = &t - &its.indices.front(); + if (skip_indicies[index]) continue; + if (is_toward_projection(t, its.vertices, projection)) continue; + skip_indicies[index] = true; + } +} + priv::CutMesh priv::to_cgal(const indexed_triangle_set &its, const Emboss::IProject3f &projection) { - CutMesh result; - if (its.empty()) return result; + if (its.empty()) return {}; + std::vector skip_indicies(its.indices.size(), {false}); + // cut out opposit triangles + set_skip_for_outward_projection(skip_indicies, its, projection); const std::vector &vertices = its.vertices; const std::vector &indices = its.indices; @@ -780,9 +808,9 @@ priv::CutMesh priv::to_cgal(const indexed_triangle_set &its, size_t edges_count = 0; for (const auto &t : indices) { - if (!is_toward_projection(t, vertices, projection)) continue; - ++faces_count; size_t index = &t - &indices.front(); + if (skip_indicies[index]) continue; + ++faces_count; use_indices[index] = true; size_t count_used_vertices = 0; for (const auto vi : t) { @@ -804,6 +832,8 @@ priv::CutMesh priv::to_cgal(const indexed_triangle_set &its, assert(vertices_count <= vertices.size()); assert(edges_count <= (indices.size() * 3) / 2); assert(faces_count <= indices.size()); + + CutMesh result; result.reserve(vertices_count, edges_count, faces_count); std::vector to_filtrated_vertices_index(vertices.size()); @@ -911,79 +941,76 @@ void priv::set_face_type(FaceTypeMap &face_type_map, const EcmType &ecm, const CutMesh &shape_mesh) { + auto get_face_type = [&mesh, &shape_mesh, &vertex_shape_map](HI hi) -> FaceType { + VI vi_from = mesh.source(hi); + VI vi_to = mesh.target(hi); + // This face has a constrained edge. + const IntersectingElement &shape_from = *vertex_shape_map[vi_from]; + const IntersectingElement &shape_to = *vertex_shape_map[vi_to]; + + assert(shape_from.point_index != std::numeric_limits::max()); + assert(shape_from.attr != (unsigned char) IntersectingElement::Type::undefined); + assert(shape_to.point_index != std::numeric_limits::max()); + assert(shape_to.attr != (unsigned char) IntersectingElement::Type::undefined); + // assert mean: There is constrained between two shapes + // Filip think it can't happens. + // consider what to do? + assert(shape_from.vertex_base == shape_to.vertex_base); + + bool is_inside = false; + // index into contour + uint32_t i_from = shape_from.point_index; + uint32_t i_to = shape_to.point_index; + IntersectingElement::Type type_from = shape_from.get_type(); + IntersectingElement::Type type_to = shape_to.get_type(); + if (i_from == i_to && type_from == type_to) { + // intersecting element must be face + assert(type_from == IntersectingElement::Type::face_1 || + type_from == IntersectingElement::Type::face_2); + + // count of vertices is twice as count of point in the contour + uint32_t i = i_from * 2; + // j is next contour point in vertices + uint32_t j = shape_from.is_last() ? 0 : i + 2; + i += shape_from.vertex_base; + j += shape_from.vertex_base; + + // opposit point(in triangle face) to edge + const auto &p = mesh.point(mesh.target(mesh.next(hi))); + + // abc is source triangle face + auto abcp = type_from == IntersectingElement::Type::face_1 ? + CGAL::orientation(shape_mesh.point(VI(i)), + shape_mesh.point(VI(i + 1)), + shape_mesh.point(VI(j)), p) : + // type_from == IntersectingElement::Type::face_2 + CGAL::orientation(shape_mesh.point(VI(j)), + shape_mesh.point(VI(i + 1)), + shape_mesh.point(VI(j + 1)), p); + is_inside = abcp == CGAL::POSITIVE; + } else if (i_from < i_to || (i_from == i_to && type_from < type_to)) { + bool is_last = shape_to.is_last() && shape_from.is_first(); + // check continuity of indicies + assert(i_from == i_to || is_last || (i_from + 1) == i_to); + if (!is_last) is_inside = true; + } else { + assert(i_from > i_to || (i_from == i_to && type_from > type_to)); + bool is_last = shape_to.is_first() && shape_from.is_last(); + // check continuity of indicies + assert(i_from == i_to || is_last || (i_to + 1) == i_from); + if (is_last) is_inside = true; + } + return (is_inside) ? FaceType::inside : FaceType::outside; + }; + for (const FI& fi : mesh.faces()) { FaceType face_type = FaceType::not_constrained; HI hi_end = mesh.halfedge(fi); HI hi = hi_end; do { - EI edge_index = mesh.edge(hi); // is edge new created - constrained? - if (get(ecm, edge_index)) { - VI vi_from = mesh.source(hi); - VI vi_to = mesh.target(hi); - // This face has a constrained edge. - const IntersectingElement& shape_from = *vertex_shape_map[vi_from]; - const IntersectingElement& shape_to = *vertex_shape_map[vi_to]; - - assert(shape_from.point_index != std::numeric_limits::max()); - assert(shape_from.attr != (unsigned char)IntersectingElement::Type::undefined); - assert(shape_to.point_index != std::numeric_limits::max()); - assert(shape_to.attr != (unsigned char)IntersectingElement::Type::undefined); - - // assert mean: There is constrained between two shapes - // Filip think it can't happens. - // consider what to do? - assert(shape_from.vertex_base == shape_to.vertex_base); - - bool is_inside = false; - - // index into contour - uint32_t i_from = shape_from.point_index; - uint32_t i_to = shape_to.point_index; - IntersectingElement::Type type_from = shape_from.get_type(); - IntersectingElement::Type type_to = shape_to.get_type(); - if (i_from == i_to && type_from == type_to) { - // intersecting element must be face - assert(type_from == IntersectingElement::Type::face_1 || - type_from == IntersectingElement::Type::face_2); - - // count of vertices is twice as count of point in the contour - uint32_t i = i_from * 2; - // j is next contour point in vertices - uint32_t j = shape_from.is_last() ? 0 : i + 2; - i += shape_from.vertex_base; - j += shape_from.vertex_base; - - // opposit point(in triangle face) to edge - const auto &p = mesh.point(mesh.target(mesh.next(hi))); - - // abc is source triangle face - auto abcp = - type_from == IntersectingElement::Type::face_1 ? - CGAL::orientation( - shape_mesh.point(VI(i)), - shape_mesh.point(VI(i + 1)), - shape_mesh.point(VI(j)), p) : - // type_from == IntersectingElement::Type::face_2 - CGAL::orientation( - shape_mesh.point(VI(j)), - shape_mesh.point(VI(i + 1)), - shape_mesh.point(VI(j + 1)), p); - is_inside = abcp == CGAL::POSITIVE; - } else if (i_from < i_to || (i_from == i_to && type_from < type_to)) { - bool is_last = shape_to.is_last() && shape_from.is_first(); - // check continuity of indicies - assert(i_from == i_to || is_last || (i_from + 1) == i_to); - if (!is_last) is_inside = true; - } else { - assert(i_from > i_to || (i_from == i_to && type_from > type_to)); - bool is_last = shape_to.is_first() && shape_from.is_last(); - // check continuity of indicies - assert(i_from == i_to || is_last || (i_to + 1) == i_from); - if (is_last) is_inside = true; - } - face_type = (is_inside) ? FaceType::inside : - FaceType::outside; + if (get(ecm, mesh.edge(hi))) { + face_type = get_face_type(hi); break; } // next half edge index inside of face @@ -998,9 +1025,15 @@ void priv::set_almost_parallel_type(FaceTypeMap &face_type_map, const Emboss::IProject3f &projection) { for (const FI &fi : mesh.faces()) { - assert(is_toward_projection(fi, mesh, projection)); auto &type = face_type_map[fi]; if (type != FaceType::inside) continue; + //* + assert(is_toward_projection(fi, mesh, projection)); + /*/ + if (!is_toward_projection(fi, mesh, projection)) { + type = FaceType::outside; + }else + // */ if (is_almost_parallel(fi, mesh, projection)) // change type type = FaceType::inside_parallel; @@ -1248,7 +1281,7 @@ void priv::create_reduce_map(ReductionMap &reduction_map, // initialize reduction map for (VI reduction_from : mesh.vertices()) reduction_map[reduction_from] = reduction_from; - + // check if vertex was made by edge_2 which is diagonal of quad auto is_reducible_vertex = [&vert_shape_map](VI reduction_from) -> bool { const IntersectingElement *ie = vert_shape_map[reduction_from]; @@ -1316,6 +1349,14 @@ SurfaceCut priv::create_index_triangle_set(const std::vector &faces, const ReductionMap &reduction_map, ConvertMap &v2v) { + // clear v2v + // more than one cut can share vertex and each cut need its own conversion + for (FI fi : faces) { + HI hi = mesh.halfedge(fi); + for (VI vi : {mesh.source(hi), mesh.target(hi), mesh.target(mesh.next(hi))}) + v2v[vi] = std::numeric_limits::max(); + } + // IMPROVE: use reduced count of faces and outlines size_t indices_size = faces.size(); size_t vertices_size = (indices_size * 3 - count_outlines / 2) / 2; @@ -1645,7 +1686,7 @@ SurfaceCuts priv::create_surface_cuts(const CutAOIs &cuts, // convert_map could be used separately for each surface cut. // But it is moore faster to use one memory allocation for them all. SurfaceCut sc = create_index_triangle_set(faces, outlines.size(), mesh, reduction_map, convert_map); - + // connect outlines sc.contours = create_cut(outlines, mesh, reduction_map, convert_map); result.emplace_back(std::move(sc)); diff --git a/src/libslic3r/CutSurface.hpp b/src/libslic3r/CutSurface.hpp index a76d16b23..5528f67a3 100644 --- a/src/libslic3r/CutSurface.hpp +++ b/src/libslic3r/CutSurface.hpp @@ -17,8 +17,8 @@ namespace Slic3r{ /// struct SurfaceCut : public indexed_triangle_set { - // connected cutted surface - indexed_triangle_set mesh; + // connected cutted surface --> inheritance is used + //indexed_triangle_set mesh; // vertex indices(index to mesh vertices) using Index = unsigned int; diff --git a/src/slic3r/GUI/Jobs/EmbossJob.cpp b/src/slic3r/GUI/Jobs/EmbossJob.cpp index 1cfdf0039..76e3f964c 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.cpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.cpp @@ -49,6 +49,14 @@ static TriangleMesh create_default_mesh(); /// Text configuration, ... static void update_volume(TriangleMesh &&mesh, const EmbossDataUpdate &data); +/// +/// extract scale in 2d +/// +/// Property of font style +/// Font file for size --> unit per em +/// scaling factor +static double get_shape_scale(const FontProp &fp, const Emboss::FontFile &ff); + /// /// Create projection for cut surface from mesh /// @@ -335,6 +343,8 @@ void UseSurfaceJob::finalize(bool canceled, std::exception_ptr &) { if (canceled || m_input.cancel->load()) return; priv::update_volume(std::move(m_result), m_input); + // TODO: use fix matrix to compensate uncentered position + } //////////////////////////// @@ -444,7 +454,7 @@ void priv::update_volume(TriangleMesh &&mesh, canvas->reload_scene(refresh_immediately); } -static double get_shape_scale(const FontProp &fp, const Emboss::FontFile &ff) +static double priv::get_shape_scale(const FontProp &fp, const Emboss::FontFile &ff) { const auto &cn = fp.collection_number; unsigned int font_index = (cn.has_value()) ? *cn : 0;