OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
priv Namespace Reference

Classes

struct  IntersectingElement
 IntersectingElement. More...
struct  SurfacePatch
struct  ModelCutId
class  ModelCut2index
 Keep conversion from VCutAOIs to Index and vice versa Model_index .. contour(or hole) poin from ExPolygons Index .. continous number. More...
struct  ProjectionDistance
 To select surface near projection distance. More...
struct  Visitor
 Track source of intersection Help for anotate inner and outer faces. More...
struct  ClosePoint
struct  SearchData
struct  Source
struct  IntersectionSources
 Corefine visitor Store intersection source for vertices of constrained edge of tm1 Must be used with corefine flag no modification of tm2. More...
struct  SurfacePatchEx

Typedefs

using Project = Emboss::IProjection
using Project3d = Emboss::IProject3d
using EpicKernel = CGAL::Exact_predicates_inexact_constructions_kernel
using CutMesh = CGAL::Surface_mesh<EpicKernel::Point_3>
using CutMeshes = std::vector<CutMesh>
using VI = CGAL::SM_Vertex_index
using HI = CGAL::SM_Halfedge_index
using EI = CGAL::SM_Edge_index
using FI = CGAL::SM_Face_index
using P3 = CGAL::Epick::Point_3
using EdgeShapeMap = CutMesh::Property_map<EI, IntersectingElement>
using FaceShapeMap = CutMesh::Property_map<FI, IntersectingElement>
using VertexShapeMap = CutMesh::Property_map<VI, const IntersectingElement *>
using FaceTypeMap = CutMesh::Property_map<FI, FaceType>
using CvtVI2VI = CutMesh::Property_map<VI, VI>
using ReductionMap = CvtVI2VI
using EdgeBoolMap = CutMesh::Property_map<EI, bool>
using CutAOI = std::pair<std::vector<FI>, std::vector<HI>>
using CutAOIs = std::vector<CutAOI>
using VCutAOIs = std::vector<CutAOIs>
using Loop = std::vector<VI>
using Loops = std::vector<Loop>
using SurfacePatches = std::vector<SurfacePatch>
using ProjectionDistances = std::vector<ProjectionDistance>
using VDistances = std::vector<ProjectionDistances>
using PointNormal = std::pair<Vec3d, Vec3d>
using PointNormals = std::array<PointNormal, 4>
using IsOnSides = std::vector<std::array<bool, 4>>
using Sources = std::vector<Source>
using VertexSourceMap = CutMesh::Property_map<VI, Source>
using SurfacePatchesEx = std::vector<SurfacePatchEx>
using BBS = std::vector<BoundingBoxf3>
using Primitive = CGAL::AABB_face_graph_triangle_primitive<CutMesh>
using Traits = CGAL::AABB_traits_3<EpicKernel, Primitive>
using Ray = EpicKernel::Ray_3
using Tree = CGAL::AABB_tree<Traits>
using Trees = std::vector<Tree>

Enumerations

enum class  FaceType { inside , outside , not_constrained , inside_processed }
 Flag for faces in CGAL mesh. More...

Functions

void set_skip_for_out_of_aoi (std::vector< bool > &skip_indicies, const indexed_triangle_set &its, const Project &projection, const BoundingBox &shapes_bb)
 Set true for indices out of area of interest.
void set_skip_by_angle (std::vector< bool > &skip_indicies, const indexed_triangle_set &its, const Project3d &projection, double max_angle=89.)
 Set true for indicies outward and almost parallel together. Note: internally calculate normals.
Vec3d to_vec3d (const P3 &p)
CutMesh to_cgal (const indexed_triangle_set &its, const std::vector< bool > &skip_indicies, bool flip=false)
 Convert triangle mesh model to CGAL Surface_mesh Filtrate out opposite triangles Add property map for source face index.
CutMesh to_cgal (const ExPolygons &shapes, const Project &projection)
 Covert 2d shape (e.g. Glyph) to CGAL model NOTE: internaly create edge_shape_map .. Property map to store conversion from edge to contour face_shape_map .. Property map to store conversion from face to contour.
bool exist_duplicit_vertex (const CutMesh &mesh)
void create_reduce_map (ReductionMap &reduction_map, const CutMesh &meshes)
 Create map to reduce unnecesary triangles, Triangles are made by divided quad to two triangles on side of cutting shape mesh Note: also use from mesh (have to be created) face_type_map .. Type of shape inside / outside vert_shape_map .. Source of outline vertex.
CutAOIs cut_from_model (CutMesh &cgal_model, const ExPolygons &shapes, CutMesh &cgal_shape, float projection_ratio, const ExPolygonsIndices &s2i)
 Create AOIs(area of interest) on model surface.
Loops create_loops (const std::vector< HI > &outlines, const CutMesh &mesh)
 Create closed loops of contour vertices created from open half edges.
SurfacePatches diff_models (VCutAOIs &cuts, CutMeshes &cut_models, CutMeshes &models, const Project3d &projection)
 Differenciate other models.
bool is_over_whole_expoly (const CutAOI &cutAOI, const ExPolygon &shape, const CutMesh &mesh)
 Checking whether patch is uninterrupted cover of whole expolygon it belongs.
bool is_over_whole_expoly (const SurfacePatch &patch, const ExPolygons &shapes, const VCutAOIs &cutAOIs, const CutMeshes &meshes)
 Checking whether patch is uninterrupted cover of whole expolygon it belongs.
Polygons unproject_loops (const SurfacePatch &patch, const Project &projection, Vec2d &depth_range)
 Unptoject points from outline loops of patch.
ExPolygon to_expoly (const SurfacePatch &patch, const Project &projection, Vec2d &depth_range)
 Unproject points from loops and create expolygons.
VDistances calc_distances (const SurfacePatches &patches, const CutMeshes &models, const CutMesh &shapes_mesh, size_t count_shapes_points, float projection_ratio)
 Calculate distances for SurfacePatches outline points NOTE: each model has to have "vert_shape_map" .. Know source of new vertices.
ProjectionDistances choose_best_distance (const VDistances &distances, const ExPolygons &shapes, const Point &start, const ExPolygonsIndices &s2i, const SurfacePatches &patches)
 Select distances in similar depth between expolygons.
std::vector< bool > select_patches (const ProjectionDistances &best_distances, const SurfacePatches &patches, const ExPolygons &shapes, const BoundingBox &shapes_bb, const ExPolygonsIndices &s2i, const VCutAOIs &cutAOIs, const CutMeshes &meshes, const Project &projection)
 Create mask for patches.
void append (SurfaceCut &sc, SurfaceCut &&sc_add)
 Merge two surface cuts together Added surface cut will be consumed.
SurfaceCut patch2cut (SurfacePatch &patch)
 Convert patch to indexed_triangle_set.
SurfaceCut merge_patches (SurfacePatches &patches, const std::vector< bool > &mask)
 Merge masked patches to one surface cut.
bool is_out_of (const Vec3d &v, const PointNormal &point_normal)
 Check.
bool is_all_on_one_side (const Vec3i32 &t, const IsOnSides &is_on_sides)
 Check if triangle t has all vertices out of any plane.
bool is_face_inside (HI hi, const CutMesh &mesh, const CutMesh &shape_mesh, const VertexShapeMap &vertex_shape_map, const ExPolygonsIndices &shape2index)
 Distiquish face type for half edge.
void set_face_type (FaceTypeMap &face_type_map, const CutMesh &mesh, const VertexShapeMap &vertex_shape_map, const EdgeBoolMap &ecm, const CutMesh &shape_mesh, const ExPolygonsIndices &shape2index)
 Face with constrained edge are inside/outside by type of intersection Other set to not_constrained(still it could be inside/outside).
void flood_fill_inner (const CutMesh &mesh, FaceTypeMap &face_type_map)
 Change FaceType from not_constrained to inside For neighbor(or neighbor of neighbor of ...) of inside triangles. Process only not_constrained triangles.
void collect_surface_data (std::queue< FI > &process, std::vector< FI > &faces, std::vector< HI > &outlines, FaceTypeMap &face_type_map, const CutMesh &mesh)
 Collect connected inside faces Collect outline half edges.
CutAOIs create_cut_area_of_interests (const CutMesh &mesh, const ExPolygons &shapes, FaceTypeMap &face_type_map)
 Create areas from mesh surface.
float calc_distance (const P3 &p, uint32_t pi, const CutMesh &shapes_mesh, float projection_ratio)
 Calculate projection distance of point [in mm].
float calc_size_sq (const Point &p)
SearchData create_search_data (const ExPolygons &shapes, const std::vector< bool > &mask)
uint32_t get_closest_point_index (const SearchData &sd, size_t line_idx, const Vec2d &hit_point, const ExPolygons &shapes, const ExPolygonsIndices &s2i)
uint32_t find_closest_point_index (const Point &p, const ExPolygons &shapes, const ExPolygonsIndices &s2i, const std::vector< bool > &mask)
std::pair< uint32_t, uint32_t > find_closest_point_pair (const ExPolygons &shapes, const std::vector< bool > &done_shapes, const ExPolygonsIndices &s2i, const std::vector< bool > &mask)
const ProjectionDistance * get_closest_projection (const ProjectionDistances &distance, float wanted_distance)
void fill_polygon_distances (const ProjectionDistance &pd, uint32_t index, const ExPolygonsIndex &id, ProjectionDistances &result, const ExPolygon &shape, const VDistances &distances)
void fill_shape_distances (uint32_t start_index, const ProjectionDistance *start_pd, ProjectionDistances &result, const ExPolygonsIndices &s2i, const ExPolygon &shape, const VDistances &distances)
ClosePoint find_close_point (const Point &p, ProjectionDistances &result, std::vector< bool > &finished_shapes, const ExPolygonsIndices &s2i, const ExPolygons &shapes)
const VI default_vi (std::numeric_limits< uint32_t >::max())
void create_face_types (FaceTypeMap &map, const CutMesh &tm1, const CutMesh &tm2, const EdgeBoolMap &ecm, const VertexSourceMap &sources)
 Create map1 and map2.
bool clip_cut (SurfacePatch &cut, CutMesh clipper)
 Implement 'cut' Minus 'clipper', where clipper is reverse input Volume NOTE: clipper will be modified (corefined by cut) !!!
BoundingBoxf3 bounding_box (const CutAOI &cut, const CutMesh &mesh)
BoundingBoxf3 bounding_box (const CutMesh &mesh)
BoundingBoxf3 bounding_box (const SurfacePatch &ecut)
SurfacePatch create_surface_patch (const std::vector< FI > &fis, CutMesh &mesh, const ReductionMap *rmap=nullptr)
 Create patch.
BBS create_bbs (const VCutAOIs &cuts, const CutMeshes &cut_models)
 Create bounding boxes for AOI.
Trees create_trees (const CutMeshes &models)
 Create AABB trees for check when patch is whole inside of model.
bool has_bb_intersection (const BoundingBoxf3 &bb, size_t model_index, const BBS &bbs, const ModelCut2index &m2i)
 Check whether bounding box has intersection with model.
bool is_patch_inside_of_model (const SurfacePatch &patch, const Tree &tree, const Project3d &projection)
 Only for model without intersection Use ray (in projection direction) from a point from patch and count intersections: pair .. outside | odd .. inside.
uint32_t get_shape_point_index (const CutAOI &cut, const CutMesh &model)
 Return some shape point index which identify shape NOTE: Used to find expolygon index.
SurfacePatch separate_patch (const std::vector< FI > &fis, SurfacePatch &patch, const CvtVI2VI &cvt_from)
 Separate triangles singned with number n.
void divide_patch (size_t i, SurfacePatchesEx &patches)
 Separate connected triangles into it's own patches new patches are added to back of input patches.
void collect_open_edges (SurfacePatches &patches)
 Fill outline in patches by open edges.
void insert_edges (Triangulation::HalfEdges &edges, uint32_t &offset, const Polygon &polygon, const Triangulation::Changes &changes)
void insert_edges (Triangulation::HalfEdges &edges, uint32_t &offset, const Polygon &polygon)
bool has_bidirectional_constrained (const Triangulation::HalfEdges &constrained)
bool is_unique (const Points &points)
bool has_self_intersection (const Points &points, const Triangulation::HalfEdges &constrained_half_edges)
static void clear (IconManager::Icons &icons)
static const std::vector< std::pair< int, bool > > & get_states (IconManager::RasterType type)
static void draw_transparent_icon (const IconManager::Icon &icon)

Variables

const std::string edge_shape_map_name = "e:IntersectingElement"
const std::string face_shape_map_name = "f:IntersectingElement"
const std::string vert_shape_map_name = "v:IntersectingElement"
const std::string face_type_map_name = "f:side"
const std::string patch_source_name = "v:patch_source"
const std::string vertex_reduction_map_name = "v:reduction"
const std::string is_constrained_edge_name = "e:is_constrained"
const std::string vertex_source_map_name = "v:SourceIntersecting"

Class Documentation

◆ priv::SurfacePatch

struct priv::SurfacePatch
Collaboration diagram for priv::SurfacePatch:
Class Members
size_t aoi_id
BoundingBoxf3 bb
bool is_whole_aoi = true
Loops loops
CutMesh mesh
size_t model_id
size_t shape_id = 0

◆ priv::ModelCutId

struct priv::ModelCutId
Class Members
uint32_t cut_index
uint32_t model_index

◆ priv::ProjectionDistance

struct priv::ProjectionDistance

To select surface near projection distance.

Class Members
uint32_t aoi_index = std::numeric_limits<uint32_t>::max()
float distance = std::numeric_limits<float>::max()
uint32_t model_index = std::numeric_limits<uint32_t>::max()
uint32_t patch_index = std::numeric_limits<uint32_t>::max()

◆ priv::ClosePoint

struct priv::ClosePoint
Class Members
float dist_sq = std::numeric_limits<float>::max()
uint32_t index = std::numeric_limits<uint32_t>::max()

◆ priv::SearchData

struct priv::SearchData
Collaboration diagram for priv::SearchData:
Class Members
vector< size_t > cvt
vector< Linef > lines
Tree< 2, double > tree

◆ priv::Source

struct priv::Source
Class Members
HI hi
int sdim =0

◆ priv::SurfacePatchEx

struct priv::SurfacePatchEx
Collaboration diagram for priv::SurfacePatchEx:
Class Members
bool full_inside = false
bool just_cliped = false
SurfacePatch patch

Typedef Documentation

◆ BBS

using priv::BBS = std::vector<BoundingBoxf3>

◆ CutAOI

using priv::CutAOI = std::pair<std::vector<FI>, std::vector<HI>>

◆ CutAOIs

using priv::CutAOIs = std::vector<CutAOI>

◆ CutMesh

using priv::CutMesh = CGAL::Surface_mesh<EpicKernel::Point_3>

◆ CutMeshes

using priv::CutMeshes = std::vector<CutMesh>

◆ CvtVI2VI

using priv::CvtVI2VI = CutMesh::Property_map<VI, VI>

◆ EdgeBoolMap

using priv::EdgeBoolMap = CutMesh::Property_map<EI, bool>

◆ EdgeShapeMap

using priv::EdgeShapeMap = CutMesh::Property_map<EI, IntersectingElement>

◆ EI

using priv::EI = CGAL::SM_Edge_index

◆ EpicKernel

using priv::EpicKernel = CGAL::Exact_predicates_inexact_constructions_kernel

◆ FaceShapeMap

using priv::FaceShapeMap = CutMesh::Property_map<FI, IntersectingElement>

◆ FaceTypeMap

using priv::FaceTypeMap = CutMesh::Property_map<FI, FaceType>

◆ FI

using priv::FI = CGAL::SM_Face_index

◆ HI

using priv::HI = CGAL::SM_Halfedge_index

◆ IsOnSides

using priv::IsOnSides = std::vector<std::array<bool, 4>>

◆ Loop

using priv::Loop = std::vector<VI>

◆ Loops

using priv::Loops = std::vector<Loop>

◆ P3

using priv::P3 = CGAL::Epick::Point_3

◆ PointNormal

using priv::PointNormal = std::pair<Vec3d, Vec3d>

◆ PointNormals

using priv::PointNormals = std::array<PointNormal, 4>

◆ Primitive

using priv::Primitive = CGAL::AABB_face_graph_triangle_primitive<CutMesh>

◆ Project

◆ Project3d

◆ ProjectionDistances

◆ Ray

using priv::Ray = EpicKernel::Ray_3

◆ ReductionMap

◆ Sources

using priv::Sources = std::vector<Source>

◆ SurfacePatches

using priv::SurfacePatches = std::vector<SurfacePatch>

◆ SurfacePatchesEx

using priv::SurfacePatchesEx = std::vector<SurfacePatchEx>

◆ Traits

using priv::Traits = CGAL::AABB_traits_3<EpicKernel, Primitive>

◆ Tree

using priv::Tree = CGAL::AABB_tree<Traits>

◆ Trees

using priv::Trees = std::vector<Tree>

◆ VCutAOIs

using priv::VCutAOIs = std::vector<CutAOIs>

◆ VDistances

using priv::VDistances = std::vector<ProjectionDistances>

◆ VertexShapeMap

using priv::VertexShapeMap = CutMesh::Property_map<VI, const IntersectingElement *>

◆ VertexSourceMap

using priv::VertexSourceMap = CutMesh::Property_map<VI, Source>

◆ VI

using priv::VI = CGAL::SM_Vertex_index

Enumeration Type Documentation

◆ FaceType

enum class priv::FaceType
strong

Flag for faces in CGAL mesh.

Enumerator
inside 
outside 
not_constrained 
inside_processed 
233 {
234 // face inside of the cutted shape
235 inside,
236 // face outside of the cutted shape
237 outside,
238 // face without constrained edge (In or Out)
240
241 // Helper flag that inside was processed
243};
bool inside(const Polygons &polygons, const Point &p)
Definition TreeNode.cpp:160
@ not_constrained
Definition CutSurface.cpp:239
@ inside_processed
Definition CutSurface.cpp:242
@ outside
Definition CutSurface.cpp:237

Function Documentation

◆ append()

void priv::append ( SurfaceCut & sc,
SurfaceCut && sc_add )

Merge two surface cuts together Added surface cut will be consumed.

Parameters
scSurface cut to extend
sc_addSurface cut to consume
3628{
3629 if (sc.empty()) {
3630 sc = std::move(sc_add);
3631 return;
3632 }
3633
3634 if (!sc_add.contours.empty()) {
3636 sc.vertices.size());
3637 size_t require = sc.contours.size() + sc_add.contours.size();
3638 if (sc.contours.capacity() < require) sc.contours.reserve(require);
3639 for (std::vector<SurfaceCut::Index> &cut : sc_add.contours)
3640 for (SurfaceCut::Index &i : cut) i += offset;
3641 Slic3r::append(sc.contours, std::move(sc_add.contours));
3642 }
3643 its_merge(sc, std::move(sc_add));
3644}
void its_merge(indexed_triangle_set &A, const indexed_triangle_set &B)
Definition TriangleMesh.cpp:1448
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157
unsigned int Index
Definition CutSurface.hpp:22
Contours contours
Definition CutSurface.hpp:26

References Slic3r::append(), Slic3r::SurfaceCut::contours, Slic3r::its_merge(), and Slic3r::offset().

Referenced by merge_patches().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ bounding_box() [1/3]

BoundingBoxf3 priv::bounding_box ( const CutAOI & cut,
const CutMesh & mesh )
2649 {
2650 const P3& p_from_cut = mesh.point(mesh.target(mesh.halfedge(cut.first.front())));
2651 Vec3d min = to_vec3d(p_from_cut);
2652 Vec3d max = min;
2653 for (FI fi : cut.first) {
2654 for(VI vi: mesh.vertices_around_face(mesh.halfedge(fi))){
2655 const P3& p = mesh.point(vi);
2656 for (size_t i = 0; i < 3; ++i) {
2657 if (min[i] > p[i]) min[i] = p[i];
2658 if (max[i] < p[i]) max[i] = p[i];
2659 }
2660 }
2661 }
2662 return BoundingBoxf3(min, max);
2663}
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
Vec3d to_vec3d(const P3 &p)
Definition CutSurface.cpp:115
CGAL::SM_Vertex_index VI
Definition CutSurface.cpp:109
CGAL::SM_Face_index FI
Definition CutSurface.cpp:112
CGAL::Epick::Point_3 P3
Definition CutSurface.cpp:113

References to_vec3d().

Referenced by bounding_box(), create_bbs(), divide_patch(), and separate_patch().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ bounding_box() [2/3]

BoundingBoxf3 priv::bounding_box ( const CutMesh & mesh)
2666{
2667 Vec3d min = to_vec3d(*mesh.points().begin());
2668 Vec3d max = min;
2669 for (VI vi : mesh.vertices()) {
2670 const P3 &p = mesh.point(vi);
2671 for (size_t i = 0; i < 3; ++i) {
2672 if (min[i] > p[i]) min[i] = p[i];
2673 if (max[i] < p[i]) max[i] = p[i];
2674 }
2675 }
2676 return BoundingBoxf3(min, max);
2677}

References to_vec3d().

Here is the call graph for this function:

◆ bounding_box() [3/3]

BoundingBoxf3 priv::bounding_box ( const SurfacePatch & ecut)
2679 {
2680 return bounding_box(ecut.mesh);
2681}
BoundingBoxf3 bounding_box(const CutAOI &cut, const CutMesh &mesh)
Definition CutSurface.cpp:2649
CutMesh mesh
Definition CutSurface.cpp:319

References bounding_box(), and priv::SurfacePatch::mesh.

Here is the call graph for this function:

◆ calc_distance()

float priv::calc_distance ( const P3 & p,
uint32_t pi,
const CutMesh & shapes_mesh,
float projection_ratio )

Calculate projection distance of point [in mm].

Parameters
pPoint to calc distance
piIndex of point on contour
shapes_meshModel of cutting shape
projection_ratioRatio for best projection distance
Returns
Distance of point from best projection
1745{
1746 // It is known because shapes_mesh is created inside of private space
1747 VI vi_start(2 * pi);
1748 VI vi_end(2 * pi + 1);
1749
1750 // Get range for intersection
1751 const P3 &start = shapes_mesh.point(vi_start);
1752 const P3 &end = shapes_mesh.point(vi_end);
1753
1754 // find index in vector with biggest difference
1755 size_t max_i = 0;
1756 float max_val = 0.f;
1757 for (size_t i = 0; i < 3; i++) {
1758 float val = start[i] - end[i];
1759 // abs value
1760 if (val < 0.f) val *= -1.f;
1761 if (max_val < val) {
1762 max_val = val;
1763 max_i = i;
1764 }
1765 }
1766
1767 float from_start = p[max_i] - start[max_i];
1768 float best_distance = projection_ratio * (end[max_i] - start[max_i]);
1769 return from_start - best_distance;
1770}
T * end(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:841

Referenced by calc_distances().

Here is the caller graph for this function:

◆ calc_distances()

priv::VDistances priv::calc_distances ( const SurfacePatches & patches,
const CutMeshes & models,
const CutMesh & shapes_mesh,
size_t count_shapes_points,
float projection_ratio )

Calculate distances for SurfacePatches outline points NOTE: each model has to have "vert_shape_map" .. Know source of new vertices.

Parameters
patchesPart of surface
modelsVertices position
shapes_meshMesh created by shapes
count_shapes_pointsCount of contour points in shapes
projection_ratioDefine best distnace
Returns
Projection distances of cutted shape points
1777{
1778 priv::VDistances result(count_shapes_points);
1779 for (const SurfacePatch &patch : patches) {
1780 // map is created during intersection by corefine visitor
1781 const VertexShapeMap vert_shape_map =
1782 models[patch.model_id].property_map<VI, const IntersectingElement *>(vert_shape_map_name).value();
1783 uint32_t patch_index = &patch - &patches.front();
1784 // map is created during patch creation / dividing
1785 const CvtVI2VI cvt = patch.mesh.property_map<VI, VI>(patch_source_name).value();
1786 // for each point on outline
1787 for (const Loop &loop : patch.loops)
1788 for (const VI &vi_patch : loop) {
1789 VI vi_model = cvt[vi_patch];
1790 if (!vi_model.is_valid()) continue;
1791 const IntersectingElement *ie = vert_shape_map[vi_model];
1792 if (ie == nullptr) continue;
1793 assert(ie->shape_point_index != std::numeric_limits<uint32_t>::max());
1794 assert(ie->attr != (unsigned char) IntersectingElement::Type::undefined);
1795 uint32_t pi = ie->shape_point_index;
1796 assert(pi <= count_shapes_points);
1797 std::vector<ProjectionDistance> &pds = result[pi];
1798 uint32_t model_index = patch.model_id;
1799 uint32_t aoi_index = patch.aoi_id;
1800 //uint32_t hi_index = &hi - &patch.outline.front();
1801 const P3 &p = patch.mesh.point(vi_patch);
1802 float distance = calc_distance(p, pi, shapes_mesh, projection_ratio);
1803 pds.push_back({model_index, aoi_index, patch_index, distance});
1804 }
1805 }
1806 return result;
1807}
CutMesh::Property_map< VI, const IntersectingElement * > VertexShapeMap
Definition CutSurface.cpp:221
const std::string vert_shape_map_name
Definition CutSurface.cpp:228
float calc_distance(const P3 &p, uint32_t pi, const CutMesh &shapes_mesh, float projection_ratio)
Calculate projection distance of point [in mm].
Definition CutSurface.cpp:1741
std::vector< ProjectionDistances > VDistances
Definition CutSurface.cpp:446
std::vector< VI > Loop
Definition CutSurface.cpp:301
const std::string patch_source_name
Definition CutSurface.cpp:250
CutMesh::Property_map< VI, VI > CvtVI2VI
Definition CutSurface.cpp:248
Definition CutSurface.cpp:315
IntersectingElement.
Definition CutSurface.cpp:180
uint32_t shape_point_index
Definition CutSurface.cpp:182
unsigned char attr
Definition CutSurface.cpp:185
@ undefined
Definition CutSurface.cpp:200

References priv::IntersectingElement::attr, calc_distance(), patch_source_name, priv::IntersectingElement::shape_point_index, priv::IntersectingElement::undefined, and vert_shape_map_name.

Referenced by Slic3r::cut_surface().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calc_size_sq()

float priv::calc_size_sq ( const Point & p)
1859 {
1860 // NOTE: p.squaredNorm() can't be use due to overflow max int value
1861 return (float) p.x() * p.x() + (float) p.y() * p.y();
1862}

Referenced by fill_shape_distances(), and find_close_point().

Here is the caller graph for this function:

◆ choose_best_distance()

priv::ProjectionDistances priv::choose_best_distance ( const VDistances & distances,
const ExPolygons & shapes,
const Point & start,
const ExPolygonsIndices & s2i,
const SurfacePatches & patches )

Select distances in similar depth between expolygons.

Parameters
distancesAll distances - Vector distances for each shape point
shapesVector of letters
startPivot for start projection in 2d
s2iConvert index to addresss inside of shape
patchesCutted parts from surface
Returns
Closest distance projection indexed by points in shapes(see s2i)
2254{
2255 assert(distances.size() == count_points(shapes));
2256
2257 // vector of patches for shape
2258 std::vector<std::vector<uint32_t>> shapes_patches(shapes.size());
2259 for (const SurfacePatch &patch : patches)
2260 shapes_patches[patch.shape_id].push_back(&patch-&patches.front());
2261
2262 // collect one closest projection for each outline point
2263 ProjectionDistances result(distances.size());
2264
2265 // store info about finished shapes
2266 std::vector<bool> finished_shapes(shapes.size(), {false});
2267
2268 // wanted distance from ideal projection
2269 // Distances are relative to projection distance
2270 // so first wanted distance is the closest one (ZERO)
2271 float wanted_distance = 0.f;
2272
2273 std::vector<bool> mask_distances(s2i.get_count(), {true});
2274 for (const auto &d : distances)
2275 if (d.empty()) mask_distances[&d - &distances.front()] = false;
2276
2277 // Select point from shapes(text contour) which is closest to center (all in 2d)
2278 uint32_t unfinished_index = find_closest_point_index(start, shapes, s2i, mask_distances);
2279 assert(unfinished_index < s2i.get_count());
2280 if (unfinished_index >= s2i.get_count())
2281 // no point to select
2282 return result;
2283
2284#ifdef DEBUG_OUTPUT_DIR
2285 Connections connections;
2286 connections.reserve(shapes.size());
2287 connections.emplace_back(unfinished_index, unfinished_index);
2288#endif // DEBUG_OUTPUT_DIR
2289
2290 do {
2291 const ProjectionDistance* pd = get_closest_projection(distances[unfinished_index], wanted_distance);
2292 // selection of closest_id should proove that pd has value
2293 // (functions: get_closest_point_index and find_close_point_in_points)
2294 assert(pd != nullptr);
2295 uint32_t expolygons_index = s2i.cvt(unfinished_index).expolygons_index;
2296 const ExPolygon &shape = shapes[expolygons_index];
2297 std::vector<uint32_t> &shape_patches = shapes_patches[expolygons_index];
2298 if (shape_patches.size() == 1){
2299 // Speed up, only one patch so copy distance from patch
2300 uint32_t first_shape_index = s2i.cvt({expolygons_index, 0, 0});
2301 uint32_t laset_shape_index = first_shape_index + count_points(shape);
2302 for (uint32_t i = first_shape_index; i < laset_shape_index; ++i) {
2303 const ProjectionDistances &pds = distances[i];
2304 if (pds.empty()) continue;
2305 // check that index belongs to patch
2306 assert(pds.front().patch_index == shape_patches.front());
2307 result[i] = pds.front();
2308 if (pds.size() == 1) continue;
2309
2310 float relative_distance = fabs(result[i].distance - pd->distance);
2311 // patch could contain multiple value for one outline point
2312 // so choose closest to start point
2313 for (uint32_t pds_index = 1; pds_index < pds.size(); ++pds_index) {
2314 // check that index still belongs to same patch
2315 assert(pds[pds_index].patch_index == shape_patches.front());
2316 float relative_distance2 = fabs(pds[pds_index].distance - pd->distance);
2317 if (relative_distance > relative_distance2) {
2318 relative_distance = relative_distance2;
2319 result[i] = pds[pds_index];
2320 }
2321 }
2322 }
2323 } else {
2324 // multiple patches for expolygon
2325 // check that exist patch to fill shape
2326 assert(!shape_patches.empty());
2327 fill_shape_distances(unfinished_index, pd, result, s2i, shape, distances);
2328 }
2329
2330 finished_shapes[expolygons_index] = true;
2331 // The most close points between finished and unfinished shapes
2332 auto [finished, unfinished] = find_closest_point_pair(
2333 shapes, finished_shapes, s2i, mask_distances);
2334
2335 // detection of end (best doesn't have value)
2336 if (finished == std::numeric_limits<uint32_t>::max()) break;
2337
2338 assert(unfinished != std::numeric_limits<uint32_t>::max());
2339 const ProjectionDistance &closest_pd = result[finished];
2340 // check that best_cp is finished and has result
2341 assert(closest_pd.aoi_index != std::numeric_limits<uint32_t>::max());
2342 wanted_distance = closest_pd.distance;
2343 unfinished_index = unfinished;
2344
2345#ifdef DEBUG_OUTPUT_DIR
2346 connections.emplace_back(finished, unfinished);
2347#endif // DEBUG_OUTPUT_DIR
2348 } while (true); //(unfinished_index != std::numeric_limits<uint32_t>::max());
2349#ifdef DEBUG_OUTPUT_DIR
2350 store(shapes, mask_distances, connections, DEBUG_OUTPUT_DIR + "closest_points.svg");
2351#endif // DEBUG_OUTPUT_DIR
2352 return result;
2353}
Definition ExPolygon.hpp:23
uint32_t get_count() const
Count of points in expolygons.
Definition ExPolygonsIndex.cpp:89
uint32_t cvt(const ExPolygonsIndex &id) const
Convert to one index number.
Definition ExPolygonsIndex.cpp:32
size_t count_points(const ExPolygons &expolys)
Definition ExPolygon.hpp:95
bool store(const Facenames &facenames)
Definition GLGizmoEmboss.cpp:3560
std::vector< ProjectionDistance > ProjectionDistances
Definition CutSurface.cpp:443
std::pair< uint32_t, uint32_t > find_closest_point_pair(const ExPolygons &shapes, const std::vector< bool > &done_shapes, const ExPolygonsIndices &s2i, const std::vector< bool > &mask)
Definition CutSurface.cpp:1986
const ProjectionDistance * get_closest_projection(const ProjectionDistances &distance, float wanted_distance)
Definition CutSurface.cpp:2057
uint32_t find_closest_point_index(const Point &p, const ExPolygons &shapes, const ExPolygonsIndices &s2i, const std::vector< bool > &mask)
Definition CutSurface.cpp:1948
void fill_shape_distances(uint32_t start_index, const ProjectionDistance *start_pd, ProjectionDistances &result, const ExPolygonsIndices &s2i, const ExPolygon &shape, const VDistances &distances)
Definition CutSurface.cpp:2141
float distance
Definition CutSurface.cpp:440
To select surface near projection distance.
Definition CutSurface.cpp:429

References priv::ProjectionDistance::aoi_index, Slic3r::count_points(), Slic3r::ExPolygonsIndices::cvt(), priv::ProjectionDistance::distance, fill_shape_distances(), find_closest_point_index(), find_closest_point_pair(), get_closest_projection(), and Slic3r::ExPolygonsIndices::get_count().

Referenced by Slic3r::cut_surface().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear()

void priv::clear ( IconManager::Icons & icons)
static
305 {
306 std::string message;
307 for (auto &icon : icons) {
308 // Exist more than this instance of shared ptr?
309 long count = icon.use_count();
310 if (count != 1) {
311 // in existing icon change texture to non existing one
312 icon->tex_id = 0;
313
314 std::string descr =
315 ((count > 2) ? (std::to_string(count - 1) + "x") : "") + // count
316 std::to_string(icon->size.x) + "x" + std::to_string(icon->size.y); // resolution
317 if (message.empty())
318 message = descr;
319 else
320 message += ", " + descr;
321 }
322 }
323
324 if (!message.empty())
325 BOOST_LOG_TRIVIAL(warning) << "There is still used icons(" << message << ").";
326}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246

References count.

Referenced by Slic3r::GUI::IconManager::~IconManager(), and Slic3r::GUI::IconManager::init().

Here is the caller graph for this function:

◆ clip_cut()

bool priv::clip_cut ( SurfacePatch & cut,
CutMesh clipper )

Implement 'cut' Minus 'clipper', where clipper is reverse input Volume NOTE: clipper will be modified (corefined by cut) !!!

Parameters
cutdiffer from
clipperdiffer what
Returns
True on succes, otherwise FALSE
2593{
2594 CutMesh& tm = cut.mesh;
2595 auto is_mesh_usable_for_clip = [](const CutMesh &mesh) {
2596 return !mesh.is_empty() &&
2597 mesh.number_of_vertices() >= 3 &&
2598 mesh.number_of_faces() > 0 &&
2599 mesh.is_valid(false);
2600 };
2601
2602 if (!is_mesh_usable_for_clip(tm) || !is_mesh_usable_for_clip(clipper))
2603 return false;
2604
2605 // Hard-stop pathological inputs before entering corefinement internals.
2606 if (CGAL::Polygon_mesh_processing::does_self_intersect(tm) ||
2607 CGAL::Polygon_mesh_processing::does_self_intersect(clipper))
2608 return false;
2609
2610 // create backup for case that there is no intersection
2611 CutMesh backup_copy = tm;
2612
2613 class ExistIntersectionClipVisitor: public CGAL::Polygon_mesh_processing::Corefinement::Default_visitor<CutMesh>
2614 {
2615 bool* exist_intersection;
2616 public:
2617 ExistIntersectionClipVisitor(bool *exist_intersection): exist_intersection(exist_intersection){}
2618 void intersection_point_detected(std::size_t, int , HI, HI, const CutMesh&, const CutMesh&, bool, bool)
2619 { *exist_intersection = true;}
2620 };
2621 bool exist_intersection = false;
2622 ExistIntersectionClipVisitor visitor{&exist_intersection};
2623
2624 // namep parameters for model tm and function clip
2625 const auto &np_tm = CGAL::parameters::visitor(visitor)
2626 .throw_on_self_intersection(false);
2627
2628 // name parameters for model clipper and function clip
2629 const auto &np_c = CGAL::parameters::throw_on_self_intersection(false);
2630 // Can't use 'do_not_modify', when Ture than clipper has to be closed !!
2631 // .do_not_modify(true);
2632 // .throw_on_self_intersection(false); is set automaticaly by param 'do_not_modify'
2633 // .clip_volume(false); is set automaticaly by param 'do_not_modify'
2634
2635 bool suc = CGAL::Polygon_mesh_processing::clip(tm, clipper, np_tm, np_c);
2636
2637 // true if the output surface mesh is manifold.
2638 // If false is returned tm and clipper are only corefined.
2639 assert(suc);
2640 // decide what TODO when can't clip source object !?!
2641 if (!exist_intersection || !suc) {
2642 // TODO: test if cut is fully in or fully out!!
2643 cut.mesh = backup_copy;
2644 return false;
2645 }
2646 return true;
2647}
CGAL::Surface_mesh< EpicKernel::Point_3 > CutMesh
Definition CutSurface.cpp:106

References priv::SurfacePatch::mesh.

Referenced by diff_models().

Here is the caller graph for this function:

◆ collect_open_edges()

void priv::collect_open_edges ( SurfacePatches & patches)

Fill outline in patches by open edges.

Parameters
patchesInput/Output meshes with open edges
3053 {
3054 std::vector<HI> open_half_edges;
3055 for (SurfacePatch &patch : patches) {
3056 open_half_edges.clear();
3057 const CutMesh &mesh = patch.mesh;
3058 for (FI fi : mesh.faces()) {
3059 HI hi1 = mesh.halfedge(fi);
3060 assert(hi1.is_valid());
3061 HI hi2 = mesh.next(hi1);
3062 assert(hi2.is_valid());
3063 HI hi3 = mesh.next(hi2);
3064 assert(hi3.is_valid());
3065 // Is fi triangle?
3066 assert(mesh.next(hi3) == hi1);
3067 for (HI hi : {hi1, hi2, hi3}) {
3068 HI hi_op = mesh.opposite(hi);
3069 FI fi_op = mesh.face(hi_op);
3070 if (!fi_op.is_valid())
3071 open_half_edges.push_back(hi);
3072 }
3073 }
3074 patch.loops = create_loops(open_half_edges, mesh);
3075 }
3076}
CGAL::SM_Halfedge_index HI
Definition CutSurface.cpp:110
Loops create_loops(const std::vector< HI > &outlines, const CutMesh &mesh)
Create closed loops of contour vertices created from open half edges.
Definition CutSurface.cpp:3442

References create_loops().

Referenced by diff_models().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ collect_surface_data()

void priv::collect_surface_data ( std::queue< FI > & process,
std::vector< FI > & faces,
std::vector< HI > & outlines,
FaceTypeMap & face_type_map,
const CutMesh & mesh )

Collect connected inside faces Collect outline half edges.

Parameters
processQueue of face to process - find connected
faces[Output] collected Face indices from mesh
outlines[Output] collected Halfedge indices from mesh
face_type_mapUse flag inside / outside NOTE: Modify in function: inside -> inside_processed
meshmesh to process
1549{
1550 assert(!process.empty());
1551 assert(faces.empty());
1552 assert(outlines.empty());
1553 while (!process.empty()) {
1554 FI fi = process.front();
1555 process.pop();
1556
1557 FaceType &fi_type = face_type_map[fi];
1558 // Do not process twice
1559 if (fi_type == FaceType::inside_processed) continue;
1560 assert(fi_type == FaceType::inside);
1561 // flag face as processed
1563 faces.push_back(fi);
1564
1565 // check neighbor triangle
1566 HI hi = mesh.halfedge(fi);
1567 HI hi_end = hi;
1568 do {
1569 HI hi_opposite = mesh.opposite(hi);
1570 // open edge doesn't have opposit half edge
1571 if (!hi_opposite.is_valid()) {
1572 outlines.push_back(hi);
1573 hi = mesh.next(hi);
1574 continue;
1575 }
1576 FI fi_opposite = mesh.face(hi_opposite);
1577 if (!fi_opposite.is_valid()) {
1578 outlines.push_back(hi);
1579 hi = mesh.next(hi);
1580 continue;
1581 }
1582 FaceType side = face_type_map[fi_opposite];
1583 if (side == FaceType::inside) {
1584 process.emplace(fi_opposite);
1585 } else if (side == FaceType::outside) {
1586 // store outlines
1587 outlines.push_back(hi);
1588 }
1589 hi = mesh.next(hi);
1590 } while (hi != hi_end);
1591 }
1592}
bool process(std::exception_ptr &eptr)
Definition EmbossJob.cpp:1427
FaceType
Flag for faces in CGAL mesh.
Definition CutSurface.cpp:233
@ inside
Definition CutSurface.cpp:235

References inside, inside_processed, and outside.

Referenced by create_cut_area_of_interests().

Here is the caller graph for this function:

◆ create_bbs()

std::vector< BoundingBoxf3 > priv::create_bbs ( const VCutAOIs & cuts,
const CutMeshes & cut_models )

Create bounding boxes for AOI.

Parameters
cutsCutted AOI from models
cut_modelsSource points of cuts
Returns
Bounding boxes
2883{
2884 size_t count = 0;
2885 for (const CutAOIs &cut : cuts) count += cut.size();
2886
2887 std::vector<BoundingBoxf3> bbs;
2888 bbs.reserve(count);
2889 for (size_t model_index = 0; model_index < cut_models.size(); ++model_index) {
2890 const CutMesh &cut_model = cut_models[model_index];
2891 const CutAOIs &cutAOIs = cuts[model_index];
2892 for (size_t cut_index = 0; cut_index < cutAOIs.size(); ++cut_index) {
2893 const CutAOI &cut = cutAOIs[cut_index];
2894 bbs.push_back(bounding_box(cut, cut_model));
2895 }
2896 }
2897 return bbs;
2898}
std::vector< CutAOI > CutAOIs
Definition CutSurface.cpp:279
std::pair< std::vector< FI >, std::vector< HI > > CutAOI
Definition CutSurface.cpp:277

References bounding_box(), and count.

Referenced by diff_models().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_cut_area_of_interests()

priv::CutAOIs priv::create_cut_area_of_interests ( const CutMesh & mesh,
const ExPolygons & shapes,
FaceTypeMap & face_type_map )

Create areas from mesh surface.

Parameters
meshModel
shapesCutted shapes
face_type_mapDefine Triangles of interest. Edge between inside / outside. NOTE: Not const because it need to flag proccessed faces
Returns
Areas of interest from mesh
1690{
1691 // IMPROVE: Create better heuristic for count.
1692 size_t faces_per_cut = mesh.faces().size() / shapes.size();
1693 size_t outlines_per_cut = faces_per_cut / 2;
1694 size_t cuts_per_model = shapes.size() * 2;
1695
1696 CutAOIs result;
1697 result.reserve(cuts_per_model);
1698
1699 // It is faster to use one queue for all cuts
1700 std::queue<FI> process;
1701 for (FI fi : mesh.faces()) {
1702 if (face_type_map[fi] != FaceType::inside) continue;
1703
1704 CutAOI cut;
1705 std::vector<FI> &faces = cut.first;
1706 std::vector<HI> &outlines = cut.second;
1707
1708 // faces for one surface cut
1709 faces.reserve(faces_per_cut);
1710 // outline for one surface cut
1711 outlines.reserve(outlines_per_cut);
1712
1713 assert(process.empty());
1714 // Process queue of faces to separate to surface_cut
1715 process.push(fi);
1716 collect_surface_data(process, faces, outlines, face_type_map, mesh);
1717 assert(!faces.empty());
1718 assert(!outlines.empty());
1719 result.emplace_back(std::move(cut));
1720 }
1721 return result;
1722}
void collect_surface_data(std::queue< FI > &process, std::vector< FI > &faces, std::vector< HI > &outlines, FaceTypeMap &face_type_map, const CutMesh &mesh)
Collect connected inside faces Collect outline half edges.
Definition CutSurface.cpp:1544

References collect_surface_data(), and inside.

Referenced by cut_from_model().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_face_types()

void priv::create_face_types ( FaceTypeMap & map,
const CutMesh & tm1,
const CutMesh & tm2,
const EdgeBoolMap & ecm,
const VertexSourceMap & sources )

Create map1 and map2.

Parameters
mapConvert tm1.face to type
tm1Corefined mesh
tm2Source of intersection
ecm1Identify constrainde edge
sourcesConvert tm1.face to type
2501{
2502 auto get_intersection_source = [&tm2](const Source& s1, const Source& s2)->FI{
2503 // when one of sources is face than return it
2504 FI fi1 = tm2.face(s1.hi);
2505 if (s1.sdim == 2) return fi1;
2506 FI fi2 = tm2.face(s2.hi);
2507 if (s2.sdim == 2) return fi2;
2508 // both vertices are made by same source triangle
2509 if (fi1 == fi2) return fi1;
2510
2511 // when one from sources is edge second one decide side of triangle triangle
2512 HI hi1_opposit = tm2.opposite(s1.hi);
2513 FI fi1_opposit;
2514 if (hi1_opposit.is_valid())
2515 fi1_opposit = tm2.face(hi1_opposit);
2516 if (fi2 == fi1_opposit) return fi2;
2517
2518 HI hi2_opposit = tm2.opposite(s2.hi);
2519 FI fi2_opposit;
2520 if (hi2_opposit.is_valid())
2521 fi2_opposit = tm2.face(hi2_opposit);
2522 if (fi1 == fi2_opposit) return fi1;
2523 if (fi1_opposit.is_valid() && fi1_opposit == fi2_opposit)
2524 return fi1_opposit;
2525
2526 // when intersection is vertex need loop over neighbor
2527 for (FI fi_around_hi1 : tm2.faces_around_target(s1.hi)) {
2528 for (FI fi_around_hi2 : tm2.faces_around_target(s2.hi)) {
2529 if (fi_around_hi1 == fi_around_hi2)
2530 return fi_around_hi1;
2531 }
2532 }
2533
2534 // should never rich it
2535 // Exist case when do not know source triangle for decide side of intersection
2536 assert(false);
2537 return FI();
2538 };
2539
2540 for (FI fi : tm1.faces()) map[fi] = FaceType::not_constrained;
2541 for (EI ei1 : tm1.edges()) {
2542 if (!get(ecm, ei1)) continue;
2543
2544 // get faces from tm1 (f1a + f1b)
2545 HI hi1 = tm1.halfedge(ei1);
2546 assert(hi1.is_valid());
2547 FI f1a = tm1.face(hi1);
2548 assert(f1a.is_valid());
2549 HI hi_op = tm1.opposite(hi1);
2550 assert(hi_op.is_valid());
2551 FI f1b = tm1.face(hi_op);
2552 assert(f1b.is_valid());
2553
2554 // get faces from tm2 (f2a + f2b)
2555 VI vi1_source = tm1.source(hi1);
2556 assert(vi1_source.is_valid());
2557 VI vi1_target = tm1.target(hi1);
2558 assert(vi1_target.is_valid());
2559
2560 const Source &s_s = sources[vi1_source];
2561 const Source &s_t = sources[vi1_target];
2562 FI fi2 = get_intersection_source(s_s, s_t);
2563
2564 // in release solve situation that face was NOT deduced
2565 if (!fi2.is_valid()) continue;
2566
2567 HI hi2 = tm2.halfedge(fi2);
2568 std::array<const P3 *, 3> t;
2569 size_t ti =0;
2570 for (VI vi2 : tm2.vertices_around_face(hi2))
2571 t[ti++] = &tm2.point(vi2);
2572
2573 // triangle tip from face f1a
2574 VI vi1a_tip = tm1.target(tm1.next(hi1));
2575 assert(vi1a_tip.is_valid());
2576 const P3 &p = tm1.point(vi1a_tip);
2577
2578 // check if f1a is behinde f2a
2579 // inside mean it will be used
2580 // outside will be discarded
2581 if (CGAL::orientation(*t[0], *t[1], *t[2], p) == CGAL::POSITIVE) {
2582 map[f1a] = FaceType::inside;
2583 map[f1b] = FaceType::outside;
2584 } else {
2585 map[f1a] = FaceType::outside;
2586 map[f1b] = FaceType::inside;
2587 }
2588 }
2589}
id get(id object, const void *key)
Definition MacIME.mm:22
CGAL::SM_Edge_index EI
Definition CutSurface.cpp:111
int sdim
Definition CutSurface.cpp:2360
HI hi
Definition CutSurface.cpp:2360
Definition CutSurface.cpp:2360

References priv::Source::hi, inside, not_constrained, outside, and priv::Source::sdim.

◆ create_loops()

priv::Loops priv::create_loops ( const std::vector< HI > & outlines,
const CutMesh & mesh )

Create closed loops of contour vertices created from open half edges.

Parameters
outlinesUnsorted half edges
meshSource mesh for half edges
Returns
Closed loops
3443{
3444 Loops loops;
3445 Loops unclosed;
3446 for (HI hi : outlines) {
3447 VI vi_s = mesh.source(hi);
3448 VI vi_t = mesh.target(hi);
3449 Loop *loop_move = nullptr;
3450 Loop *loop_connect = nullptr;
3451 for (std::vector<VI> &cut : unclosed) {
3452 if (cut.back() != vi_s) continue;
3453 if (cut.front() == vi_t) {
3454 // cut closing
3455 loop_move = &cut;
3456 } else {
3457 loop_connect = &cut;
3458 }
3459 break;
3460 }
3461 if (loop_move != nullptr) {
3462 // index of closed cut
3463 size_t index = loop_move - &unclosed.front();
3464 // move cut to result
3465 loops.emplace_back(std::move(*loop_move));
3466 // remove it from unclosed cut
3467 unclosed.erase(unclosed.begin() + index);
3468 } else if (loop_connect != nullptr) {
3469 // try find tail to connect cut
3470 Loop *loop_tail = nullptr;
3471 for (Loop &cut : unclosed) {
3472 if (cut.front() != vi_t) continue;
3473 loop_tail = &cut;
3474 break;
3475 }
3476 if (loop_tail != nullptr) {
3477 // index of tail
3478 size_t index = loop_tail - &unclosed.front();
3479 // move to connect vector
3480 loop_connect->insert(loop_connect->end(),
3481 make_move_iterator(loop_tail->begin()),
3482 make_move_iterator(loop_tail->end()));
3483 // remove tail from unclosed cut
3484 unclosed.erase(unclosed.begin() + index);
3485 } else {
3486 loop_connect->push_back(vi_t);
3487 }
3488 } else { // not found
3489 bool create_cut = true;
3490 // try to insert to front of cut
3491 for (Loop &cut : unclosed) {
3492 if (cut.front() != vi_t) continue;
3493 cut.insert(cut.begin(), vi_s);
3494 create_cut = false;
3495 break;
3496 }
3497 if (create_cut)
3498 unclosed.emplace_back(std::vector{vi_s, vi_t});
3499 }
3500 }
3501 assert(unclosed.empty());
3502 return loops;
3503}
std::vector< Loop > Loops
Definition CutSurface.cpp:302

Referenced by collect_open_edges().

Here is the caller graph for this function:

◆ create_reduce_map()

void priv::create_reduce_map ( ReductionMap & reduction_map,
const CutMesh & meshes )

Create map to reduce unnecesary triangles, Triangles are made by divided quad to two triangles on side of cutting shape mesh Note: also use from mesh (have to be created) face_type_map .. Type of shape inside / outside vert_shape_map .. Source of outline vertex.

Parameters
reduction_mapReduction map from vertex to vertex, when key == value than no reduction
facesFaces of one
meshInput object

Append reduction or change existing one.

Parameters
hiHalEdge between outside and inside face. Target vertex will be reduced, source vertex left

[[maybe_unused]] &face_type_map, &is_reducible_vertex are need only in debug

1595{
1596 const VertexShapeMap vert_shape_map = mesh.property_map<VI, const IntersectingElement*>(vert_shape_map_name).value();
1597 const EdgeBoolMap ecm = mesh.property_map<EI, bool>(is_constrained_edge_name).value();
1598
1599 // check if vertex was made by edge_2 which is diagonal of quad
1600 auto is_reducible_vertex = [&vert_shape_map](VI reduction_from) -> bool {
1601 const IntersectingElement *ie = vert_shape_map[reduction_from];
1602 if (ie == nullptr) return false;
1604 return type == IntersectingElement::Type::edge_2;
1605 };
1606
1613 auto add_reduction = [&] //&reduction_map, &mesh, &face_type_map, &is_reducible_vertex
1614 (HI hi) {
1615 VI erase = mesh.target(hi);
1616 VI left = mesh.source(hi);
1617 assert(is_reducible_vertex(erase));
1618 assert(!is_reducible_vertex(left));
1619 VI &vi = reduction_map[erase];
1620 // check if it is first add
1621 if (vi.is_valid())
1622 return;
1623
1624 // check that all triangles after reduction has 'erase' and 'left' vertex
1625 // on same side of opposite line of vertex in triangle
1626 Vec3d v_erase = to_vec3d(mesh.point(erase));
1627 Vec3d v_left = to_vec3d(mesh.point(left));
1628 for (FI fi : mesh.faces_around_target(hi)) {
1629 if (!fi.is_valid())
1630 continue;
1631 // get vertices of rest
1632 VI vi_a, vi_b;
1633 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi))) {
1634 if (!vi.is_valid())
1635 continue;
1636 if (vi == erase)
1637 continue;
1638 if (!vi_a.is_valid())
1639 vi_a = vi;
1640 else {
1641 assert(!vi_b.is_valid());
1642 vi_b = vi;
1643 }
1644 }
1645 assert(vi_b.is_valid());
1646 // do not check triangle, which will be removed
1647 if (vi_a == left || vi_b == left)
1648 continue;
1649
1650 Vec3d v_a = to_vec3d(mesh.point(vi_a));
1651 Vec3d v_b = to_vec3d(mesh.point(vi_b));
1652 // Vectors of triangle edges
1653 Vec3d v_ab = v_b - v_a;
1654 Vec3d v_ae = v_erase - v_a;
1655 Vec3d v_al = v_left - v_a;
1656
1657 Vec3d n1 = v_ab.cross(v_ae);
1658 Vec3d n2 = v_ab.cross(v_al);
1659 // check that normal has same direction
1660 if (((n1.x() > 0) != (n2.x() > 0)) ||
1661 ((n1.y() > 0) != (n2.y() > 0)) ||
1662 ((n1.z() > 0) != (n2.z() > 0)))
1663 return; // this reduction will create CCW triangle
1664 }
1665
1666 reduction_map[erase] = left;
1667 // I have no better rule than take the first
1668 // for decide which reduction will be better
1669 // But it could be use only one of them
1670 };
1671
1672 for (EI ei : mesh.edges()) {
1673 if (!ecm[ei]) continue;
1674 HI hi = mesh.halfedge(ei);
1675 VI vi = mesh.target(hi);
1676 if (is_reducible_vertex(vi)) add_reduction(hi);
1677
1678 HI hi_op = mesh.opposite(hi);
1679 VI vi_op = mesh.target(hi_op);
1680 if (is_reducible_vertex(vi_op)) add_reduction(hi_op);
1681 }
1682#ifdef DEBUG_OUTPUT_DIR
1683 store(mesh, reduction_map, DEBUG_OUTPUT_DIR + "reduces/");
1684#endif // DEBUG_OUTPUT_DIR
1685}
void erase(std::vector< VecType > &vec, const std::vector< bool > &flags)
Definition RaycastManager.cpp:315
@ left
Definition MarchingSquares.hpp:188
const std::string is_constrained_edge_name
Definition CutSurface.cpp:259
CutMesh::Property_map< EI, bool > EdgeBoolMap
Definition CutSurface.cpp:258
Type get_type() const
Definition CutSurface.cpp:211
Type
Definition CutSurface.cpp:195
@ edge_2
Definition CutSurface.cpp:198

References priv::IntersectingElement::edge_2, priv::IntersectingElement::get_type(), is_constrained_edge_name, to_vec3d(), and vert_shape_map_name.

Referenced by diff_models().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_search_data()

priv::SearchData priv::create_search_data ( const ExPolygons & shapes,
const std::vector< bool > & mask )
1866{
1867 // IMPROVE: Use float precission (it is enough)
1868 SearchData sd;
1869 sd.lines.reserve(mask.size());
1870 sd.cvt.reserve(mask.size());
1871 size_t index = 0;
1872 auto add_lines = [&sd, &index, &mask]
1873 (const Polygon &poly) {
1874 Vec2d prev = poly.back().cast<double>();
1875 bool use_point = mask[index + poly.points.size() - 1];
1876 for (const Point &p : poly.points) {
1877 if (!use_point) {
1878 use_point = mask[index];
1879 if (use_point) prev = p.cast<double>();
1880 } else if (!mask[index]) {
1881 use_point = false;
1882 } else {
1883 Vec2d p_d = p.cast<double>();
1884 sd.lines.emplace_back(prev, p_d);
1885 sd.cvt.push_back(index);
1886 prev = p_d;
1887 }
1888 ++index;
1889 }
1890 };
1891
1892 for (const ExPolygon &shape : shapes) {
1893 add_lines(shape.contour);
1894 for (const Polygon &hole : shape.holes) add_lines(hole);
1895 }
1897 return sd;
1898}
Definition Point.hpp:199
Definition Polygon.hpp:31
AABBTreeIndirect::Tree< LineType::Dim, typename LineType::Scalar > build_aabb_tree_over_indexed_lines(const std::vector< LineType > &lines)
Definition AABBTreeLines.hpp:172
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
std::vector< size_t > cvt
Definition CutSurface.cpp:1831
std::vector< Linef > lines
Definition CutSurface.cpp:1829
AABBTreeIndirect::Tree< 2, double > tree
Definition CutSurface.cpp:1833
Definition CutSurface.cpp:1827

References Slic3r::AABBTreeLines::build_aabb_tree_over_indexed_lines(), priv::SearchData::cvt, priv::SearchData::lines, and priv::SearchData::tree.

Referenced by find_closest_point_index(), and find_closest_point_pair().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_surface_patch()

priv::SurfacePatch priv::create_surface_patch ( const std::vector< FI > & fis,
CutMesh & mesh,
const ReductionMap * rmap = nullptr )

Create patch.

Parameters
fisDefine patch faces
meshSource of fis NOTE: Need temporary add property map for convert vertices
rmapOptions to reduce vertices from fis. NOTE: Used for skip vertices made by diagonal edge in rectangle of shape side
Returns
Patch
2686{
2687 auto is_counted = mesh.add_property_map<VI, bool>("v:is_counted").first;
2688 uint32_t count_vertices = 0;
2689 if (rmap == nullptr) {
2690 for (FI fi : fis)
2691 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi)))
2692 if (!is_counted[vi]) {
2693 is_counted[vi] = true;
2694 ++count_vertices;
2695 }
2696 } else {
2697 for (FI fi : fis)
2698 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi))) {
2699 // Will vertex be reduced?
2700 if ((*rmap)[vi].is_valid()) continue;
2701 if (!is_counted[vi]) {
2702 is_counted[vi] = true;
2703 ++count_vertices;
2704 }
2705 }
2706 }
2707 mesh.remove_property_map(is_counted);
2708
2709 uint32_t count_faces = fis.size();
2710 // IMPROVE: Value is greater than neccessary, count edges used twice
2711 uint32_t count_edges = count_faces*3;
2712
2713 CutMesh cm;
2714 cm.reserve(count_vertices, count_edges, count_faces);
2715
2716 // vertex conversion function from mesh VI to result VI
2717 CvtVI2VI mesh2result = mesh.add_property_map<VI,VI>("v:mesh2result").first;
2718
2719 if (rmap == nullptr) {
2720 for (FI fi : fis) {
2721 std::array<VI, 3> t;
2722 int index = 0;
2723 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi))) {
2724 VI &vi_cvt = mesh2result[vi];
2725 if (!vi_cvt.is_valid()) {
2726 vi_cvt = VI(cm.vertices().size());
2727 cm.add_vertex(mesh.point(vi));
2728 }
2729 t[index++] = vi_cvt;
2730 }
2731 cm.add_face(t[0], t[1], t[2]);
2732 }
2733 } else {
2734 for (FI fi :fis) {
2735 std::array<VI, 3> t;
2736 int index = 0;
2737 bool exist_reduction = false;
2738 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi))) {
2739 VI vi_r = (*rmap)[vi];
2740 if (vi_r.is_valid()) {
2741 exist_reduction = true;
2742 vi = vi_r;
2743 }
2744 VI &vi_cvt = mesh2result[vi];
2745 if (!vi_cvt.is_valid()) {
2746 vi_cvt = VI(cm.vertices().size());
2747 cm.add_vertex(mesh.point(vi));
2748 }
2749 t[index++] = vi_cvt;
2750 }
2751
2752 // prevent add reduced triangle
2753 if (exist_reduction &&
2754 (t[0] == t[1] ||
2755 t[1] == t[2] ||
2756 t[2] == t[0]))
2757 continue;
2758
2759 cm.add_face(t[0], t[1], t[2]);
2760 }
2761 }
2762
2763 assert(count_vertices == cm.vertices().size());
2764 assert((rmap == nullptr && count_faces == cm.faces().size()) ||
2765 (rmap != nullptr && count_faces >= cm.faces().size()));
2766 assert(count_edges >= cm.edges().size());
2767
2768 // convert VI from this patch to source VI, when exist
2769 CvtVI2VI cvt = cm.add_property_map<VI, VI>(patch_source_name).first;
2770 // vi_s .. VertexIndex into mesh (source)
2771 // vi_d .. new VertexIndex in cm (destination)
2772 for (VI vi_s : mesh.vertices()) {
2773 VI vi_d = mesh2result[vi_s];
2774 if (!vi_d.is_valid()) continue;
2775 cvt[vi_d] = vi_s;
2776 }
2777 mesh.remove_property_map(mesh2result);
2778 return {std::move(cm)};
2779}
bool is_valid(const FontFile &font, unsigned int index)
Definition Emboss.cpp:284

References patch_source_name.

Referenced by diff_models(), and separate_patch().

Here is the caller graph for this function:

◆ create_trees()

priv::Trees priv::create_trees ( const CutMeshes & models)

Create AABB trees for check when patch is whole inside of model.

Parameters
modelsSource for trees
Returns
trees
2901 {
2902 Trees result;
2903 result.reserve(models.size());
2904 for (const CutMesh &model : models) {
2905 Tree tree;
2906 tree.insert(faces(model).first, faces(model).second, model);
2907 tree.build();
2908 result.emplace_back(std::move(tree));
2909 }
2910 return result;
2911}
CGAL::AABB_tree< Traits > Tree
Definition CutSurface.cpp:2808
std::vector< Tree > Trees
Definition CutSurface.cpp:2809

◆ cut_from_model()

priv::CutAOIs priv::cut_from_model ( CutMesh & cgal_model,
const ExPolygons & shapes,
CutMesh & cgal_shape,
float projection_ratio,
const ExPolygonsIndices & s2i )

Create AOIs(area of interest) on model surface.

Parameters
cgal_modelInput model converted to CGAL NOTE: will be extended by corefine edge
shapes2d contours
cgal_shape[const]Model made by shapes NOTE: Can't be definde as const because of corefine function input definition, but it is.
projection_ratioWanted projection distance
s2iConvert index to shape point from ExPolygons
Returns
Patches from model surface
1439{
1440 // pointer to edge or face shape_map
1441 VertexShapeMap vert_shape_map = cgal_model.add_property_map<VI, const IntersectingElement*>(vert_shape_map_name, nullptr).first;
1442
1443 // detect anomalities in visitor.
1444 bool is_valid = true;
1445 // NOTE: map are created when convert shapes to cgal model
1446 const EdgeShapeMap edge_shape_map = cgal_shape.property_map<EI, IntersectingElement>(edge_shape_map_name).value();
1447 const FaceShapeMap face_shape_map = cgal_shape.property_map<FI, IntersectingElement>(face_shape_map_name).value();
1448 Visitor visitor{cgal_model, cgal_shape, edge_shape_map, face_shape_map, vert_shape_map, &is_valid};
1449
1450 // a property map containing the constrained-or-not status of each edge
1451 EdgeBoolMap ecm = cgal_model.add_property_map<EI, bool>(is_constrained_edge_name, false).first;
1452 const auto &p = CGAL::parameters::visitor(visitor)
1453 .edge_is_constrained_map(ecm)
1454 .throw_on_self_intersection(false);
1455 const auto& q = CGAL::parameters::do_not_modify(true);
1456 CGAL::Polygon_mesh_processing::corefine(cgal_model, cgal_shape, p, q);
1457
1458 if (!is_valid) return {};
1459
1460 FaceTypeMap face_type_map = cgal_model.add_property_map<FI, FaceType>(face_type_map_name, FaceType::not_constrained).first;
1461
1462 // Select inside and outside face in model
1463 set_face_type(face_type_map, cgal_model, vert_shape_map, ecm, cgal_shape, s2i);
1464#ifdef DEBUG_OUTPUT_DIR
1465 store(cgal_model, face_type_map, DEBUG_OUTPUT_DIR + "constrained/"); // only debug
1466#endif // DEBUG_OUTPUT_DIR
1467
1468 // flood fill the other faces inside the region.
1469 flood_fill_inner(cgal_model, face_type_map);
1470
1471#ifdef DEBUG_OUTPUT_DIR
1472 store(cgal_model, face_type_map, DEBUG_OUTPUT_DIR + "filled/", true); // only debug
1473#endif // DEBUG_OUTPUT_DIR
1474
1475 // IMPROVE: AOIs area could be created during flood fill
1476 return create_cut_area_of_interests(cgal_model, shapes, face_type_map);
1477}
void flood_fill_inner(const CutMesh &mesh, FaceTypeMap &face_type_map)
Change FaceType from not_constrained to inside For neighbor(or neighbor of neighbor of ....
Definition CutSurface.cpp:1479
CutAOIs create_cut_area_of_interests(const CutMesh &mesh, const ExPolygons &shapes, FaceTypeMap &face_type_map)
Create areas from mesh surface.
Definition CutSurface.cpp:1687
const std::string face_type_map_name
Definition CutSurface.cpp:245
const std::string face_shape_map_name
Definition CutSurface.cpp:225
CutMesh::Property_map< EI, IntersectingElement > EdgeShapeMap
Definition CutSurface.cpp:217
const std::string edge_shape_map_name
Definition CutSurface.cpp:224
CutMesh::Property_map< FI, IntersectingElement > FaceShapeMap
Definition CutSurface.cpp:218
void set_face_type(FaceTypeMap &face_type_map, const CutMesh &mesh, const VertexShapeMap &vertex_shape_map, const EdgeBoolMap &ecm, const CutMesh &shape_mesh, const ExPolygonsIndices &shape2index)
Face with constrained edge are inside/outside by type of intersection Other set to not_constrained(st...
Definition CutSurface.cpp:1411
CutMesh::Property_map< FI, FaceType > FaceTypeMap
Definition CutSurface.cpp:244
Track source of intersection Help for anotate inner and outer faces.
Definition CutSurface.cpp:1139

References create_cut_area_of_interests(), edge_shape_map_name, face_shape_map_name, face_type_map_name, flood_fill_inner(), is_constrained_edge_name, not_constrained, set_face_type(), and vert_shape_map_name.

Referenced by Slic3r::cut_surface().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ default_vi()

const VI priv::default_vi ( std::numeric_limits< uint32_t > ::max())

◆ diff_models()

priv::SurfacePatches priv::diff_models ( VCutAOIs & cuts,
CutMeshes & cut_models,
CutMeshes & models,
const Project3d & projection )

Differenciate other models.

Parameters
cutsPatches from meshes
cut_modelsSource points for Cutted AOIs NOTE: Create Reduction map as mesh property - clean on end
modelsOriginal models without cut modifications used for differenciation NOTE: Clip function modify Mesh
projectionDefine projection direction
Returns
Cuts differenciate by models - Patch
3082{
3083 // IMPROVE: when models contain ONE mesh. It is only about convert cuts to patches
3084 // and reduce unneccessary triangles on contour
3085
3086 //Convert model_index and cut_index into one index
3087 priv::ModelCut2index m2i(cuts);
3088
3089 // create bounding boxes for cuts
3090 std::vector<BoundingBoxf3> bbs = create_bbs(cuts, cut_models);
3091 Trees trees(models.size());
3092
3093 SurfacePatches patches;
3094
3095 // queue of patches for one AOI (permanent with respect to for loop)
3096 SurfacePatchesEx aoi_patches;
3097
3098 //SurfacePatches aoi_patches;
3099 patches.reserve(m2i.get_count()); // only approximation of count
3100 size_t index = 0;
3101 for (size_t model_index = 0; model_index < models.size(); ++model_index) {
3102 CutAOIs &model_cuts = cuts[model_index];
3103 CutMesh &cut_model_ = cut_models[model_index];
3104 const CutMesh &cut_model = cut_model_;
3105 ReductionMap vertex_reduction_map = cut_model_.add_property_map<VI, VI>(vertex_reduction_map_name).first;
3106 create_reduce_map(vertex_reduction_map, cut_model);
3107
3108 for (size_t cut_index = 0; cut_index < model_cuts.size(); ++cut_index, ++index) {
3109 const CutAOI &cut = model_cuts[cut_index];
3110 SurfacePatchEx patch_ex;
3111 SurfacePatch &patch = patch_ex.patch;
3112 patch = create_surface_patch(cut.first, cut_model_, &vertex_reduction_map);
3113 patch.bb = bbs[index];
3114 patch.aoi_id = cut_index;
3115 patch.model_id = model_index;
3116 patch.shape_id = get_shape_point_index(cut, cut_model);
3117 patch.is_whole_aoi = true;
3118
3119 aoi_patches.clear();
3120 aoi_patches.push_back(patch_ex);
3121 for (size_t model_index2 = 0; model_index2 < models.size(); ++model_index2) {
3122 // do not clip source model itself
3123 if (model_index == model_index2) continue;
3124 for (SurfacePatchEx &patch_ex : aoi_patches) {
3125 SurfacePatch &patch = patch_ex.patch;
3126 if (has_bb_intersection(patch.bb, model_index2, bbs, m2i) &&
3127 clip_cut(patch, models[model_index2])){
3128 patch_ex.just_cliped = true;
3129 } else {
3130 // build tree on demand
3131 // NOTE: it is possible not neccessary: e.g. one model
3132 Tree &tree = trees[model_index2];
3133 if (tree.empty()) {
3134 const CutMesh &model = models[model_index2];
3135 auto f_range = faces(model);
3136 tree.insert(f_range.first, f_range.second, model);
3137 tree.build();
3138 }
3139 if (is_patch_inside_of_model(patch, tree, projection))
3140 patch_ex.full_inside = true;
3141 }
3142 }
3143 // erase full inside
3144 for (size_t i = aoi_patches.size(); i != 0; --i) {
3145 auto it = aoi_patches.begin() + (i - 1);
3146 if (it->full_inside) aoi_patches.erase(it);
3147 }
3148
3149 // detection of full AOI inside of model
3150 if (aoi_patches.empty()) break;
3151
3152 // divide cliped into parts
3153 size_t end = aoi_patches.size();
3154 for (size_t i = 0; i < end; ++i)
3155 if (aoi_patches[i].just_cliped)
3156 divide_patch(i, aoi_patches);
3157 }
3158
3159 if (!aoi_patches.empty()) {
3160 patches.reserve(patches.size() + aoi_patches.size());
3161 for (SurfacePatchEx &patch : aoi_patches)
3162 patches.push_back(std::move(patch.patch));
3163
3164 }
3165 }
3166 cut_model_.remove_property_map(vertex_reduction_map);
3167 }
3168
3169 // Also use outline inside of patches(made by non manifold models)
3170 // IMPROVE: trace outline from AOIs
3171 collect_open_edges(patches);
3172 return patches;
3173}
Keep conversion from VCutAOIs to Index and vice versa Model_index .. contour(or hole) poin from ExPol...
Definition CutSurface.cpp:357
void create_reduce_map(ReductionMap &reduction_map, const CutMesh &meshes)
Create map to reduce unnecesary triangles, Triangles are made by divided quad to two triangles on sid...
Definition CutSurface.cpp:1594
std::vector< SurfacePatchEx > SurfacePatchesEx
Definition CutSurface.cpp:2793
const std::string vertex_reduction_map_name
Definition CutSurface.cpp:255
size_t aoi_id
Definition CutSurface.cpp:334
bool full_inside
Definition CutSurface.cpp:2789
uint32_t get_shape_point_index(const CutAOI &cut, const CutMesh &model)
Return some shape point index which identify shape NOTE: Used to find expolygon index.
Definition CutSurface.cpp:2956
void collect_open_edges(SurfacePatches &patches)
Fill outline in patches by open edges.
Definition CutSurface.cpp:3053
SurfacePatch patch
Definition CutSurface.cpp:2786
bool just_cliped
Definition CutSurface.cpp:2791
BoundingBoxf3 bb
Definition CutSurface.cpp:328
void divide_patch(size_t i, SurfacePatchesEx &patches)
Separate connected triangles into it's own patches new patches are added to back of input patches.
Definition CutSurface.cpp:2992
bool is_patch_inside_of_model(const SurfacePatch &patch, const Tree &tree, const Project3d &projection)
Only for model without intersection Use ray (in projection direction) from a point from patch and cou...
Definition CutSurface.cpp:2928
BBS create_bbs(const VCutAOIs &cuts, const CutMeshes &cut_models)
Create bounding boxes for AOI.
Definition CutSurface.cpp:2881
bool clip_cut(SurfacePatch &cut, CutMesh clipper)
Implement 'cut' Minus 'clipper', where clipper is reverse input Volume NOTE: clipper will be modified...
Definition CutSurface.cpp:2592
size_t model_id
Definition CutSurface.cpp:332
CvtVI2VI ReductionMap
Definition CutSurface.cpp:254
std::vector< SurfacePatch > SurfacePatches
Definition CutSurface.cpp:341
bool has_bb_intersection(const BoundingBoxf3 &bb, size_t model_index, const BBS &bbs, const ModelCut2index &m2i)
Check whether bounding box has intersection with model.
Definition CutSurface.cpp:2913
size_t shape_id
Definition CutSurface.cpp:336
bool is_whole_aoi
Definition CutSurface.cpp:339
SurfacePatch create_surface_patch(const std::vector< FI > &fis, CutMesh &mesh, const ReductionMap *rmap=nullptr)
Create patch.
Definition CutSurface.cpp:2683
Definition CutSurface.cpp:2785

References priv::SurfacePatch::aoi_id, priv::SurfacePatch::bb, clip_cut(), collect_open_edges(), create_bbs(), create_reduce_map(), create_surface_patch(), divide_patch(), priv::SurfacePatchEx::full_inside, priv::ModelCut2index::get_count(), get_shape_point_index(), has_bb_intersection(), is_patch_inside_of_model(), priv::SurfacePatch::is_whole_aoi, priv::SurfacePatchEx::just_cliped, priv::SurfacePatch::model_id, priv::SurfacePatchEx::patch, priv::SurfacePatch::shape_id, and vertex_reduction_map_name.

Referenced by Slic3r::cut_surface().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ divide_patch()

void priv::divide_patch ( size_t i,
SurfacePatchesEx & patches )

Separate connected triangles into it's own patches new patches are added to back of input patches.

Parameters
iindex into patches
patchesIn/Out Patches
2993{
2994 SurfacePatchEx &patch_ex = patches[i];
2995 assert(patch_ex.just_cliped);
2996 patch_ex.just_cliped = false;
2997
2998 SurfacePatch& patch = patch_ex.patch;
2999 CutMesh& cm = patch.mesh;
3000 assert(!cm.faces().empty());
3001 std::string patch_number_name = "f:patch_number";
3002 CutMesh::Property_map<FI,bool> is_processed = cm.add_property_map<FI, bool>(patch_number_name, false).first;
3003
3004 const CvtVI2VI cvt_from = patch.mesh.property_map<VI, VI>(patch_source_name).value();
3005
3006 std::vector<FI> fis;
3007 fis.reserve(cm.faces().size());
3008
3009 SurfacePatchesEx new_patches;
3010 std::vector<FI> queue;
3011 // IMPROVE: create groups around triangles and than connect groups
3012 for (FI fi_cm : cm.faces()) {
3013 if (is_processed[fi_cm]) continue;
3014 assert(queue.empty());
3015 queue.push_back(fi_cm);
3016 if (!fis.empty()) {
3017 // Be carefull after push to patches,
3018 // all ref on patch contain non valid values
3019 SurfacePatchEx patch_ex_n;
3020 patch_ex_n.patch = separate_patch(fis, patch, cvt_from);
3021 patch_ex_n.patch.is_whole_aoi = false;
3022 new_patches.push_back(std::move(patch_ex_n));
3023 fis.clear();
3024 }
3025 // flood fill from triangle fi_cm to surrounding
3026 do {
3027 FI fi_q = queue.back();
3028 queue.pop_back();
3029 if (is_processed[fi_q]) continue;
3030 is_processed[fi_q] = true;
3031 fis.push_back(fi_q);
3032 HI hi = cm.halfedge(fi_q);
3033 for (FI fi : cm.faces_around_face(hi)) {
3034 // by documentation The face descriptor may be the null face, and it may be several times the same face descriptor.
3035 if (!fi.is_valid()) continue;
3036 if (!is_processed[fi]) queue.push_back(fi);
3037 }
3038 } while (!queue.empty());
3039 }
3040 cm.remove_property_map(is_processed);
3041 assert(!fis.empty());
3042
3043 // speed up for only one patch - no dividing (the most common)
3044 if (new_patches.empty()) {
3045 patch.bb = bounding_box(cm);
3046 patch.is_whole_aoi = false;
3047 } else {
3048 patch = separate_patch(fis, patch, cvt_from);
3049 patches.insert(patches.end(), new_patches.begin(), new_patches.end());
3050 }
3051}
SurfacePatch separate_patch(const std::vector< FI > &fis, SurfacePatch &patch, const CvtVI2VI &cvt_from)
Separate triangles singned with number n.
Definition CutSurface.cpp:2973

References priv::SurfacePatch::bb, bounding_box(), priv::SurfacePatch::is_whole_aoi, priv::SurfacePatchEx::just_cliped, priv::SurfacePatch::mesh, priv::SurfacePatchEx::patch, patch_source_name, and separate_patch().

Referenced by diff_models().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ draw_transparent_icon()

void priv::draw_transparent_icon ( const IconManager::Icon & icon)
static
348{
349 // Check input
350 if (!icon.is_valid()) {
351 assert(false);
352 BOOST_LOG_TRIVIAL(warning) << "Drawing invalid Icon.";
353 ImGui::Text("?");
354 return;
355 }
356
357 // size UV texture coors [in texture ratio]
358 ImVec2 size_uv(icon.br.x - icon.tl.x, icon.br.y - icon.tl.y);
359 ImVec2 one_px(size_uv.x / icon.size.x, size_uv.y / icon.size.y);
360
361 // use top left corner of first icon
362 IconManager::Icon icon_px = icon; // copy
363 // reduce uv coors to one pixel
364 icon_px.tl = ImVec2(0, 0);
365 icon_px.br = one_px;
366 draw(icon_px);
367}
void draw(const IconManager::Icon &icon, const ImVec2 &size, const ImVec4 &tint_col, const ImVec4 &border_col)
Draw imgui image with icon.
Definition IconManager.cpp:373
Data for render texture with icon.
Definition IconManager.hpp:53
ImVec2 br
Definition IconManager.hpp:59
ImVec2 size
Definition IconManager.hpp:55
bool is_valid() const
Definition IconManager.hpp:63
ImVec2 tl
Definition IconManager.hpp:58

References Slic3r::GUI::IconManager::Icon::br, Slic3r::GUI::draw(), Slic3r::GUI::IconManager::Icon::is_valid(), Slic3r::GUI::IconManager::Icon::size, and Slic3r::GUI::IconManager::Icon::tl.

Referenced by Slic3r::GUI::clickable().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ exist_duplicit_vertex()

bool priv::exist_duplicit_vertex ( const CutMesh & mesh)
1004 {
1005 std::vector<Vec3d> points;
1006 points.reserve(mesh.vertices().size());
1007 // copy points
1008 for (VI vi : mesh.vertices()) {
1009 const P3 &p = mesh.point(vi);
1010 points.emplace_back(p.x(), p.y(), p.z());
1011 }
1012 std::sort(points.begin(), points.end(), [](const Vec3d &v1, const Vec3d &v2) {
1013 return v1.x() < v2.x() ||
1014 (v1.x() == v2.x() &&
1015 (v1.y() < v2.y() ||
1016 (v1.y() == v2.y() &&
1017 v1.z() < v2.z())));
1018 });
1019 // find first duplicit
1020 auto it = std::adjacent_find(points.begin(), points.end());
1021 return it != points.end();
1022}

Referenced by to_cgal().

Here is the caller graph for this function:

◆ fill_polygon_distances()

void priv::fill_polygon_distances ( const ProjectionDistance & pd,
uint32_t index,
const ExPolygonsIndex & id,
ProjectionDistances & result,
const ExPolygon & shape,
const VDistances & distances )
2080{
2081 const Points& points = (id.polygon_index == 0) ?
2082 shape.contour.points :
2083 shape.holes[id.polygon_index - 1].points;
2084 // border of indexes for Polygon
2085 uint32_t first_index = index - id.point_index;
2086 uint32_t last_index = first_index + points.size();
2087
2088 uint32_t act_index = index;
2089 const ProjectionDistance* act_pd = &pd;
2090
2091 // Copy starting pd to result
2092 result[act_index] = pd;
2093
2094 auto exist_next = [&distances, &act_index, &act_pd, &result]
2095 (uint32_t nxt_index) {
2096 const ProjectionDistance *nxt_pd = get_closest_projection(distances[nxt_index] ,act_pd->distance);
2097 // exist next projection distance ?
2098 if (nxt_pd == nullptr) return false;
2099
2100 // check no rewrite result
2101 assert(result[nxt_index].aoi_index == std::numeric_limits<uint32_t>::max());
2102 // copy founded projection to result
2103 result[nxt_index] = *nxt_pd; // copy
2104
2105 // next
2106 act_index = nxt_index;
2107 act_pd = &result[nxt_index];
2108 return true;
2109 };
2110
2111 // last index in circle
2112 uint32_t finish_index = (index == first_index) ? (last_index - 1) :
2113 (index - 1);
2114 // Positive iteration inside polygon
2115 do {
2116 uint32_t nxt_index = act_index + 1;
2117 // close loop of indexes inside of contour
2118 if (nxt_index == last_index) nxt_index = first_index;
2119 // check that exist next
2120 if (!exist_next(nxt_index)) break;
2121 } while (act_index != finish_index);
2122
2123 // when all results for polygon are set no neccessary to iterate negative
2124 if (act_index == finish_index) return;
2125
2126 act_index = index;
2127 act_pd = &pd;
2128 // Negative iteration inside polygon
2129 do {
2130 uint32_t nxt_index = (act_index == first_index) ?
2131 (last_index-1) : (act_index - 1);
2132 // When iterate negative it must be split to parts
2133 // and can't iterate in circle
2134 assert(nxt_index != index);
2135 // check that exist next
2136 if (!exist_next(nxt_index)) break;
2137 } while (true);
2138}
Polygon contour
Definition ExPolygon.hpp:42
Points points
Definition MultiPoint.hpp:22
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
const Polygons & holes(const ExPolygon &p)
Definition AGGRaster.hpp:31

References Slic3r::ExPolygon::contour, priv::ProjectionDistance::distance, get_closest_projection(), Slic3r::ExPolygon::holes, and Slic3r::MultiPoint::points.

Referenced by fill_shape_distances().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_shape_distances()

void priv::fill_shape_distances ( uint32_t start_index,
const ProjectionDistance * start_pd,
ProjectionDistances & result,
const ExPolygonsIndices & s2i,
const ExPolygon & shape,
const VDistances & distances )
2147{
2148 uint32_t expolygons_index = s2i.cvt(start_index).expolygons_index;
2149 uint32_t first_shape_index = s2i.cvt({expolygons_index, 0, 0});
2150 do {
2151 fill_polygon_distances(*start_pd, start_index, s2i.cvt(start_index),result, shape, distances);
2152 // seaching only inside shape, return index of closed finished point
2153 auto find_close_finished_point = [&first_shape_index, &shape, &result]
2154 (const Point &p) -> ClosePoint {
2155 uint32_t index = first_shape_index;
2156 ClosePoint cp;
2157 auto check_finished_points = [&cp, &result, &index, &p]
2158 (const Points& pts) {
2159 for (const Point &p_ : pts) {
2160 // finished point with some distances
2161 if (result[index].aoi_index == std::numeric_limits<uint32_t>::max()) {
2162 ++index;
2163 continue;
2164 }
2165 float distance = calc_size_sq(p_ - p);
2166 if (cp.dist_sq > distance) {
2167 cp.dist_sq = distance;
2168 cp.index = index;
2169 }
2170 ++index;
2171 }
2172 };
2173 check_finished_points(shape.contour.points);
2174 for (const Polygon &h : shape.holes)
2175 check_finished_points(h.points);
2176 return cp;
2177 };
2178
2179 // find next closest pair of points
2180 // (finished + unfinished) in ExPolygon
2181 start_index = std::numeric_limits<uint32_t>::max(); // unfinished_index
2182 uint32_t finished_index = std::numeric_limits<uint32_t>::max();
2183 float dist_sq = std::numeric_limits<float>::max();
2184
2185 // first index in shape
2186 uint32_t index = first_shape_index;
2187 auto check_unfinished_points = [&index, &result, &distances, &find_close_finished_point, &dist_sq, &start_index, &finished_index]
2188 (const Points& pts) {
2189 for (const Point &p : pts) {
2190 // try find unfinished
2191 if (result[index].aoi_index !=
2192 std::numeric_limits<uint32_t>::max() ||
2193 distances[index].empty()) {
2194 ++index;
2195 continue;
2196 }
2197 ClosePoint cp = find_close_finished_point(p);
2198 if (dist_sq > cp.dist_sq) {
2199 dist_sq = cp.dist_sq;
2200 start_index = index;
2201 finished_index = cp.index;
2202 }
2203 ++index;
2204 }
2205 };
2206 // for each unfinished points
2207 check_unfinished_points(shape.contour.points);
2208 for (const Polygon &h : shape.holes)
2209 check_unfinished_points(h.points);
2210 } while (start_index != std::numeric_limits<uint32_t>::max());
2211}
float distance(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:19
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:273
void fill_polygon_distances(const ProjectionDistance &pd, uint32_t index, const ExPolygonsIndex &id, ProjectionDistances &result, const ExPolygon &shape, const VDistances &distances)
Definition CutSurface.cpp:2074
float calc_size_sq(const Point &p)
Definition CutSurface.cpp:1859
Definition CutSurface.cpp:1820

References calc_size_sq(), Slic3r::ExPolygonsIndices::cvt(), priv::ClosePoint::dist_sq, Slic3r::empty(), fill_polygon_distances(), priv::ClosePoint::index, and Slic3r::MultiPoint::points.

Referenced by choose_best_distance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_close_point()

priv::ClosePoint priv::find_close_point ( const Point & p,
ProjectionDistances & result,
std::vector< bool > & finished_shapes,
const ExPolygonsIndices & s2i,
const ExPolygons & shapes )
2218{
2219 // result
2220 ClosePoint cp;
2221 // for all finished points
2222 for (uint32_t shape_index = 0; shape_index < shapes.size(); ++shape_index) {
2223 if (!finished_shapes[shape_index]) continue;
2224 const ExPolygon &shape = shapes[shape_index];
2225 uint32_t index = s2i.cvt({shape_index, 0, 0});
2226 auto find_close_point_in_points = [&p, &cp, &index, &result]
2227 (const Points &pts){
2228 for (const Point &p_ : pts) {
2229 // Exist result (is finished) ?
2230 if (result[index].aoi_index ==
2231 std::numeric_limits<uint32_t>::max()) {
2232 ++index;
2233 continue;
2234 }
2235 float distance_sq = calc_size_sq(p - p_);
2236 if (cp.dist_sq > distance_sq) {
2237 cp.dist_sq = distance_sq;
2238 cp.index = index;
2239 }
2240 ++index;
2241 }
2242 };
2243 find_close_point_in_points(shape.contour.points);
2244 // shape could be inside of another shape's hole
2245 for (const Polygon& h:shape.holes)
2246 find_close_point_in_points(h.points);
2247 }
2248 return cp;
2249}
Polygons holes
Definition ExPolygon.hpp:43

References calc_size_sq(), Slic3r::ExPolygon::contour, Slic3r::ExPolygonsIndices::cvt(), Slic3r::ExPolygon::holes, and Slic3r::MultiPoint::points.

Here is the call graph for this function:

◆ find_closest_point_index()

uint32_t priv::find_closest_point_index ( const Point & p,
const ExPolygons & shapes,
const ExPolygonsIndices & s2i,
const std::vector< bool > & mask )
1952{
1953 SearchData sd = create_search_data(shapes, mask);
1954 if (sd.tree.nodes().size() == 0){
1955 // no lines in expolygon, check whether exist point to start
1956 double closest_square_distance = INFINITY;
1957 uint32_t closest_id = -1;
1958 for (uint32_t i = 0; i < mask.size(); i++)
1959 if (mask[i]){
1960 ExPolygonsIndex ei = s2i.cvt(i);
1961 const Point& s_p = ei.is_contour()?
1962 shapes[ei.expolygons_index].contour[ei.point_index]:
1963 shapes[ei.expolygons_index].holes[ei.hole_index()][ei.point_index];
1964 double square_distance = (p - s_p).cast<double>().squaredNorm();
1965 if (closest_id >= mask.size() ||
1966 closest_square_distance > square_distance) {
1967 closest_id = i;
1968 closest_square_distance = square_distance;
1969 }
1970 }
1971 assert(closest_id < mask.size());
1972 return closest_id;
1973 }
1974 size_t line_idx = std::numeric_limits<size_t>::max();
1975 Vec2d hit_point;
1976 Vec2d p_d = p.cast<double>();
1977 [[maybe_unused]] double distance_sq =
1979 sd.lines, sd.tree, p_d, line_idx, hit_point);
1980 assert(distance_sq > 0);
1981
1982 // IMPROVE: one could use line ratio to find closest point
1983 return get_closest_point_index(sd, line_idx, hit_point, shapes, s2i);
1984}
const std::vector< Node > & nodes() const
Definition AABBTreeIndirect.hpp:109
VectorType::Scalar squared_distance_to_indexed_lines(const std::vector< LineType > &lines, const TreeType &tree, const VectorType &point, size_t &hit_idx_out, Eigen::PlainObjectBase< VectorType > &hit_point_out, typename VectorType::Scalar max_sqr_dist=std::numeric_limits< typename VectorType::Scalar >::infinity())
Definition AABBTreeLines.hpp:211
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299
uint32_t get_closest_point_index(const SearchData &sd, size_t line_idx, const Vec2d &hit_point, const ExPolygons &shapes, const ExPolygonsIndices &s2i)
Definition CutSurface.cpp:1900
SearchData create_search_data(const ExPolygons &shapes, const std::vector< bool > &mask)
Definition CutSurface.cpp:1864
Index into ExPolygons Identify expolygon, its contour (or hole) and point.
Definition ExPolygonsIndex.hpp:14
uint32_t expolygons_index
Definition ExPolygonsIndex.hpp:16
uint32_t point_index
Definition ExPolygonsIndex.hpp:24
bool is_contour() const
Definition ExPolygonsIndex.hpp:26
uint32_t hole_index() const
Definition ExPolygonsIndex.hpp:28

References Slic3r::cast(), create_search_data(), Slic3r::ExPolygonsIndices::cvt(), Slic3r::ExPolygonsIndex::expolygons_index, get_closest_point_index(), Slic3r::ExPolygonsIndex::hole_index(), Slic3r::ExPolygonsIndex::is_contour(), priv::SearchData::lines, Slic3r::AABBTreeIndirect::Tree< ANumDimensions, ACoordType >::nodes(), Slic3r::ExPolygonsIndex::point_index, Slic3r::AABBTreeLines::squared_distance_to_indexed_lines(), and priv::SearchData::tree.

Referenced by choose_best_distance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_closest_point_pair()

std::pair< uint32_t, uint32_t > priv::find_closest_point_pair ( const ExPolygons & shapes,
const std::vector< bool > & done_shapes,
const ExPolygonsIndices & s2i,
const std::vector< bool > & mask )
1991{
1992 assert(mask.size() == s2i.get_count());
1993 assert(done_shapes.size() == shapes.size());
1994 std::vector<bool> unfinished_mask = mask; // copy
1995
1996 size_t index = 0;
1997 for (size_t shape_index = 0; shape_index < shapes.size(); shape_index++) {
1998 size_t count = count_points(shapes[shape_index]);
1999 if (done_shapes[shape_index]) {
2000 for (size_t i = 0; i < count; ++i, ++index)
2001 unfinished_mask[index] = false;
2002 } else {
2003 index += count;
2004 }
2005 }
2006 assert(index == s2i.get_count());
2007 SearchData sd = create_search_data(shapes, unfinished_mask);
2008
2009 struct ClosestPair
2010 {
2011 size_t finish_idx = std::numeric_limits<size_t>::max();
2012 size_t unfinished_line_idx = std::numeric_limits<size_t>::max();
2013 Vec2d hit_point = Vec2d();
2014 double distance_sq = std::numeric_limits<double>::max();
2015 } cp;
2016
2017 index = 0;
2018 for (size_t shape_index = 0; shape_index < shapes.size(); shape_index++) {
2019 const ExPolygon shape = shapes[shape_index];
2020 if (!done_shapes[shape_index]) {
2021 index += count_points(shape);
2022 continue;
2023 }
2024
2025 auto search_in_polygon = [&index, &cp, &sd, &mask](const Polygon& polygon) {
2026 for (size_t i = 0; i < polygon.size(); ++i, ++index) {
2027 if (mask[index] == false) continue;
2028 Vec2d p_d = polygon[i].cast<double>();
2029 size_t line_idx = std::numeric_limits<size_t>::max();
2030 Vec2d hit_point;
2032 sd.lines, sd.tree, p_d, line_idx, hit_point, cp.distance_sq);
2033 if (distance_sq < 0 ||
2034 distance_sq >= cp.distance_sq) continue;
2035 assert(line_idx < sd.lines.size());
2036 cp.distance_sq = distance_sq;
2037 cp.unfinished_line_idx = line_idx;
2038 cp.hit_point = hit_point;
2039 cp.finish_idx = index;
2040 }
2041 };
2042 search_in_polygon(shape.contour);
2043 for (const Polygon& hole: shape.holes)
2044 search_in_polygon(hole);
2045 }
2046 assert(index == s2i.get_count());
2047 // check that exists result
2048 if (cp.finish_idx == std::numeric_limits<size_t>::max()) {
2049 return std::make_pair(std::numeric_limits<size_t>::max(),
2050 std::numeric_limits<size_t>::max());
2051 }
2052
2053 size_t unfinished_idx = get_closest_point_index(sd, cp.unfinished_line_idx, cp.hit_point, shapes, s2i);
2054 return std::make_pair(cp.finish_idx, unfinished_idx);
2055}
Slic3r::Polygon Polygon
Definition Emboss.cpp:101

References Slic3r::ExPolygon::contour, count, Slic3r::count_points(), create_search_data(), get_closest_point_index(), Slic3r::ExPolygonsIndices::get_count(), Slic3r::ExPolygon::holes, and Slic3r::AABBTreeLines::squared_distance_to_indexed_lines().

Referenced by choose_best_distance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ flood_fill_inner()

void priv::flood_fill_inner ( const CutMesh & mesh,
FaceTypeMap & face_type_map )

Change FaceType from not_constrained to inside For neighbor(or neighbor of neighbor of ...) of inside triangles. Process only not_constrained triangles.

Parameters
meshCorefined mesh
face_type_mapIn/Out map with faces type
1481{
1482 std::vector<FI> process;
1483 // guess count of connected not constrained triangles
1484 size_t guess_size = 128;
1485 process.reserve(guess_size);
1486
1487 // check if neighbor(one of three in triangle) has type inside
1488 auto has_inside_neighbor = [&mesh, &face_type_map](FI fi) {
1489 HI hi = mesh.halfedge(fi);
1490 HI hi_end = hi;
1491 auto exist_next = [&hi, &hi_end, &mesh]() -> bool {
1492 hi = mesh.next(hi);
1493 return hi != hi_end;
1494 };
1495 // loop over 3 half edges of face
1496 do {
1497 HI hi_opposite = mesh.opposite(hi);
1498 // open edge doesn't have opposit half edge
1499 if (!hi_opposite.is_valid()) continue;
1500 FI fi_opposite = mesh.face(hi_opposite);
1501 if (!fi_opposite.is_valid()) continue;
1502 if (face_type_map[fi_opposite] == FaceType::inside) return true;
1503 } while (exist_next());
1504 return false;
1505 };
1506
1507 for (FI fi : mesh.faces()) {
1508 FaceType type = face_type_map[fi];
1509 if (type != FaceType::not_constrained) continue;
1510 if (!has_inside_neighbor(fi)) continue;
1511 assert(process.empty());
1512 process.push_back(fi);
1513 //store(mesh, face_type_map, DEBUG_OUTPUT_DIR + "progress.off");
1514
1515 while (!process.empty()) {
1516 FI process_fi = process.back();
1517 process.pop_back();
1518 // Do not fill twice
1519 FaceType& process_type = face_type_map[process_fi];
1520 if (process_type == FaceType::inside) continue;
1521 process_type = FaceType::inside;
1522
1523 // check neighbor triangle
1524 HI hi = mesh.halfedge(process_fi);
1525 HI hi_end = hi;
1526 auto exist_next = [&hi, &hi_end, &mesh]() -> bool {
1527 hi = mesh.next(hi);
1528 return hi != hi_end;
1529 };
1530 do {
1531 HI hi_opposite = mesh.opposite(hi);
1532 // open edge doesn't have opposit half edge
1533 if (!hi_opposite.is_valid()) continue;
1534 FI fi_opposite = mesh.face(hi_opposite);
1535 if (!fi_opposite.is_valid()) continue;
1536 FaceType type_opposite = face_type_map[fi_opposite];
1537 if (type_opposite == FaceType::not_constrained)
1538 process.push_back(fi_opposite);
1539 } while (exist_next());
1540 }
1541 }
1542}

References inside, and not_constrained.

Referenced by cut_from_model().

Here is the caller graph for this function:

◆ get_closest_point_index()

uint32_t priv::get_closest_point_index ( const SearchData & sd,
size_t line_idx,
const Vec2d & hit_point,
const ExPolygons & shapes,
const ExPolygonsIndices & s2i )
1905{
1906 const Linef &line = sd.lines[line_idx];
1907 Vec2d dir = line.a - line.b;
1908 Vec2d dir_abs = dir.cwiseAbs();
1909 // use x coordinate
1910 int i = (dir_abs.x() > dir_abs.y())? 0 :1;
1911
1912 bool use_index = abs(line.a[i] - hit_point[i]) >
1913 abs(line.b[i] - hit_point[i]);
1914 size_t point_index = sd.cvt[line_idx];
1915
1916 // Lambda used only for check result
1917 [[maybe_unused]] auto is_same = [&s2i, &shapes]
1918 (const Vec2d &p, size_t i) -> bool {
1919 auto id = s2i.cvt(i);
1920 const ExPolygon &shape = shapes[id.expolygons_index];
1921 const Polygon &poly = (id.polygon_index == 0) ?
1922 shape.contour :
1923 shape.holes[id.polygon_index - 1];
1924 Vec2crd p_ = p.cast<coord_t>();
1925 return p_ == poly[id.point_index];
1926 };
1927
1928 if (use_index) {
1929 assert(is_same(line.b, point_index));
1930 return point_index;
1931 }
1932 auto id = s2i.cvt(point_index);
1933 if (id.point_index != 0) {
1934 assert(is_same(line.a, point_index - 1));
1935 return point_index - 1;
1936 }
1937 const ExPolygon &shape = shapes[id.expolygons_index];
1938 size_t count_polygon_points = (id.polygon_index == 0) ?
1939 shape.contour.size() :
1940 shape.holes[id.polygon_index - 1].size();
1941 size_t prev_point_index = point_index + (count_polygon_points - 1);
1942 assert(is_same(line.a, prev_point_index));
1943 // return previous point index
1944 return prev_point_index;
1945}
Definition Line.hpp:255
Vec2d b
Definition Line.hpp:265
Vec2d a
Definition Line.hpp:264
size_t size() const
Definition MultiPoint.hpp:50
int64_t coord_t
Definition libslic3r.h:48
bool is_same(const Range< ItA > &A, const Range< ItB > &B)
Definition CSGMeshCopy.hpp:59
Eigen::Matrix< coord_t, 2, 1, Eigen::DontAlign > Vec2crd
Definition Point.hpp:52

References Slic3r::Linef::a, Slic3r::Linef::b, Slic3r::ExPolygon::contour, priv::SearchData::cvt, Slic3r::ExPolygonsIndices::cvt(), Slic3r::ExPolygon::holes, priv::SearchData::lines, and Slic3r::MultiPoint::size().

Referenced by find_closest_point_index(), and find_closest_point_pair().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_closest_projection()

const priv::ProjectionDistance * priv::get_closest_projection ( const ProjectionDistances & distance,
float wanted_distance )
2059{
2060 // minimal distance
2061 float min_d = std::numeric_limits<float>::max();
2062 const ProjectionDistance *min_pd = nullptr;
2063 for (const ProjectionDistance &pd : distance) {
2064 float d = std::fabs(pd.distance - wanted_distance);
2065 // There should be limit for maximal distance
2066 if (min_d > d) {
2067 min_d = d;
2068 min_pd = &pd;
2069 }
2070 }
2071 return min_pd;
2072}

Referenced by choose_best_distance(), and fill_polygon_distances().

Here is the caller graph for this function:

◆ get_shape_point_index()

uint32_t priv::get_shape_point_index ( const CutAOI & cut,
const CutMesh & model )

Return some shape point index which identify shape NOTE: Used to find expolygon index.

Parameters
cutUsed to search source shapes poin
model
Returns
shape point index
2957{
2958 // map is created during intersection by corefine visitor
2959 const VertexShapeMap vert_shape_map = model.property_map<VI, const IntersectingElement *>(vert_shape_map_name).value();
2960 // for each half edge of outline
2961 for (HI hi : cut.second) {
2962 VI vi = model.source(hi);
2963 const IntersectingElement *ie = vert_shape_map[vi];
2964 if (ie == nullptr) continue;
2965 assert(ie->shape_point_index != std::numeric_limits<uint32_t>::max());
2966 return ie->shape_point_index;
2967 }
2968 // can't found any intersecting element in cut
2969 assert(false);
2970 return 0;
2971}

References priv::IntersectingElement::shape_point_index, and vert_shape_map_name.

Referenced by diff_models().

Here is the caller graph for this function:

◆ get_states()

const std::vector< std::pair< int, bool > > & priv::get_states ( IconManager::RasterType type)
static
328 {
329 static std::vector<std::pair<int, bool>> color = {std::make_pair(0, false)};
330 static std::vector<std::pair<int, bool>> white = {std::make_pair(1, false)};
331 static std::vector<std::pair<int, bool>> gray = {std::make_pair(2, false)};
332 static std::vector<std::pair<int, bool>> color_wite_gray = {
333 std::make_pair(1, false), // Activable
334 std::make_pair(0, false), // Hovered
335 std::make_pair(2, false) // Disabled
336 };
337
338 switch (type) {
339 case IconManager::RasterType::color: return color;
340 case IconManager::RasterType::white_only_data: return white;
341 case IconManager::RasterType::gray_only_data: return gray;
342 case IconManager::RasterType::color_wite_gray: return color_wite_gray;
343 default: return color;
344 }
345}

References Slic3r::GUI::IconManager::color, Slic3r::GUI::IconManager::color_wite_gray, Slic3r::GUI::IconManager::gray_only_data, and Slic3r::GUI::IconManager::white_only_data.

Referenced by Slic3r::GUI::IconManager::init().

Here is the caller graph for this function:

◆ has_bb_intersection()

bool priv::has_bb_intersection ( const BoundingBoxf3 & bb,
size_t model_index,
const BBS & bbs,
const ModelCut2index & m2i )

Check whether bounding box has intersection with model.

Parameters
bbBounding box to check
model_indexModel to check with
bbsAll bounding boxes from VCutAOIs
m2iHelp index into VCutAOIs
Returns
True when exist bounding boxes intersection
2917{
2918 const auto&offsets = m2i.get_offsets();
2919 // for cut index with model_index2
2920 size_t start = offsets[model_index];
2921 size_t next = model_index + 1;
2922 size_t end = (next < offsets.size()) ? offsets[next] : m2i.get_count();
2923 for (size_t bb_index = start; bb_index < end; bb_index++)
2924 if (bb.intersects(bbs[bb_index])) return true;
2925 return false;
2926}
bool intersects(const BoundingBox3Base< PointType > &other) const
Definition BoundingBox.hpp:170
const std::vector< uint32_t > & get_offsets() const
Definition CutSurface.cpp:367
uint32_t get_count() const
Definition CutSurface.cpp:366

References priv::ModelCut2index::get_count(), priv::ModelCut2index::get_offsets(), and Slic3r::BoundingBox3Base< PointType >::intersects().

Referenced by diff_models().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ has_bidirectional_constrained()

bool priv::has_bidirectional_constrained ( const Triangulation::HalfEdges & constrained)
inline
57{
58 for (const auto &c : constrained) {
59 auto key = std::make_pair(c.second, c.first);
60 auto it = std::lower_bound(constrained.begin(), constrained.end(),
61 key);
62 if (it != constrained.end() && *it == key) return true;
63 }
64 return false;
65}

Referenced by Slic3r::Triangulation::triangulate().

Here is the caller graph for this function:

◆ has_self_intersection()

bool priv::has_self_intersection ( const Points & points,
const Triangulation::HalfEdges & constrained_half_edges )
inline
77{
78 Lines lines;
79 lines.reserve(constrained_half_edges.size());
80 for (const auto &he : constrained_half_edges)
81 lines.emplace_back(points[he.first], points[he.second]);
82 return !get_intersections(lines).empty();
83}
std::vector< Line > Lines
Definition Line.hpp:20
IntersectionsLines get_intersections(const Lines &lines)
Definition IntersectionPoints.cpp:46

References Slic3r::get_intersections().

Referenced by Slic3r::Triangulation::triangulate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ insert_edges() [1/2]

void priv::insert_edges ( Triangulation::HalfEdges & edges,
uint32_t & offset,
const Polygon & polygon )
inline
43 {
44 const Points &pts = polygon.points;
45 uint32_t size = static_cast<uint32_t>(pts.size());
46 uint32_t prev_index = offset + size - 1;
47 for (uint32_t i = 0; i < size; ++i) {
48 uint32_t index = offset + i;
49 edges.push_back({prev_index, index});
50 prev_index = index;
51 }
52 offset += size;
53}

References Slic3r::offset(), and Slic3r::MultiPoint::points.

Here is the call graph for this function:

◆ insert_edges() [2/2]

void priv::insert_edges ( Triangulation::HalfEdges & edges,
uint32_t & offset,
const Polygon & polygon,
const Triangulation::Changes & changes )
inline
28 {
29 const Points &pts = polygon.points;
30 uint32_t size = static_cast<uint32_t>(pts.size());
31 uint32_t last_index = offset + size - 1;
32 uint32_t prev_index = changes[last_index];
33 for (uint32_t i = 0; i < size; ++i) {
34 uint32_t index = changes[offset + i];
35 // when duplicit points are neighbor
36 if (prev_index == index) continue;
37 edges.push_back({prev_index, index});
38 prev_index = index;
39 }
40 offset += size;
41}

References Slic3r::offset(), and Slic3r::MultiPoint::points.

Referenced by Slic3r::Triangulation::triangulate(), Slic3r::Triangulation::triangulate(), Slic3r::Triangulation::triangulate(), and Slic3r::Triangulation::triangulate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_all_on_one_side()

bool priv::is_all_on_one_side ( const Vec3i32 & t,
const IsOnSides & is_on_sides )

Check if triangle t has all vertices out of any plane.

Parameters
tTriangle
is_on_sidesFlag is vertex index out of plane
Returns
True when triangle is out of one of plane
751 {
752 for (size_t side = 0; side < 4; side++) {
753 bool result = true;
754 for (auto vi : t) {
755 if (!is_on_sides[vi][side]) {
756 result = false;
757 break;
758 }
759 }
760 if (result) return true;
761 }
762 return false;
763}

◆ is_face_inside()

bool priv::is_face_inside ( HI hi,
const CutMesh & mesh,
const CutMesh & shape_mesh,
const VertexShapeMap & vertex_shape_map,
const ExPolygonsIndices & shape2index )

Distiquish face type for half edge.

Parameters
hiDefine face
meshMesh to process
shape_meshVertices of mesh made by shapes
vertex_shape_mapKeep information about source of created vertex
shape2index
shape2indexConvert index to shape point from ExPolygons
Returns
Face type defined by hi
1350{
1351 VI vi_from = mesh.source(hi);
1352 VI vi_to = mesh.target(hi);
1353 // This face has a constrained edge.
1354 const IntersectingElement &shape_from = *vertex_shape_map[vi_from];
1355 const IntersectingElement &shape_to = *vertex_shape_map[vi_to];
1356 assert(shape_from.shape_point_index != std::numeric_limits<uint32_t>::max());
1357 assert(shape_from.attr != (unsigned char) IntersectingElement::Type::undefined);
1358 assert(shape_to.shape_point_index != std::numeric_limits<uint32_t>::max());
1359 assert(shape_to.attr != (unsigned char) IntersectingElement::Type::undefined);
1360
1361 // index into contour
1362 uint32_t i_from = shape_from.shape_point_index;
1363 uint32_t i_to = shape_to.shape_point_index;
1364 IntersectingElement::Type type_from = shape_from.get_type();
1365 IntersectingElement::Type type_to = shape_to.get_type();
1366 if (i_from == i_to && type_from == type_to) {
1367 // intersecting element must be face
1368 assert(type_from == IntersectingElement::Type::face_1 ||
1370
1371 // count of vertices is twice as count of point in the contour
1372 uint32_t i = i_from * 2;
1373 // j is next contour point in vertices
1374 uint32_t j = i + 2;
1375 if (shape_from.is_last()) {
1376 ExPolygonsIndex point_id = shape2index.cvt(i_from);
1377 point_id.point_index = 0;
1378 j = shape2index.cvt(point_id)*2;
1379 }
1380
1381 // opposit point(in triangle face) to edge
1382 const P3 &p = mesh.point(mesh.target(mesh.next(hi)));
1383
1384 // abc is source triangle face
1385 CGAL::Sign abcp = type_from == IntersectingElement::Type::face_1 ?
1386 CGAL::orientation(shape_mesh.point(VI(i)),
1387 shape_mesh.point(VI(i + 1)),
1388 shape_mesh.point(VI(j)), p) :
1389 // type_from == IntersectingElement::Type::face_2
1390 CGAL::orientation(shape_mesh.point(VI(j)),
1391 shape_mesh.point(VI(i + 1)),
1392 shape_mesh.point(VI(j + 1)), p);
1393 return abcp == CGAL::POSITIVE;
1394 } else if (i_from < i_to || (i_from == i_to && type_from < type_to)) {
1395 bool is_last = shape_to.is_last() && shape_from.is_first();
1396 // check continuity of indicies
1397 assert(i_from == i_to || is_last || (i_from + 1) == i_to);
1398 return !is_last;
1399 } else {
1400 assert(i_from > i_to || (i_from == i_to && type_from > type_to));
1401 bool is_last = shape_to.is_first() && shape_from.is_last();
1402 // check continuity of indicies
1403 assert(i_from == i_to || is_last || (i_to + 1) == i_from);
1404 return is_last;
1405 }
1406
1407 assert(false);
1408 return false;
1409}
Definition VoronoiUtilsCgal.cpp:27
Definition Orient.cpp:47
bool is_first() const
Definition CutSurface.cpp:212
bool is_last() const
Definition CutSurface.cpp:213
@ face_2
Definition CutSurface.cpp:199
@ face_1
Definition CutSurface.cpp:197

References priv::IntersectingElement::attr, Slic3r::ExPolygonsIndices::cvt(), priv::IntersectingElement::face_1, priv::IntersectingElement::face_2, priv::IntersectingElement::get_type(), priv::IntersectingElement::is_first(), priv::IntersectingElement::is_last(), Slic3r::ExPolygonsIndex::point_index, priv::IntersectingElement::shape_point_index, and priv::IntersectingElement::undefined.

Referenced by set_face_type().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_out_of()

bool priv::is_out_of ( const Vec3d & v,
const PointNormal & point_normal )

Check.

Parameters
side
v
point_normals
Returns
744{
745 const Vec3d& p = point_normal.first;
746 const Vec3d& n = point_normal.second;
747 double signed_distance = (v - p).dot(n);
748 return signed_distance > 1e-5;
749};
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:154

References Slic3r::dot().

Referenced by set_skip_for_out_of_aoi().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_over_whole_expoly() [1/2]

bool priv::is_over_whole_expoly ( const CutAOI & cutAOI,
const ExPolygon & shape,
const CutMesh & mesh )

Checking whether patch is uninterrupted cover of whole expolygon it belongs.

Parameters
cutAOIPart of surface to check
shapeSource shape
meshSource of cut
Returns
True when cover whole expolygon otherwise false
3189{
3190 // NonInterupted contour is without other point and contain all from shape
3191 const VertexShapeMap vert_shape_map = mesh.property_map<VI, const IntersectingElement*>(vert_shape_map_name).value();
3192 for (HI hi : cutAOI.second) {
3193 const IntersectingElement *ie_s = vert_shape_map[mesh.source(hi)];
3194 const IntersectingElement *ie_t = vert_shape_map[mesh.target(hi)];
3195 if (ie_s == nullptr || ie_t == nullptr)
3196 return false;
3197
3198 assert(ie_s->attr != (unsigned char) IntersectingElement::Type::undefined);
3199 assert(ie_t->attr != (unsigned char) IntersectingElement::Type::undefined);
3200
3201 // check if it is neighbor indices
3202 uint32_t i_s = ie_s->shape_point_index;
3203 uint32_t i_t = ie_t->shape_point_index;
3204 assert(i_s != std::numeric_limits<uint32_t>::max());
3205 assert(i_t != std::numeric_limits<uint32_t>::max());
3206 if (i_s == std::numeric_limits<uint32_t>::max() ||
3207 i_t == std::numeric_limits<uint32_t>::max())
3208 return false;
3209
3210 // made by same index
3211 if (i_s == i_t) continue;
3212
3213 // order from source to target
3214 if (i_s > i_t) {
3215 std::swap(i_s, i_t);
3216 std::swap(ie_s, ie_t);
3217 }
3218 // Must be after fix order !!
3219 bool is_last_polygon_segment = ie_s->is_first() && ie_t->is_last();
3220 if (is_last_polygon_segment) {
3221 std::swap(i_s, i_t);
3222 std::swap(ie_s, ie_t);
3223 }
3224
3225 // Is continous indices
3226 if (!is_last_polygon_segment &&
3227 (ie_s->is_last() || (i_s + 1) != i_t))
3228 return false;
3229
3230 IntersectingElement::Type t_s = ie_s->get_type();
3231 IntersectingElement::Type t_t = ie_t->get_type();
3234 return false;
3235
3236 // next segment must start with edge intersection
3238 return false;
3239
3240 // After face1 must be edge2 or face2
3242 return false;
3243 }
3244
3245 // When all open edges are on contour than there is NO holes is shape
3246 auto is_open = [&mesh](HI hi)->bool {
3247 HI opposite = mesh.opposite(hi);
3248 return !mesh.face(opposite).is_valid();
3249 };
3250
3251 std::vector<HI> opens; // copy
3252 opens.reserve(cutAOI.second.size());
3253 for (HI hi : cutAOI.second) // from lower to bigger
3254 if (is_open(hi)) opens.push_back(hi);
3255 std::sort(opens.begin(), opens.end());
3256
3257 for (FI fi: cutAOI.first) {
3258 HI face_hi = mesh.halfedge(fi);
3259 for (HI hi : mesh.halfedges_around_face(face_hi)) {
3260 if (!is_open(hi)) continue;
3261 // open edge
3262 auto lb = std::lower_bound(opens.begin(), opens.end(), hi);
3263 if (lb == opens.end() || *lb != hi)
3264 return false; // not in contour
3265 }
3266 }
3267 return true;
3268}
ColorRGB opposite(const ColorRGB &color)
Definition Color.cpp:281
@ edge_1
Definition CutSurface.cpp:196

References priv::IntersectingElement::attr, priv::IntersectingElement::edge_1, priv::IntersectingElement::face_1, priv::IntersectingElement::get_type(), priv::IntersectingElement::is_first(), priv::IntersectingElement::is_last(), Slic3r::opposite(), priv::IntersectingElement::shape_point_index, priv::IntersectingElement::undefined, and vert_shape_map_name.

Referenced by is_over_whole_expoly(), and select_patches().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_over_whole_expoly() [2/2]

bool priv::is_over_whole_expoly ( const SurfacePatch & patch,
const ExPolygons & shapes,
const VCutAOIs & cutAOIs,
const CutMeshes & meshes )

Checking whether patch is uninterrupted cover of whole expolygon it belongs.

Parameters
patchPart of surface to check
shapeSource shape
Returns
True when cover whole expolygon otherwise false
3179{
3180 if (!patch.is_whole_aoi) return false;
3181 return is_over_whole_expoly(cutAOIs[patch.model_id][patch.aoi_id],
3182 shapes[patch.shape_id],
3183 meshes[patch.model_id]);
3184}
bool is_over_whole_expoly(const CutAOI &cutAOI, const ExPolygon &shape, const CutMesh &mesh)
Checking whether patch is uninterrupted cover of whole expolygon it belongs.
Definition CutSurface.cpp:3186

References priv::SurfacePatch::aoi_id, is_over_whole_expoly(), priv::SurfacePatch::is_whole_aoi, priv::SurfacePatch::model_id, and priv::SurfacePatch::shape_id.

Here is the call graph for this function:

◆ is_patch_inside_of_model()

bool priv::is_patch_inside_of_model ( const SurfacePatch & patch,
const Tree & tree,
const Project3d & projection )

Only for model without intersection Use ray (in projection direction) from a point from patch and count intersections: pair .. outside | odd .. inside.

Parameters
patchPatch to check
treeModel converted to AABB tree
projectionDefine direction of projection
Returns
True when patch point lay inside of model defined by tree, otherwise FALSE
2931{
2932 // TODO: Solve model with hole in projection direction !!!
2933 const P3 &a = patch.mesh.point(VI(0));
2934 Vec3d a_ = to_vec3d(a);
2935 Vec3d b_ = projection.project(a_);
2936 P3 b(b_.x(), b_.y(), b_.z());
2937
2938 Ray ray_query(a, b);
2939 size_t count = tree.number_of_intersected_primitives(ray_query);
2940 bool is_in = (count % 2) == 1;
2941
2942 // try opposit direction result should be same, otherwise open model is used
2943 //Vec3f c_ = a_ - (b_ - a_); // opposit direction
2944 //P3 c(c_.x(), c_.y(), c_.z());
2945 //Ray ray_query2(a, b);
2946 //size_t count2 = tree.number_of_intersected_primitives(ray_query2);
2947 //bool is_in2 = (count2 % 2) == 1;
2948 assert(((tree.number_of_intersected_primitives(
2949 Ray(a, P3(2 * a.x() - b.x(),
2950 2 * a.y() - b.y(),
2951 2 * a.z() - b.z()))) %
2952 2) == 1) == is_in);
2953 return is_in;
2954}
virtual Vec3d project(const Vec3d &point) const =0
Move point with respect to projection direction e.g. Orthogonal projection will move with point by di...
EpicKernel::Ray_3 Ray
Definition CutSurface.cpp:2807

References count, priv::SurfacePatch::mesh, Slic3r::Emboss::IProject3d::project(), and to_vec3d().

Referenced by diff_models().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_unique()

bool priv::is_unique ( const Points & points)
inline
67 {
68 Points pts = points; // copy
69 std::sort(pts.begin(), pts.end());
70 auto it = std::adjacent_find(pts.begin(), pts.end());
71 return it == pts.end();
72}

Referenced by Slic3r::Triangulation::triangulate().

Here is the caller graph for this function:

◆ merge_patches()

SurfaceCut priv::merge_patches ( SurfacePatches & patches,
const std::vector< bool > & mask )

Merge masked patches to one surface cut.

Parameters
patchesAll patches NOTE: Not const because One needs to add property for Convert indices
maskMash for using patch
Returns
Result surface cut
3647{
3648 SurfaceCut result;
3649 for (SurfacePatch &patch : patches) {
3650 size_t index = &patch - &patches.front();
3651 if (!mask[index]) continue;
3652 append(result, patch2cut(patch));
3653 }
3654 return result;
3655}
void append(SurfaceCut &sc, SurfaceCut &&sc_add)
Merge two surface cuts together Added surface cut will be consumed.
Definition CutSurface.cpp:3627
SurfaceCut patch2cut(SurfacePatch &patch)
Convert patch to indexed_triangle_set.
Definition CutSurface.cpp:3573
Represents cutted surface from object Extend index triangle set by outlines.
Definition CutSurface.hpp:20

References append(), and patch2cut().

Here is the call graph for this function:

◆ patch2cut()

SurfaceCut priv::patch2cut ( SurfacePatch & patch)

Convert patch to indexed_triangle_set.

Parameters
patchPart of surface
Returns
Converted patch
3574{
3575 CutMesh &mesh = patch.mesh;
3576
3577 std::string convert_map_name = "v:convert";
3578 CutMesh::Property_map<VI, SurfaceCut::Index> convert_map =
3579 mesh.add_property_map<VI, SurfaceCut::Index>(convert_map_name).first;
3580
3581 size_t indices_size = mesh.faces().size();
3582 size_t vertices_size = mesh.vertices().size();
3583
3584 SurfaceCut sc;
3585 sc.indices.reserve(indices_size);
3586 sc.vertices.reserve(vertices_size);
3587 for (VI vi : mesh.vertices()) {
3588 // vi order is is not sorted
3589 // assert(vi.idx() == sc.vertices.size());
3590 // vi is not continous
3591 // assert(vi.idx() < vertices_size);
3592 convert_map[vi] = sc.vertices.size();
3593 const P3 &p = mesh.point(vi);
3594 sc.vertices.emplace_back(p.x(), p.y(), p.z());
3595 }
3596
3597 for (FI fi : mesh.faces()) {
3598 HI hi = mesh.halfedge(fi);
3599 assert(mesh.next(hi).is_valid());
3600 assert(mesh.next(mesh.next(hi)).is_valid());
3601 // Is fi triangle?
3602 assert(mesh.next(mesh.next(mesh.next(hi))) == hi);
3603
3604 // triangle indicies
3605 Vec3i32 ti;
3606 size_t i = 0;
3607 for (VI vi : { mesh.source(hi),
3608 mesh.target(hi),
3609 mesh.target(mesh.next(hi))})
3610 ti[i++] = convert_map[vi];
3611 sc.indices.push_back(ti);
3612 }
3613
3614 sc.contours.reserve(patch.loops.size());
3615 for (const Loop &loop : patch.loops) {
3616 sc.contours.push_back({});
3617 std::vector<SurfaceCut::Index> &contour = sc.contours.back();
3618 contour.reserve(loop.size());
3619 for (VI vi : loop) contour.push_back(convert_map[vi]);
3620 }
3621
3622 // Not neccessary, clean and free memory
3623 mesh.remove_property_map(convert_map);
3624 return sc;
3625}
Eigen::Matrix< int32_t, 3, 1, Eigen::DontAlign > Vec3i32
Definition Point.hpp:59
const Polygon & contour(const ExPolygon &p)
Definition AGGRaster.hpp:30
Loops loops
Definition CutSurface.cpp:325

References Slic3r::contour(), Slic3r::SurfaceCut::contours, priv::SurfacePatch::loops, and priv::SurfacePatch::mesh.

Referenced by merge_patches().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_patches()

std::vector< bool > priv::select_patches ( const ProjectionDistances & best_distances,
const SurfacePatches & patches,
const ExPolygons & shapes,
const BoundingBox & shapes_bb,
const ExPolygonsIndices & s2i,
const VCutAOIs & cutAOIs,
const CutMeshes & meshes,
const Project & projection )

Create mask for patches.

Parameters
best_distancesFor each point selected closest distance
patchesAll patches
shapesShape to cut
shapes_bbBound of shapes
s2i
cutAOIs
meshes
projection
Returns
Mask of used patch
3278{
3279 // extension to cover numerical mistake made by back projection patch from 3d to 2d
3280 // Calculated as one percent of average size(width and height)
3281 Point s = shapes_bb.size();
3282 const float extend_delta = (s.x() + s.y())/ float(2 * 100);
3283
3284 // vector of patches for shape
3285 std::vector<std::vector<uint32_t>> used_shapes_patches(shapes.size());
3286 std::vector<bool> in_distances(patches.size(), {false});
3287 for (const ProjectionDistance &d : best_distances) {
3288 // exist valid projection for shape point?
3289 if (d.patch_index == std::numeric_limits<uint32_t>::max()) continue;
3290 if (in_distances[d.patch_index]) continue;
3291 in_distances[d.patch_index] = true;
3292
3293 ExPolygonsIndex id = s2i.cvt(&d - &best_distances.front());
3294 used_shapes_patches[id.expolygons_index].push_back(d.patch_index);
3295 }
3296
3297 // vector of patches for shape
3298 std::vector<std::vector<uint32_t>> shapes_patches(shapes.size());
3299 for (const SurfacePatch &patch : patches)
3300 shapes_patches[patch.shape_id].push_back(&patch - &patches.front());
3301
3302#ifdef DEBUG_OUTPUT_DIR
3303 std::string store_dir = DEBUG_OUTPUT_DIR + "select_patches/";
3304 prepare_dir(store_dir);
3305#endif // DEBUG_OUTPUT_DIR
3306
3307 for (size_t shape_index = 0; shape_index < shapes.size(); shape_index++) {
3308 const ExPolygon &shape = shapes[shape_index];
3309 std::vector<uint32_t> &used_shape_patches = used_shapes_patches[shape_index];
3310 if (used_shape_patches.empty()) continue;
3311 // is used all exist patches?
3312 if (used_shapes_patches.size() == shapes_patches[shape_index].size()) continue;
3313 if (used_shape_patches.size() == 1) {
3314 uint32_t patch_index = used_shape_patches.front();
3315 const SurfacePatch &patch = patches[patch_index];
3316 if (is_over_whole_expoly(patch, shapes, cutAOIs, meshes)) continue;
3317 }
3318
3319 // only shapes containing multiple patches
3320 // or not full filled are back projected (hard processed)
3321
3322 // intersection of converted patches to 2d
3323 ExPolygons fill;
3324 fill.reserve(used_shape_patches.size());
3325
3326 // Heuristics to predict which patch to be used need average patch depth
3327 Vec2d used_patches_depth(std::numeric_limits<double>::max(), std::numeric_limits<double>::min());
3328 for (uint32_t patch_index : used_shape_patches) {
3329 ExPolygon patch_area = to_expoly(patches[patch_index], projection, used_patches_depth);
3330 //*/
3331 ExPolygons patch_areas = offset_ex(patch_area, extend_delta);
3332 fill.insert(fill.end(), patch_areas.begin(), patch_areas.end());
3333 /*/
3334 // without save extension
3335 fill.push_back(patch_area);
3336 //*/
3337 }
3338 fill = union_ex(fill);
3339
3340 // not cutted area of expolygon
3341 ExPolygons rest = diff_ex(ExPolygons{shape}, fill, ApplySafetyOffset::Yes);
3342#ifdef DEBUG_OUTPUT_DIR
3343 BoundingBox shape_bb = get_extents(shape);
3344 SVG svg(store_dir + "shape_" + std::to_string(shape_index) + ".svg", shape_bb);
3345 svg.draw(fill, "darkgreen");
3346 svg.draw(rest, "green");
3347#endif // DEBUG_OUTPUT_DIR
3348
3349 // already filled by multiple patches
3350 if (rest.empty()) continue;
3351
3352 // find patches overlaped rest area
3353 struct PatchShape{
3354 uint32_t patch_index;
3355 ExPolygon shape;
3357 double depth_range_center_distance; // always positive
3358 };
3359 using PatchShapes = std::vector<PatchShape>;
3360 PatchShapes patch_shapes;
3361
3362 double used_patches_depth_center = (used_patches_depth[0] + used_patches_depth[1]) / 2;
3363
3364 // sort used_patches for faster search
3365 std::sort(used_shape_patches.begin(), used_shape_patches.end());
3366 for (uint32_t patch_index : shapes_patches[shape_index]) {
3367 // check is patch already used
3368 auto it = std::lower_bound(used_shape_patches.begin(), used_shape_patches.end(), patch_index);
3369 if (it != used_shape_patches.end() && *it == patch_index) continue;
3370
3371 // Heuristics to predict which patch to be used need average patch depth
3372 Vec2d patche_depth_range(std::numeric_limits<double>::max(), std::numeric_limits<double>::min());
3373 ExPolygon patch_shape = to_expoly(patches[patch_index], projection, patche_depth_range);
3374 double depth_center = (patche_depth_range[0] + patche_depth_range[1]) / 2;
3375 double depth_range_center_distance = std::fabs(used_patches_depth_center - depth_center);
3376
3377 ExPolygons patch_intersection = intersection_ex(ExPolygons{patch_shape}, rest);
3378 if (patch_intersection.empty()) continue;
3379
3380 patch_shapes.push_back({patch_index, patch_shape, patch_intersection, depth_range_center_distance});
3381 }
3382
3383 // nothing to add
3384 if (patch_shapes.empty()) continue;
3385 // only one solution to add
3386 if (patch_shapes.size() == 1) {
3387 used_shape_patches.push_back(patch_shapes.front().patch_index);
3388 continue;
3389 }
3390
3391 // Idea: Get depth range of used patches and add patches in order by distance to used depth center
3392 std::sort(patch_shapes.begin(), patch_shapes.end(), [](const PatchShape &a, const PatchShape &b)
3393 { return a.depth_range_center_distance < b.depth_range_center_distance; });
3394
3395#ifdef DEBUG_OUTPUT_DIR
3396 for (size_t i = patch_shapes.size(); i > 0; --i) {
3397 const PatchShape &p = patch_shapes[i - 1];
3398 int gray_level = (i * 200) / patch_shapes.size();
3399 std::stringstream color;
3400 color << "#" << std::hex << std::setfill('0') << std::setw(2) << gray_level << gray_level << gray_level;
3401 svg.draw(p.shape, color.str());
3402 Point text_pos = get_extents(p.shape).center().cast<int>();
3403 svg.draw_text(text_pos, std::to_string(i-1).c_str(), "orange", std::ceil(shape_bb.size().x() / 20 * 0.000001));
3404 //svg.draw(p.intersection, color.str());
3405 }
3406#endif // DEBUG_OUTPUT_DIR
3407
3408 for (const PatchShape &patch : patch_shapes) {
3409 // Check when exist some place to fill
3410 ExPolygons patch_intersection = intersection_ex(patch.intersection, rest);
3411 if (patch_intersection.empty()) continue;
3412
3413 // Extend for sure
3414 ExPolygons intersection = offset_ex(patch.intersection, extend_delta);
3415 rest = diff_ex(rest, intersection, ApplySafetyOffset::Yes);
3416
3417 used_shape_patches.push_back(patch.patch_index);
3418 if (rest.empty()) break;
3419 }
3420
3421 // QUESTION: How to select which patch to use? How to sort them?
3422 // Now is used back projection distance from used patches
3423 //
3424 // Idealy by outline depth: (need ray cast into patches)
3425 // how to calc wanted depth - idealy by depth of outline help to overlap
3426 // how to calc patch depth - depth in place of outline position
3427 // Which outline to use between
3428
3429 }
3430
3431 std::vector<bool> result(patches.size(), {false});
3432 for (const std::vector<uint32_t> &patches: used_shapes_patches)
3433 for (uint32_t patch_index : patches) {
3434 assert(patch_index < result.size());
3435 // check only onece insertation of patch
3436 assert(!result[patch_index]);
3437 result[patch_index] = true;
3438 }
3439 return result;
3440}
PointType size() const
Definition BoundingBox.cpp:178
PointType center() const
Definition BoundingBox.cpp:228
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:831
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20
BoundingBox get_extents(const ExPolygonsWithIds &e)
Definition Emboss.cpp:1374
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:769
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:605
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:878
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, PolyFillType fill_type)
Definition ClipperUtils.cpp:1011
ExPolygon to_expoly(const SurfacePatch &patch, const Project &projection, Vec2d &depth_range)
Unproject points from loops and create expolygons.
Definition CutSurface.cpp:3550

References Slic3r::BoundingBoxBase< PointType, APointsType >::center(), Slic3r::ExPolygonsIndices::cvt(), Slic3r::diff_ex(), Slic3r::SVG::draw(), Slic3r::SVG::draw_text(), Slic3r::get_extents(), Slic3r::intersection(), Slic3r::intersection_ex(), is_over_whole_expoly(), Slic3r::offset_ex(), Slic3r::BoundingBoxBase< PointType, APointsType >::size(), to_expoly(), Slic3r::union_ex(), and Slic3r::Yes.

Referenced by Slic3r::cut_surface().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ separate_patch()

priv::SurfacePatch priv::separate_patch ( const std::vector< FI > & fis,
SurfacePatch & patch,
const CvtVI2VI & cvt_from )

Separate triangles singned with number n.

Parameters
fisFace indices owned by separate patch
patchOriginal patch NOTE: Can't be const. For indexing vetices need temporary add property map
cvt_fromconversion map
Returns
Just separated patch
2976{
2977 assert(patch.mesh.is_valid());
2978 SurfacePatch patch_new = create_surface_patch(fis, patch.mesh);
2979 patch_new.bb = bounding_box(patch_new.mesh);
2980 patch_new.aoi_id = patch.aoi_id;
2981 patch_new.model_id = patch.model_id;
2982 patch_new.shape_id = patch.shape_id;
2983 // fix cvt
2984 CvtVI2VI cvt = patch_new.mesh.property_map<VI, VI>(patch_source_name).value();
2985 for (VI &vi : cvt) {
2986 if (!vi.is_valid()) continue;
2987 vi = cvt_from[vi];
2988 }
2989 return patch_new;
2990}

References priv::SurfacePatch::aoi_id, priv::SurfacePatch::bb, bounding_box(), create_surface_patch(), priv::SurfacePatch::mesh, priv::SurfacePatch::model_id, patch_source_name, and priv::SurfacePatch::shape_id.

Referenced by divide_patch().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_face_type()

void priv::set_face_type ( FaceTypeMap & face_type_map,
const CutMesh & mesh,
const VertexShapeMap & vertex_shape_map,
const EdgeBoolMap & ecm,
const CutMesh & shape_mesh,
const ExPolygonsIndices & shape2index )

Face with constrained edge are inside/outside by type of intersection Other set to not_constrained(still it could be inside/outside).

Parameters
face_type_map[Output] property map with type of faces
meshMesh to process
vertex_shape_mapKeep information about source of created vertex
ecmDynamic Edge Constrained Map of bool
shape_meshVertices of mesh made by shapes
shape2indexConvert index to shape point from ExPolygons
1417{
1418 for (EI ei : mesh.edges()) {
1419 if (!ecm[ei]) continue;
1420 HI hi = mesh.halfedge(ei);
1421 FI fi = mesh.face(hi);
1422 bool is_inside = is_face_inside(hi, mesh, shape_mesh, vertex_shape_map, shape2index);
1423 face_type_map[fi] = is_inside ? FaceType::inside : FaceType::outside;
1424 HI hi_op = mesh.opposite(hi);
1425 assert(hi_op.is_valid());
1426 if (!hi_op.is_valid()) continue;
1427 FI fi_op = mesh.face(hi_op);
1428 assert(fi_op.is_valid());
1429 if (!fi_op.is_valid()) continue;
1430 face_type_map[fi_op] = (!is_inside) ? FaceType::inside : FaceType::outside;
1431 }
1432}
bool is_face_inside(HI hi, const CutMesh &mesh, const CutMesh &shape_mesh, const VertexShapeMap &vertex_shape_map, const ExPolygonsIndices &shape2index)
Distiquish face type for half edge.
Definition CutSurface.cpp:1345

References inside, is_face_inside(), and outside.

Referenced by cut_from_model().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_skip_by_angle()

void priv::set_skip_by_angle ( std::vector< bool > & skip_indicies,
const indexed_triangle_set & its,
const Project3d & projection,
double max_angle = 89. )

Set true for indicies outward and almost parallel together. Note: internally calculate normals.

Parameters
skip_indiciesFlag to convert triangle to cgal
itsmodel
projectionDirection to measure angle
max_angleMaximal allowed angle between opposit normal and projection direction [in DEG]
910{
911 assert(max_angle < 90. && max_angle > 89.);
912 assert(skip_indicies.size() == its.indices.size());
913 float threshold = static_cast<float>(cos(max_angle / 180. * M_PI));
914 for (const stl_triangle_vertex_indices& face : its.indices) {
915 size_t index = &face - &its.indices.front();
916 if (skip_indicies[index]) continue;
917 Vec3f n = its_face_normal(its, face);
918 const Vec3f& v = its.vertices[face[0]];
919 const Vec3d vd = v.cast<double>();
920 // Improve: For Orthogonal Projection it is same for each vertex
921 Vec3d projectedd = projection.project(vd);
922 Vec3f projected = projectedd.cast<float>();
923 Vec3f project_dir = projected - v;
924 project_dir.normalize();
925 float cos_alpha = project_dir.dot(n);
926 if (cos_alpha > threshold) continue;
927 skip_indicies[index] = true;
928 }
929}
#define M_PI
Definition ExtrusionSimulator.cpp:31
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
Vec3f its_face_normal(const indexed_triangle_set &its, const stl_triangle_vertex_indices face)
Definition TriangleMesh.hpp:351

References Slic3r::its_face_normal(), M_PI, and Slic3r::Emboss::IProject3d::project().

Referenced by Slic3r::cut_surface().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_skip_for_out_of_aoi()

void priv::set_skip_for_out_of_aoi ( std::vector< bool > & skip_indicies,
const indexed_triangle_set & its,
const Project & projection,
const BoundingBox & shapes_bb )

Set true for indices out of area of interest.

Parameters
skip_indiciesFlag to convert triangle to cgal
itsmodel
projectionConvert 2d point to pair of 3d points
shapes_bb2d bounding box define AOI
769{
770 assert(skip_indicies.size() == its.indices.size());
771 // 1`*----* 2`
772 // / 2 /|
773 // 1 *----* |
774 // | | * 3`
775 // | |/
776 // 0 *----* 3
778 std::array<std::pair<Vec3d, Vec3d>, 4> bb;
779 int index = 0;
780 for (Point v :
781 {shapes_bb.min, Point{shapes_bb.min.x(), shapes_bb.max.y()},
782 shapes_bb.max, Point{shapes_bb.max.x(), shapes_bb.min.y()}})
783 bb[index++] = projection.create_front_back(v);
784
785 // define planes to test
786 // 0 .. under
787 // 1 .. left
788 // 2 .. above
789 // 3 .. right
790 size_t prev_i = 3;
791 // plane is defined by point and normal
792 PointNormals point_normals;
793 for (size_t i = 0; i < 4; i++) {
794 const Vec3d &p1 = bb[i].first;
795 const Vec3d &p2 = bb[i].second;
796 const Vec3d &p3 = bb[prev_i].first;
797 prev_i = i;
798
799 Vec3d v1 = p2 - p1;
800 v1.normalize();
801 Vec3d v2 = p3 - p1;
802 v2.normalize();
803
804 Vec3d normal = v2.cross(v1);
805 normal.normalize();
806
807 point_normals[i] = {p1, normal};
808 }
809
810 // check that projection is not left handed
811 // Fix for reflected projection
812 if (is_out_of(point_normals[2].first, point_normals[0])) {
813 // projection is reflected so normals are reflected
814 for (auto &pn : point_normals)
815 pn.second *= -1;
816 }
817
818 // same meaning as point normal
819 IsOnSides is_on_sides(its.vertices.size(), {false,false,false,false});
820
821 // inspect all vertices when it is out of bounding box
822 tbb::parallel_for(tbb::blocked_range<size_t>(0, its.vertices.size()),
823 [&its, &point_normals, &is_on_sides](const tbb::blocked_range<size_t> &range) {
824 for (size_t i = range.begin(); i < range.end(); ++i) {
825 Vec3d v = its.vertices[i].cast<double>();
826 // under + above
827 for (int side : {0, 2}) {
828 if (is_out_of(v, point_normals[side])) {
829 is_on_sides[i][side] = true;
830 // when it is under it can't be above
831 break;
832 }
833 }
834 // left + right
835 for (int side : {1, 3}) {
836 if (is_out_of(v, point_normals[side])) {
837 is_on_sides[i][side] = true;
838 // when it is on left side it can't be on right
839 break;
840 }
841 }
842 }
843 }); // END parallel for
844
845 // inspect all triangles, when it is out of bounding box
846 tbb::parallel_for(tbb::blocked_range<size_t>(0, its.indices.size()),
847 [&its, &is_on_sides, &skip_indicies](const tbb::blocked_range<size_t> &range) {
848 for (size_t i = range.begin(); i < range.end(); ++i) {
849 if (is_all_on_one_side(its.indices[i], is_on_sides))
850 skip_indicies[i] = true;
851 }
852 }); // END parallel for
853}
PointType max
Definition BoundingBox.hpp:21
PointType min
Definition BoundingBox.hpp:20
virtual std::pair< Vec3d, Vec3d > create_front_back(const Point &p) const =0
convert 2d point to 3d points
auto range(Cont &&cont)
Definition libslic3r.h:405
Point normal(Point pt, double scale)
Definition TreeSupport.cpp:112
bool is_out_of(const Vec3d &v, const PointNormal &point_normal)
Check.
Definition CutSurface.cpp:743
std::vector< std::array< bool, 4 > > IsOnSides
Definition CutSurface.cpp:732
std::array< PointNormal, 4 > PointNormals
Definition CutSurface.cpp:721

References Slic3r::Emboss::IProjection::create_front_back(), is_out_of(), Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::normal(), and Slic3r::range().

Referenced by Slic3r::cut_surface(), and Slic3r::its_cut_AoI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_cgal() [1/2]

priv::CutMesh priv::to_cgal ( const ExPolygons & shapes,
const Project & projection )

Covert 2d shape (e.g. Glyph) to CGAL model NOTE: internaly create edge_shape_map .. Property map to store conversion from edge to contour face_shape_map .. Property map to store conversion from face to contour.

Parameters
shapes2d shapes to project
projectionDefine transformation 2d point into 3d
Returns
CGAL model of extruded shape
1026{
1027 if (shapes.empty()) return {};
1028
1029 CutMesh result;
1030 EdgeShapeMap edge_shape_map = result.add_property_map<EI, IntersectingElement>(edge_shape_map_name).first;
1031 FaceShapeMap face_shape_map = result.add_property_map<FI, IntersectingElement>(face_shape_map_name).first;
1032
1033 std::vector<VI> indices;
1034 auto insert_contour = [&projection, &indices, &result,
1035 &edge_shape_map, &face_shape_map]
1036 (const Polygon &polygon) {
1037 indices.clear();
1038 indices.reserve(polygon.points.size() * 2);
1039 size_t num_vertices_old = result.number_of_vertices();
1040 for (const Point &polygon_point : polygon.points) {
1041 auto [front, back] = projection.create_front_back(polygon_point);
1042 P3 v_front{front.x(), front.y(), front.z()};
1043 VI vi1 = result.add_vertex(v_front);
1044 assert(vi1.idx() == (indices.size() + num_vertices_old));
1045 indices.push_back(vi1);
1046
1047 P3 v_back{back.x(), back.y(), back.z()};
1048 VI vi2 = result.add_vertex(v_back);
1049 assert(vi2.idx() == (indices.size() + num_vertices_old));
1050 indices.push_back(vi2);
1051 }
1052
1053 auto find_edge = [&result](FI fi, VI from, VI to) {
1054 HI hi = result.halfedge(fi);
1055 for (; result.target(hi) != to; hi = result.next(hi));
1056 assert(result.source(hi) == from);
1057 assert(result.target(hi) == to);
1058 return result.edge(hi);
1059 };
1060
1061 uint32_t contour_index = static_cast<uint32_t>(num_vertices_old / 2);
1062 for (int32_t i = 0; i < int32_t(indices.size()); i += 2) {
1063 bool is_first = i == 0;
1064 bool is_last = size_t(i + 2) >= indices.size();
1065 int32_t j = is_last ? 0 : (i + 2);
1066
1067 FI fi1 = result.add_face(indices[i], indices[j], indices[i + 1]);
1068 EI ei1 = find_edge(fi1, indices[i + 1], indices[i]);
1069 EI ei2 = find_edge(fi1, indices[j], indices[i + 1]);
1070 FI fi2 = result.add_face(indices[j], indices[j + 1], indices[i + 1]);
1071 IntersectingElement element {contour_index, (unsigned char)IntersectingElement::Type::undefined};
1072 if (is_first) element.set_is_first();
1073 if (is_last) element.set_is_last();
1074 edge_shape_map[ei1] = element.set_type(IntersectingElement::Type::edge_1);
1075 face_shape_map[fi1] = element.set_type(IntersectingElement::Type::face_1);
1076 edge_shape_map[ei2] = element.set_type(IntersectingElement::Type::edge_2);
1077 face_shape_map[fi2] = element.set_type(IntersectingElement::Type::face_2);
1078 ++contour_index;
1079 }
1080 };
1081
1082 size_t count_point = count_points(shapes);
1083 result.reserve(result.number_of_vertices() + 2 * count_point,
1084 result.number_of_edges() + 4 * count_point,
1085 result.number_of_faces() + 2 * count_point);
1086
1087 // Identify polygon
1088 for (const ExPolygon &shape : shapes) {
1089 insert_contour(shape.contour);
1090 for (const Polygon &hole : shape.holes)
1091 insert_contour(hole);
1092 }
1093 assert(!exist_duplicit_vertex(result));
1094 return result;
1095}
bool exist_duplicit_vertex(const CutMesh &mesh)
Definition CutSurface.cpp:1004
void set_is_first()
Definition CutSurface.cpp:209

References Slic3r::count_points(), Slic3r::Emboss::IProjection::create_front_back(), priv::IntersectingElement::edge_1, priv::IntersectingElement::edge_2, edge_shape_map_name, exist_duplicit_vertex(), priv::IntersectingElement::face_1, priv::IntersectingElement::face_2, face_shape_map_name, priv::IntersectingElement::set_is_first(), priv::IntersectingElement::set_is_last(), priv::IntersectingElement::set_type(), and priv::IntersectingElement::undefined.

Here is the call graph for this function:

◆ to_cgal() [2/2]

priv::CutMesh priv::to_cgal ( const indexed_triangle_set & its,
const std::vector< bool > & skip_indicies,
bool flip = false )

Convert triangle mesh model to CGAL Surface_mesh Filtrate out opposite triangles Add property map for source face index.

Parameters
itsModel
skip_indiciesFlags that triangle should be skiped
flipWhen true triangle will flip normal
Returns
CGAL mesh - half edge mesh
934{
935 const std::vector<stl_vertex> &vertices = its.vertices;
936 const std::vector<stl_triangle_vertex_indices> &indices = its.indices;
937
938 std::vector<bool> use_vetices(vertices.size(), {false});
939
940 size_t vertices_count = 0;
941 size_t faces_count = 0;
942 size_t edges_count = 0;
943
944 for (const auto &t : indices) {
945 size_t index = &t - &indices.front();
946 if (skip_indicies[index]) continue;
947 ++faces_count;
948 size_t count_used_vertices = 0;
949 for (const auto vi : t) {
950 if (!use_vetices[vi]) {
951 ++vertices_count;
952 use_vetices[vi] = true;
953 } else {
954 ++count_used_vertices;
955 }
956 }
957 switch (count_used_vertices) {
958 case 3: break; // all edges are already counted
959 case 2: edges_count += 2; break;
960 case 1:
961 case 0: edges_count += 3; break;
962 default: assert(false);
963 }
964 }
965 assert(vertices_count <= vertices.size());
966 assert(edges_count <= (indices.size() * 3));
967 assert(faces_count <= indices.size());
968
969 CutMesh result;
970 result.reserve(vertices_count, edges_count, faces_count);
971
972 std::vector<VI> to_filtrated_vertices_index(vertices.size());
973 size_t filtrated_vertices_index = 0;
974 for (size_t i = 0; i < vertices.size(); ++i)
975 if (use_vetices[i]) {
976 to_filtrated_vertices_index[i] = VI(filtrated_vertices_index);
977 ++filtrated_vertices_index;
978 }
979
980 for (const stl_vertex& v : vertices) {
981 if (!use_vetices[&v - &vertices.front()]) continue;
982 result.add_vertex(CutMesh::Point{v.x(), v.y(), v.z()});
983 }
984
985 if (!flip) {
986 for (const stl_triangle_vertex_indices &f : indices) {
987 if (skip_indicies[&f - &indices.front()]) continue;
988 result.add_face(to_filtrated_vertices_index[f[0]],
989 to_filtrated_vertices_index[f[1]],
990 to_filtrated_vertices_index[f[2]]);
991 }
992 } else {
993 for (const stl_triangle_vertex_indices &f : indices) {
994 if (skip_indicies[&f - &indices.front()]) continue;
995 result.add_face(to_filtrated_vertices_index[f[2]],
996 to_filtrated_vertices_index[f[1]],
997 to_filtrated_vertices_index[f[0]]);
998 }
999 }
1000
1001 return result;
1002}
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:124

References Slic3r::f().

Referenced by Slic3r::cut_surface().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_expoly()

ExPolygon priv::to_expoly ( const SurfacePatch & patch,
const Project & projection,
Vec2d & depth_range )

Unproject points from loops and create expolygons.

Parameters
patchPatch to convert on expolygon
projectionConvert 3d point to 2d
depth_rangeRange of unprojected points x .. min, y .. max value
Returns
Expolygon represent patch in 2d
3551{
3552 Polygons polys = unproject_loops(patch, projection, depth_range);
3553 // should not be used when no opposit triangle are counted so should not create overlaps
3554 PolyFillType fill_type = pftEvenOdd;
3555 ExPolygons expolys = Slic3r::union_ex(polys, fill_type);
3556 if (expolys.size() == 1)
3557 return expolys.front();
3558
3559 // It should be one expolygon
3560 assert(false);
3561
3562 if (expolys.empty()) return {};
3563 // find biggest
3564 const ExPolygon *biggest = &expolys.front();
3565 for (size_t index = 1; index < expolys.size(); ++index) {
3566 const ExPolygon *current = &expolys[index];
3567 if (biggest->contour.size() < current->contour.size())
3568 biggest = current;
3569 }
3570 return *biggest;
3571}
PolyFillType
Definition ClipperUtils.hpp:23
@ pftEvenOdd
Definition ClipperUtils.hpp:23
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
Polygons unproject_loops(const SurfacePatch &patch, const Project &projection, Vec2d &depth_range)
Unptoject points from outline loops of patch.
Definition CutSurface.cpp:3505

References Slic3r::ExPolygon::contour, Slic3r::pftEvenOdd, Slic3r::MultiPoint::size(), Slic3r::union_ex(), and unproject_loops().

Referenced by select_patches().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_vec3d()

Vec3d priv::to_vec3d ( const P3 & p)
inline
115{ return Vec3d(p.x(),p.y(),p.z()); }

Referenced by bounding_box(), bounding_box(), create_reduce_map(), is_patch_inside_of_model(), and unproject_loops().

Here is the caller graph for this function:

◆ unproject_loops()

Polygons priv::unproject_loops ( const SurfacePatch & patch,
const Project & projection,
Vec2d & depth_range )

Unptoject points from outline loops of patch.

Parameters
patchContain loops and vertices
projectionKnow how to project from 3d to 2d
depth_rangeRange of unprojected points x .. min, y .. max value
Returns
Unprojected points in loops
3506{
3507 assert(!patch.loops.empty());
3508 if (patch.loops.empty()) return {};
3509
3510 // NOTE: this method is working only when patch did not contain outward faces
3511 Polygons polys;
3512 polys.reserve(patch.loops.size());
3513 // project conture into 2d space to fillconvert outlines to
3514
3515 size_t count = 0;
3516 for (const Loop &l : patch.loops) count += l.size();
3517 std::vector<float> depths;
3518 depths.reserve(count);
3519
3520 Points pts;
3521 for (const Loop &l : patch.loops) {
3522 pts.clear();
3523 pts.reserve(l.size());
3524 for (VI vi : l) {
3525 const P3 &p3 = patch.mesh.point(vi);
3526 Vec3d p = to_vec3d(p3);
3527 double depth;
3528 std::optional<Vec2d> p2_opt = projection.unproject(p, &depth);
3529 if (depth_range[0] > depth) depth_range[0] = depth; // min
3530 if (depth_range[1] < depth) depth_range[1] = depth; // max
3531 // Check when appear that skip is enough for poit which can't be unprojected
3532 // - it could break contour
3533 assert(p2_opt.has_value());
3534 if (!p2_opt.has_value()) continue;
3535
3536 pts.push_back(p2_opt->cast<Point::coord_type>());
3537 depths.push_back(static_cast<float>(depth));
3538 }
3539 // minimal is triangle
3540 assert(pts.size() >= 3);
3541 if (pts.size() < 3) continue;
3542
3543 polys.emplace_back(pts);
3544 }
3545
3546 assert(!polys.empty());
3547 return polys;
3548}
virtual std::optional< Vec2d > unproject(const Vec3d &p, double *depth=nullptr) const =0
Back projection.
coord_t coord_type
Definition Point.hpp:201

References count, priv::SurfacePatch::loops, priv::SurfacePatch::mesh, to_vec3d(), and Slic3r::Emboss::IProjection::unproject().

Referenced by to_expoly().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ edge_shape_map_name

const std::string priv::edge_shape_map_name = "e:IntersectingElement"

Referenced by cut_from_model(), and to_cgal().

◆ face_shape_map_name

const std::string priv::face_shape_map_name = "f:IntersectingElement"

Referenced by cut_from_model(), and to_cgal().

◆ face_type_map_name

const std::string priv::face_type_map_name = "f:side"

Referenced by cut_from_model().

◆ is_constrained_edge_name

const std::string priv::is_constrained_edge_name = "e:is_constrained"

◆ patch_source_name

const std::string priv::patch_source_name = "v:patch_source"

◆ vert_shape_map_name

const std::string priv::vert_shape_map_name = "v:IntersectingElement"

◆ vertex_reduction_map_name

const std::string priv::vertex_reduction_map_name = "v:reduction"

Referenced by diff_models().

◆ vertex_source_map_name

const std::string priv::vertex_source_map_name = "v:SourceIntersecting"