Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
priv Namespace Reference

Classes

struct  ClosePoint
 
struct  IntersectingElement
 IntersectingElement. More...
 
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...
 
class  JobException
 
struct  Limit
 
struct  Limits
 
struct  MinMax
 
class  ModelCut2index
 Keep conversion from VCutAOIs to Index and vice versa Model_index .. contour(or hole) poin from ExPolygons Index .. continous number. More...
 
struct  ModelCutId
 
struct  ProjectionDistance
 To select surface near projection distance. More...
 
struct  SearchData
 
struct  Source
 
struct  SpikeDesc
 
struct  SurfacePatch
 
struct  SurfacePatchEx
 
struct  Visitor
 Track source of intersection Help for anotate inner and outer faces. More...
 

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< EpicKernel, Primitive >
 
using Ray = EpicKernel::Ray_3
 
using Tree = CGAL::AABB_tree< Traits >
 
using Trees = std::vector< Tree >
 
using PatchNumber = CutMesh::Property_map< FI, size_t >
 
using Polygon = Slic3r::Polygon
 

Enumerations

enum class  FaceType { inside , outside , not_constrained , inside_processed }
 Flag for faces in CGAL mesh. More...
 
enum class  IconType : unsigned {
  rename = 0 , erase , add , save ,
  undo , italic , unitalic , bold ,
  unbold , system_selector , open_file , exclamation ,
  lock , lock_bold , unlock , unlock_bold ,
  _count
}
 
enum class  IconState : unsigned { activable = 0 , hovered , disabled }
 

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 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 Vec3i &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_tfind_closest_point_pair (const ExPolygons &shapes, const std::vector< bool > &done_shapes, const ExPolygonsIndices &s2i, const std::vector< bool > &mask)
 
const ProjectionDistanceget_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.
 
bool is_valid (const FontFile &font, unsigned int index)
 
fontinfo_opt load_font_info (const unsigned char *data, unsigned int index=0)
 
std::optional< Glyphget_glyph (const stbtt_fontinfo &font_info, int unicode_letter, float flatness)
 
const Glyphget_glyph (int unicode, const FontFile &font, const FontProp &font_prop, Glyphs &cache, fontinfo_opt &font_info_opt)
 
EmbossStyle create_style (std::wstring name, std::wstring path)
 
Point to_point (const stbtt__point &point)
 
void remove_bad (Polygons &polygons)
 
void remove_bad (ExPolygons &expolygons)
 
bool remove_same_neighbor (Polygon &points)
 
bool remove_same_neighbor (Polygons &polygons)
 
bool remove_same_neighbor (ExPolygons &expolygons)
 
bool remove_self_intersections (ExPolygons &shape, unsigned max_iteration=10)
 
ExPolygon create_bounding_rect (const ExPolygons &shape)
 
void remove_small_islands (ExPolygons &shape, double minimal_area)
 
Points collect_close_points (const ExPolygons &expolygons, double distance=.6)
 
bool heal_dupl_inter (ExPolygons &shape, unsigned max_iteration)
 
void visualize_heal (const std::string &svg_filepath, const ExPolygons &expolygons)
 
const Points pts_2x2 ({Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)})
 
const Points pts_3x3 ({Point(-1, -1), Point(1, -1), Point(1, 1), Point(-1, 1)})
 
bool remove_when_spike (Polygon &polygon, size_t index, const SpikeDesc &spike_desc)
 
void remove_spikes_in_duplicates (ExPolygons &expolygons, const Points &duplicates)
 
void add_quad (uint32_t i1, uint32_t i2, indexed_triangle_set &result, uint32_t count_point)
 
indexed_triangle_set polygons2model_unique (const ExPolygons &shape2d, const IProjection &projection, const Points &points)
 
indexed_triangle_set polygons2model_duplicit (const ExPolygons &shape2d, const IProjection &projection, const Points &points, const Points &duplicits)
 
Slic3r::Pointfs compute_intersections (const Slic3r::Lines &lines)
 
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)
 
template<typename T >
void to_range_pi_pi (T &angle)
 
static DataBase create_emboss_data_base (const std::string &text, StyleManager &style_manager, std::shared_ptr< std::atomic< bool > > &cancel)
 Prepare data for emboss.
 
static void start_create_volume_job (const ModelObject *object, const Transform3d volume_trmat, DataBase &emboss_data, ModelVolumeType volume_type)
 Start job for add new volume to object with given transformation.
 
static bool start_create_volume_on_surface_job (DataBase &emboss_data, ModelVolumeType volume_type, const Vec2d &screen_coor, const GLVolume *gl_volume, RaycastManager &raycaster, GLCanvas3D &canvas)
 Start job for add new volume on surface of object defined by screen coor.
 
static void find_closest_volume (const Selection &selection, const Vec2d &screen_center, const Camera &camera, const ModelObjectPtrs &objects, Vec2d *closest_center, const GLVolume **closest_volume)
 Find volume in selected object with closest convex hull to screen center. Return.
 
static void start_create_object_job (DataBase &emboss_data, const Vec2d &coor)
 Start job for add object with text into scene.
 
const IconManager::Iconget_icon (const IconManager::VIcons &icons, IconType type, IconState state)
 
static bool draw_button (const IconManager::VIcons &icons, IconType type, bool disable=false)
 
static bool apply_camera_dir (const Camera &camera, GLCanvas3D &canvas)
 Apply camera direction for emboss direction.
 
static ImVec2 calc_fine_position (const Selection &selection, const ImVec2 &windows_size, const Size &canvas_size)
 Move window for edit emboss text near to embossed object NOTE: embossed object must be selected.
 
static void change_window_position (std::optional< ImVec2 > &output_window_offset, bool try_to_fix)
 Change position of emboss window.
 
static bool is_text_empty (const std::string &text)
 
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)
 
bool check (const DataBase &input, bool check_fontfile=true, bool use_surface=false)
 Assert check of inputs data.
 
bool check (const DataCreateVolume &input, bool is_main_thread=false)
 
bool check (const DataCreateObject &input)
 
bool check (const DataUpdate &input, bool is_main_thread=false, bool use_surface=false)
 
bool check (const CreateSurfaceVolumeData &input, bool is_main_thread=false)
 
bool check (const UpdateSurfaceVolumeData &input, bool is_main_thread=false)
 
template<typename Fnc >
static ExPolygons create_shape (DataBase &input, Fnc was_canceled)
 
template<typename Fnc >
static TriangleMesh try_create_mesh (DataBase &input, Fnc was_canceled)
 Try to create mesh from text.
 
template<typename Fnc >
static TriangleMesh create_mesh (DataBase &input, Fnc was_canceled, Job::Ctl &ctl)
 
static TriangleMesh create_default_mesh ()
 Create default mesh for embossed text.
 
static void update_volume (TriangleMesh &&mesh, const DataUpdate &data, Transform3d *tr=nullptr)
 Must be called on main thread.
 
static void create_volume (TriangleMesh &&mesh, const ObjectID &object_id, const ModelVolumeType type, const Transform3d trmat, const DataBase &data)
 Add new volume to object.
 
static ModelVolumeget_volume (ModelObjectPtrs &objects, const ObjectID &volume_id)
 Select Volume from objects.
 
static OrthoProject create_projection_for_cut (Transform3d tr, double shape_scale, const std::pair< float, float > &z_range)
 Create projection for cut surface from mesh.
 
static OrthoProject3d create_emboss_projection (bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut)
 Create tranformation for emboss Cutted surface.
 
static TriangleMesh cut_surface (DataBase &input1, const SurfaceVolumeData &input2, std::function< bool()> was_canceled)
 Cut surface into triangle mesh.
 
static void create_message (const std::string &message)
 
static bool process (std::exception_ptr &eptr)
 
static bool finalize (bool canceled, std::exception_ptr &eptr, const DataBase &input)
 

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"
 
static const struct priv::Limits limits
 
constexpr double up_limit = 0.9
 
constexpr float safe_extension = 1.0f
 

Class Documentation

◆ 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::Limit

struct priv::Limit
template<typename T>
struct priv::Limit< T >
+ Inheritance diagram for priv::Limit< T >:
Class Members
MinMax< T > gui
MinMax< T > values

◆ priv::MinMax

struct priv::MinMax
template<typename T>
struct priv::MinMax< T >
+ Inheritance diagram for priv::MinMax< T >:
+ Collaboration diagram for priv::MinMax< T >:
Class Members
T max
T min

◆ 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::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::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::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 = typedef std::vector<BoundingBoxf3>

◆ CutAOI

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

◆ CutAOIs

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

◆ CutMesh

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

◆ CutMeshes

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

◆ CvtVI2VI

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

◆ EdgeBoolMap

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

◆ EdgeShapeMap

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

◆ EI

using priv::EI = typedef CGAL::SM_Edge_index

◆ EpicKernel

using priv::EpicKernel = typedef CGAL::Exact_predicates_inexact_constructions_kernel

◆ FaceShapeMap

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

◆ FaceTypeMap

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

◆ FI

using priv::FI = typedef CGAL::SM_Face_index

◆ HI

using priv::HI = typedef CGAL::SM_Halfedge_index

◆ IsOnSides

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

◆ Loop

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

◆ Loops

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

◆ P3

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

◆ PatchNumber

using priv::PatchNumber = typedef CutMesh::Property_map<FI, size_t>

◆ PointNormal

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

◆ PointNormals

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

◆ Polygon

using priv::Polygon = typedef Slic3r::Polygon

◆ Primitive

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

◆ Project

◆ Project3d

◆ ProjectionDistances

using priv::ProjectionDistances = typedef std::vector<ProjectionDistance>

◆ Ray

using priv::Ray = typedef EpicKernel::Ray_3

◆ ReductionMap

using priv::ReductionMap = typedef CvtVI2VI

◆ Sources

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

◆ SurfacePatches

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

◆ SurfacePatchesEx

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

◆ Traits

using priv::Traits = typedef CGAL::AABB_traits<EpicKernel, Primitive>

◆ Tree

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

◆ Trees

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

◆ VCutAOIs

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

◆ VDistances

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

◆ VertexShapeMap

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

◆ VertexSourceMap

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

◆ VI

using priv::VI = typedef 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 
199 {
200 // face inside of the cutted shape
201 inside,
202 // face outside of the cutted shape
203 outside,
204 // face without constrained edge (In or Out)
206
207 // Helper flag that inside was processed
209};

◆ IconState

enum class priv::IconState : unsigned
strong
Enumerator
activable 
hovered 
disabled 
228: unsigned { activable = 0, hovered /*1*/, disabled /*2*/ };

◆ IconType

enum class priv::IconType : unsigned
strong
Enumerator
rename 
erase 
add 
save 
undo 
italic 
unitalic 
bold 
unbold 
system_selector 
open_file 
exclamation 
lock 
lock_bold 
unlock 
unlock_bold 
_count 

Function Documentation

◆ add_quad()

void priv::add_quad ( uint32_t  i1,
uint32_t  i2,
indexed_triangle_set result,
uint32_t  count_point 
)
1377{
1378 // bottom indices
1379 uint32_t i1_ = i1 + count_point;
1380 uint32_t i2_ = i2 + count_point;
1381 result.indices.emplace_back(i2, i2_, i1);
1382 result.indices.emplace_back(i1_, i1, i2_);
1383};
std::vector< stl_triangle_vertex_indices > indices
Definition stl.h:164
unsigned __int32 uint32_t
Definition unistd.h:79

References indexed_triangle_set::indices.

Referenced by polygons2model_duplicit(), and polygons2model_unique().

+ Here is the caller graph for this function:

◆ 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
3551{
3552 if (sc.empty()) {
3553 sc = std::move(sc_add);
3554 return;
3555 }
3556
3557 if (!sc_add.contours.empty()) {
3559 sc.vertices.size());
3560 size_t require = sc.contours.size() + sc_add.contours.size();
3561 if (sc.contours.capacity() < require) sc.contours.reserve(require);
3562 for (std::vector<SurfaceCut::Index> &cut : sc_add.contours)
3563 for (SurfaceCut::Index &i : cut) i += offset;
3564 Slic3r::append(sc.contours, std::move(sc_add.contours));
3565 }
3566 its_merge(sc, std::move(sc_add));
3567}
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:416
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:110
void its_merge(indexed_triangle_set &its, indexed_triangle_set &&its_add)
Merge one triangle mesh to another Added triangle set will be consumed.
Definition TriangleMesh.cpp:1355
Represents cutted surface from object Extend index triangle set by outlines.
Definition CutSurface.hpp:16
unsigned int Index
Definition CutSurface.hpp:18
Contours contours
Definition CutSurface.hpp:22
std::vector< stl_vertex > vertices
Definition stl.h:165
bool empty() const
Definition stl.h:167

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

Referenced by merge_patches().

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

◆ apply_camera_dir()

bool priv::apply_camera_dir ( const Camera camera,
GLCanvas3D canvas 
)
static

Apply camera direction for emboss direction.

Parameters
cameraDefine view vector
canvasContaine Selected Model to modify
Returns
True when apply change otherwise false
3639 {
3640 const Vec3d &cam_dir = camera.get_dir_forward();
3641
3642 Selection &sel = canvas.get_selection();
3643 if (sel.is_empty()) return false;
3644
3645 // camera direction transformed into volume coordinate system
3646 Transform3d to_world = world_matrix_fixed(sel);
3647 Vec3d cam_dir_tr = to_world.inverse().linear() * cam_dir;
3648 cam_dir_tr.normalize();
3649
3650 Vec3d emboss_dir(0., 0., -1.);
3651
3652 // check wether cam_dir is already used
3653 if (is_approx(cam_dir_tr, emboss_dir)) return false;
3654
3655 assert(sel.get_volume_idxs().size() == 1);
3656 GLVolume *gl_volume = sel.get_volume(*sel.get_volume_idxs().begin());
3657
3658 Transform3d vol_rot;
3659 Transform3d vol_tr = gl_volume->get_volume_transformation().get_matrix();
3660 // check whether cam_dir is opposit to emboss dir
3661 if (is_approx(cam_dir_tr, -emboss_dir)) {
3662 // rotate 180 DEG by y
3663 vol_rot = Eigen::AngleAxis(M_PI_2, Vec3d(0., 1., 0.));
3664 } else {
3665 // calc params for rotation
3666 Vec3d axe = emboss_dir.cross(cam_dir_tr);
3667 axe.normalize();
3668 double angle = std::acos(emboss_dir.dot(cam_dir_tr));
3669 vol_rot = Eigen::AngleAxis(angle, axe);
3670 }
3671
3672 Vec3d offset = vol_tr * Vec3d::Zero();
3673 Vec3d offset_inv = vol_rot.inverse() * offset;
3674 Transform3d res = vol_tr *
3676 vol_rot *
3678 //Transform3d res = vol_tr * vol_rot;
3680 get_model_volume(*gl_volume, sel.get_model()->objects)->set_transformation(res);
3681 return true;
3682}
Definition 3DScene.hpp:50
void set_volume_transformation(const Geometry::Transformation &transformation)
Definition 3DScene.hpp:242
const Geometry::Transformation & get_volume_transformation() const
Definition 3DScene.hpp:241
const Selection & get_selection() const
Definition GLCanvas3D.hpp:761
Definition Selection.hpp:31
const IndicesList & get_volume_idxs() const
Definition Selection.hpp:290
Model * get_model() const
Definition Selection.hpp:206
bool is_empty() const
Definition Selection.hpp:240
const GLVolume * get_volume(unsigned int volume_idx) const
Definition Selection.cpp:663
Definition Geometry.hpp:380
const Transform3d & get_matrix() const
Definition Geometry.hpp:437
ModelObjectPtrs objects
Definition Model.hpp:1254
void set_transformation(const Geometry::Transformation &transformation)
Definition Model.hpp:891
EIGEN_DEVICE_FUNC Transform inverse(TransformTraits traits=(TransformTraits) Mode) const
Definition Transform.h:1202
EIGEN_DEVICE_FUNC ConstLinearPart linear() const
Definition Transform.h:400
Represents a 3D rotation as a rotation angle around an arbitrary 3D axis.
Definition AngleAxis.h:50
Represents a translation transformation.
Definition Translation.h:31
const ModelVolume * get_model_volume(const GLVolume &v, const Model &model)
Definition GLCanvas3D.cpp:7869
Transform3d world_matrix_fixed(const GLVolume &gl_volume, const ModelObjectPtrs &objects)
Get transformation to world.
Definition SurfaceDrag.cpp:296
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:52
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:112
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:271
Vec3d get_dir_forward() const
Definition Camera.hpp:84

References Slic3r::angle(), Slic3r::GUI::Camera::get_dir_forward(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::GUI::Selection::get_model(), Slic3r::GUI::get_model_volume(), Slic3r::GUI::GLCanvas3D::get_selection(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), Slic3r::GLVolume::get_volume_transformation(), Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::inverse(), Slic3r::is_approx(), Slic3r::GUI::Selection::is_empty(), Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::linear(), Slic3r::Model::objects, Slic3r::offset(), Slic3r::ModelVolume::set_transformation(), Slic3r::GLVolume::set_volume_transformation(), and Slic3r::GUI::world_matrix_fixed().

Referenced by Slic3r::GUI::GLGizmoEmboss::draw_advanced().

+ 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 
)
2573 {
2574 const P3& p_from_cut = mesh.point(mesh.target(mesh.halfedge(cut.first.front())));
2575 Vec3d min = to_vec3d(p_from_cut);
2576 Vec3d max = min;
2577 for (FI fi : cut.first) {
2578 for(VI vi: mesh.vertices_around_face(mesh.halfedge(fi))){
2579 const P3& p = mesh.point(vi);
2580 for (size_t i = 0; i < 3; ++i) {
2581 if (min[i] > p[i]) min[i] = p[i];
2582 if (max[i] < p[i]) max[i] = p[i];
2583 }
2584 }
2585 }
2586 return BoundingBoxf3(min, max);
2587}
Definition BoundingBox.hpp:221
Vec3d to_vec3d(const openvdb::Vec3s &v)
Definition OpenVDBUtils.cpp:51
CGAL::SM_Face_index FI
Definition CutSurface.cpp:78
CGAL::Epick::Point_3 P3
Definition CutSurface.cpp:79
CGAL::SM_Vertex_index VI
Definition CutSurface.cpp:75

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)
2590{
2591 Vec3d min = to_vec3d(*mesh.points().begin());
2592 Vec3d max = min;
2593 for (VI vi : mesh.vertices()) {
2594 const P3 &p = mesh.point(vi);
2595 for (size_t i = 0; i < 3; ++i) {
2596 if (min[i] > p[i]) min[i] = p[i];
2597 if (max[i] < p[i]) max[i] = p[i];
2598 }
2599 }
2600 return BoundingBoxf3(min, max);
2601}

References to_vec3d().

+ Here is the call graph for this function:

◆ bounding_box() [3/3]

BoundingBoxf3 priv::bounding_box ( const SurfacePatch ecut)
2603 {
2604 return bounding_box(ecut.mesh);
2605}
BoundingBoxf3 bounding_box(const TriangleMesh &m)
Definition TriangleMesh.hpp:340
CutMesh mesh
Definition CutSurface.cpp:285

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
1707{
1708 // It is known because shapes_mesh is created inside of private space
1709 VI vi_start(2 * pi);
1710 VI vi_end(2 * pi + 1);
1711
1712 // Get range for intersection
1713 const P3 &start = shapes_mesh.point(vi_start);
1714 const P3 &end = shapes_mesh.point(vi_end);
1715
1716 // find index in vector with biggest difference
1717 size_t max_i = 0;
1718 float max_val = 0.f;
1719 for (size_t i = 0; i < 3; i++) {
1720 float val = start[i] - end[i];
1721 // abs value
1722 if (val < 0.f) val *= -1.f;
1723 if (max_val < val) {
1724 max_val = val;
1725 max_i = i;
1726 }
1727 }
1728
1729 float from_start = p[max_i] - start[max_i];
1730 float best_distance = projection_ratio * (end[max_i] - start[max_i]);
1731 return from_start - best_distance;
1732}
S::iterator end(S &sh, const PathTag &)
Definition geometry_traits.hpp:620

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
1739{
1740 priv::VDistances result(count_shapes_points);
1741 for (const SurfacePatch &patch : patches) {
1742 // map is created during intersection by corefine visitor
1743 const VertexShapeMap &vert_shape_map =
1744 models[patch.model_id].property_map<VI, const IntersectingElement *>(vert_shape_map_name).first;
1745 uint32_t patch_index = &patch - &patches.front();
1746 // map is created during patch creation / dividing
1747 const CvtVI2VI& cvt = patch.mesh.property_map<VI, VI>(patch_source_name).first;
1748 // for each point on outline
1749 for (const Loop &loop : patch.loops)
1750 for (const VI &vi_patch : loop) {
1751 VI vi_model = cvt[vi_patch];
1752 if (!vi_model.is_valid()) continue;
1753 const IntersectingElement *ie = vert_shape_map[vi_model];
1754 if (ie == nullptr) continue;
1755 assert(ie->shape_point_index != std::numeric_limits<uint32_t>::max());
1756 assert(ie->attr != (unsigned char) IntersectingElement::Type::undefined);
1757 uint32_t pi = ie->shape_point_index;
1758 assert(pi <= count_shapes_points);
1759 std::vector<ProjectionDistance> &pds = result[pi];
1760 uint32_t model_index = patch.model_id;
1761 uint32_t aoi_index = patch.aoi_id;
1762 //uint32_t hi_index = &hi - &patch.outline.front();
1763 const P3 &p = patch.mesh.point(vi_patch);
1764 float distance = calc_distance(p, pi, shapes_mesh, projection_ratio);
1765 pds.push_back({model_index, aoi_index, patch_index, distance});
1766 }
1767 }
1768 return result;
1769}
#define const
Definition getopt.c:38
std::vector< ProjectionDistances > VDistances
Definition CutSurface.cpp:412
const std::string vert_shape_map_name
Definition CutSurface.cpp:194
CutMesh::Property_map< VI, VI > CvtVI2VI
Definition CutSurface.cpp:214
std::vector< VI > Loop
Definition CutSurface.cpp:267
const std::string patch_source_name
Definition CutSurface.cpp:216
CutMesh::Property_map< VI, const IntersectingElement * > VertexShapeMap
Definition CutSurface.cpp:187
Definition CutSurface.cpp:281
IntersectingElement.
Definition CutSurface.cpp:146
uint32_t shape_point_index
Definition CutSurface.cpp:148
unsigned char attr
Definition CutSurface.cpp:151

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_fine_position()

ImVec2 priv::calc_fine_position ( const Selection selection,
const ImVec2 windows_size,
const Size canvas_size 
)
static

Move window for edit emboss text near to embossed object NOTE: embossed object must be selected.

3584{
3585 const Selection::IndicesList indices = selection.get_volume_idxs();
3586 // no selected volume
3587 if (indices.empty())
3588 return {};
3589 const GLVolume *volume = selection.get_volume(*indices.begin());
3590 // bad volume selected (e.g. deleted one)
3591 if (volume == nullptr)
3592 return {};
3593
3594 const Camera &camera = wxGetApp().plater()->get_camera();
3595 Slic3r::Polygon hull = CameraUtils::create_hull2d(camera, *volume);
3596
3597 ImVec2 c_size(canvas_size.get_width(), canvas_size.get_height());
3598 ImVec2 offset = ImGuiWrapper::suggest_location(windows_size, hull, c_size);
3599 return offset;
3600}
static Polygon create_hull2d(const Camera &camera, const GLVolume &volume)
Create hull around GLVolume in 2d space of camera.
Definition CameraUtils.cpp:47
static ImVec2 suggest_location(const ImVec2 &dialog_size, const Slic3r::Polygon &interest, const ImVec2 &canvas_size)
Suggest loacation of dialog window, dependent on actual visible thing on platter like Gizmo menu size...
Definition ImGuiWrapper.cpp:1445
std::set< unsigned int > IndicesList
Definition Selection.hpp:33
int get_height() const
Definition GLCanvas3D.hpp:75
int get_width() const
Definition GLCanvas3D.hpp:72
Definition Polygon.hpp:24
Definition imgui.h:245
Definition Camera.hpp:12

References Slic3r::GUI::CameraUtils::create_hull2d(), Slic3r::GUI::Size::get_height(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), Slic3r::GUI::Size::get_width(), Slic3r::offset(), and Slic3r::GUI::ImGuiWrapper::suggest_location().

Referenced by Slic3r::GUI::GLGizmoEmboss::draw_window(), and Slic3r::GUI::GLGizmoEmboss::on_set_state().

+ 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)
1821 {
1822 // NOTE: p.squaredNorm() can't be use due to overflow max int value
1823 return (float) p.x() * p.x() + (float) p.y() * p.y();
1824}

Referenced by fill_shape_distances(), and find_close_point().

+ Here is the caller graph for this function:

◆ change_window_position()

void priv::change_window_position ( std::optional< ImVec2 > &  output_window_offset,
bool  try_to_fix 
)
static

Change position of emboss window.

Parameters
output_window_offset
try_to_fixWhen True Only move to be full visible otherwise reset position
3604 {
3605 const char* name = "Emboss";
3606 ImGuiWindow *window = ImGui::FindWindowByName(name);
3607 // is window just created
3608 if (window == NULL)
3609 return;
3610
3611 // position of window on screen
3612 ImVec2 position = window->Pos;
3613 ImVec2 size = window->SizeFull;
3614
3615 // screen size
3617
3618 if (position.x < 0) {
3619 if (position.y < 0)
3620 output_window_offset = ImVec2(0, 0);
3621 else
3622 output_window_offset = ImVec2(0, position.y);
3623 } else if (position.y < 0) {
3624 output_window_offset = ImVec2(position.x, 0);
3625 } else if (screen.x < (position.x + size.x)) {
3626 if (screen.y < (position.y + size.y))
3627 output_window_offset = ImVec2(screen.x - size.x, screen.y - size.y);
3628 else
3629 output_window_offset = ImVec2(screen.x - size.x, position.y);
3630 } else if (screen.y < (position.y + size.y)) {
3631 output_window_offset = ImVec2(position.x, screen.y - size.y);
3632 }
3633
3634 if (!try_to_fix && output_window_offset.has_value())
3635 output_window_offset = ImVec2(-1, -1); // Cannot
3636}
IMGUI_API ImGuiViewport * GetMainViewport()
Definition imgui.cpp:10630
IMGUI_API ImGuiWindow * FindWindowByName(const char *name)
Definition imgui.cpp:5110
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:183
ImVec2 Size
Definition imgui.h:2764
Definition imgui_internal.h:1807
ImVec2 Pos
Definition imgui_internal.h:1811
ImVec2 SizeFull
Definition imgui_internal.h:1813
float y
Definition imgui.h:246
float x
Definition imgui.h:246

References ImGui::FindWindowByName(), ImGui::GetMainViewport(), ImGuiWindow::Pos, ImGuiViewport::Size, ImGuiWindow::SizeFull, ImVec2::x, and ImVec2::y.

Referenced by Slic3r::GUI::GLGizmoEmboss::on_set_state(), and Slic3r::GUI::GLGizmoEmboss::set_minimal_window_size().

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

◆ check() [1/6]

bool priv::check ( const CreateSurfaceVolumeData input,
bool  is_main_thread = false 
)
399{
400 bool use_surface = true;
401 bool res = check((DataBase)input, is_main_thread, use_surface);
402 assert(!input.sources.empty());
403 res &= !input.sources.empty();
404 return res;
405}
static int input(void)
bool check(const DataBase &input, bool check_fontfile=true, bool use_surface=false)
Assert check of inputs data.
Definition EmbossJob.cpp:348
Base data holder for embossing.
Definition EmbossJob.hpp:23

References check(), and input().

+ Here is the call graph for this function:

◆ check() [2/6]

bool priv::check ( const DataBase input,
bool  check_fontfile = true,
bool  use_surface = false 
)

Assert check of inputs data.

private namespace implementation

Parameters
input
Returns
349{
350 bool res = true;
351 if (check_fontfile) {
352 assert(input.font_file.has_value());
353 res &= input.font_file.has_value();
354 }
355 assert(!input.text_configuration.fix_3mf_tr.has_value());
356 res &= !input.text_configuration.fix_3mf_tr.has_value();
357 assert(!input.text_configuration.text.empty());
358 res &= !input.text_configuration.text.empty();
359 assert(!input.volume_name.empty());
360 res &= !input.volume_name.empty();
361 assert(input.text_configuration.style.prop.use_surface == use_surface);
362 res &= input.text_configuration.style.prop.use_surface == use_surface;
363 return res;
364}

References input().

Referenced by Slic3r::GUI::Emboss::CreateObjectJob::CreateObjectJob(), Slic3r::GUI::Emboss::CreateSurfaceVolumeJob::CreateSurfaceVolumeJob(), Slic3r::GUI::Emboss::CreateVolumeJob::CreateVolumeJob(), Slic3r::GUI::Emboss::UpdateJob::UpdateJob(), Slic3r::GUI::Emboss::UpdateSurfaceVolumeJob::UpdateSurfaceVolumeJob(), check(), check(), check(), check(), check(), Slic3r::GUI::Emboss::CreateVolumeJob::process(), Slic3r::GUI::Emboss::CreateObjectJob::process(), Slic3r::GUI::Emboss::UpdateJob::process(), Slic3r::GUI::Emboss::CreateSurfaceVolumeJob::process(), Slic3r::GUI::Emboss::UpdateSurfaceVolumeJob::process(), and remove_spikes_in_duplicates().

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

◆ check() [3/6]

bool priv::check ( const DataCreateObject input)
374 {
375 bool check_fontfile = false;
376 bool res = check((DataBase) input, check_fontfile);
377 assert(input.screen_coor.x() >= 0.);
378 res &= input.screen_coor.x() >= 0.;
379 assert(input.screen_coor.y() >= 0.);
380 res &= input.screen_coor.y() >= 0.;
381 assert(input.bed_shape.size() >= 3); // at least triangle
382 res &= input.bed_shape.size() >= 3;
383 return res;
384}

References check(), and input().

+ Here is the call graph for this function:

◆ check() [4/6]

bool priv::check ( const DataCreateVolume input,
bool  is_main_thread = false 
)
365 {
366 bool check_fontfile = false;
367 bool res = check((DataBase) input, check_fontfile);
368 assert(input.volume_type != ModelVolumeType::INVALID);
369 res &= input.volume_type != ModelVolumeType::INVALID;
370 assert(input.object_id.id >= 0);
371 res &= input.object_id.id >= 0;
372 return res;
373}

References check(), input(), and Slic3r::INVALID.

+ Here is the call graph for this function:

◆ check() [5/6]

bool priv::check ( const DataUpdate input,
bool  is_main_thread = false,
bool  use_surface = false 
)
385 {
386 bool check_fontfile = true;
387 bool res = check((DataBase) input, check_fontfile, use_surface);
388 assert(input.volume_id.id >= 0);
389 res &= input.volume_id.id >= 0;
390 if (is_main_thread)
391 assert(get_volume(wxGetApp().model().objects, input.volume_id) != nullptr);
392 assert(input.cancel != nullptr);
393 res &= input.cancel != nullptr;
394 if (is_main_thread)
395 assert(!input.cancel->load());
396 return res;
397}
static float get_volume(stl_file *stl)
Definition util.cpp:276

References check(), Slic3r::GUI::get_volume(), and input().

+ Here is the call graph for this function:

◆ check() [6/6]

bool priv::check ( const UpdateSurfaceVolumeData input,
bool  is_main_thread = false 
)
406 {
407 bool use_surface = true;
408 bool res = check((DataUpdate)input, is_main_thread, use_surface);
409 assert(!input.sources.empty());
410 res &= !input.sources.empty();
411 return res;
412}
Hold neccessary data to update embossed text object in job.
Definition EmbossJob.hpp:105

References check(), and input().

+ Here is the call 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)
2196{
2197 assert(distances.size() == count_points(shapes));
2198
2199 // vector of patches for shape
2200 std::vector<std::vector<uint32_t>> shapes_patches(shapes.size());
2201 for (const SurfacePatch &patch : patches)
2202 shapes_patches[patch.shape_id].push_back(&patch-&patches.front());
2203
2204 // collect one closest projection for each outline point
2205 ProjectionDistances result(distances.size());
2206
2207 // store info about finished shapes
2208 std::vector<bool> finished_shapes(shapes.size(), {false});
2209
2210 // wanted distance from ideal projection
2211 // Distances are relative to projection distance
2212 // so first wanted distance is the closest one (ZERO)
2213 float wanted_distance = 0.f;
2214
2215 std::vector<bool> mask_distances(s2i.get_count(), {true});
2216 for (const auto &d : distances)
2217 if (d.empty()) mask_distances[&d - &distances.front()] = false;
2218
2219 // Select point from shapes(text contour) which is closest to center (all in 2d)
2220 uint32_t unfinished_index = find_closest_point_index(start, shapes, s2i, mask_distances);
2221
2222#ifdef DEBUG_OUTPUT_DIR
2223 Connections connections;
2224 connections.reserve(shapes.size());
2225 connections.emplace_back(unfinished_index, unfinished_index);
2226#endif // DEBUG_OUTPUT_DIR
2227
2228 do {
2229 const ProjectionDistance* pd = get_closest_projection(distances[unfinished_index], wanted_distance);
2230 // selection of closest_id should proove that pd has value
2231 // (functions: get_closest_point_index and find_close_point_in_points)
2232 assert(pd != nullptr);
2233 uint32_t expolygons_index = s2i.cvt(unfinished_index).expolygons_index;
2234 const ExPolygon &shape = shapes[expolygons_index];
2235 std::vector<uint32_t> &shape_patches = shapes_patches[expolygons_index];
2236 if (shape_patches.size() == 1){
2237 // Speed up, only one patch so copy distance from patch
2238 uint32_t first_shape_index = s2i.cvt({expolygons_index, 0, 0});
2239 uint32_t laset_shape_index = first_shape_index + count_points(shape);
2240 for (uint32_t i = first_shape_index; i < laset_shape_index; ++i) {
2241 const ProjectionDistances &pds = distances[i];
2242 if (pds.empty()) continue;
2243 // check that index belongs to patch
2244 assert(pds.front().patch_index == shape_patches.front());
2245 result[i] = pds.front();
2246 if (pds.size() == 1) continue;
2247
2248 float relative_distance = fabs(result[i].distance - pd->distance);
2249 // patch could contain multiple value for one outline point
2250 // so choose closest to start point
2251 for (uint32_t pds_index = 1; pds_index < pds.size(); ++pds_index) {
2252 // check that index still belongs to same patch
2253 assert(pds[pds_index].patch_index == shape_patches.front());
2254 float relative_distance2 = fabs(pds[pds_index].distance - pd->distance);
2255 if (relative_distance > relative_distance2) {
2256 relative_distance = relative_distance2;
2257 result[i] = pds[pds_index];
2258 }
2259 }
2260 }
2261 } else {
2262 // multiple patches for expolygon
2263 // check that exist patch to fill shape
2264 assert(!shape_patches.empty());
2265 fill_shape_distances(unfinished_index, pd, result, s2i, shape, distances);
2266 }
2267
2268 finished_shapes[expolygons_index] = true;
2269 // The most close points between finished and unfinished shapes
2270 auto [finished, unfinished] = find_closest_point_pair(
2271 shapes, finished_shapes, s2i, mask_distances);
2272
2273 // detection of end (best doesn't have value)
2274 if (finished == std::numeric_limits<uint32_t>::max()) break;
2275
2276 assert(unfinished != std::numeric_limits<uint32_t>::max());
2277 const ProjectionDistance &closest_pd = result[finished];
2278 // check that best_cp is finished and has result
2279 assert(closest_pd.aoi_index != std::numeric_limits<uint32_t>::max());
2280 wanted_distance = closest_pd.distance;
2281 unfinished_index = unfinished;
2282
2283#ifdef DEBUG_OUTPUT_DIR
2284 connections.emplace_back(finished, unfinished);
2285#endif // DEBUG_OUTPUT_DIR
2286 } while (true); //(unfinished_index != std::numeric_limits<uint32_t>::max());
2287#ifdef DEBUG_OUTPUT_DIR
2288 store(shapes, mask_distances, connections, DEBUG_OUTPUT_DIR + "closest_points.svg");
2289#endif // DEBUG_OUTPUT_DIR
2290 return result;
2291}
Definition ExPolygon.hpp:16
uint32_t get_count() const
Count of points in expolygons.
Definition ExPolygonsIndex.cpp:82
uint32_t cvt(const ExPolygonsIndex &id) const
Convert to one index number.
Definition ExPolygonsIndex.cpp:25
if(!(yy_init))
Definition lexer.c:1190
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:229
size_t count_points(const ExPolygons &expolys)
Definition ExPolygon.hpp:88
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:1928
const ProjectionDistance * get_closest_projection(const ProjectionDistances &distance, float wanted_distance)
Definition CutSurface.cpp:1999
uint32_t find_closest_point_index(const Point &p, const ExPolygons &shapes, const ExPolygonsIndices &s2i, const std::vector< bool > &mask)
Definition CutSurface.cpp:1910
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:2083
float distance
Definition CutSurface.cpp:406
std::vector< ProjectionDistance > ProjectionDistances
Definition CutSurface.cpp:409
To select surface near projection distance.
Definition CutSurface.cpp:395

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
98 {
99 std::string message;
100 for (auto &icon : icons) {
101 // Exist more than this instance of shared ptr?
102 long count = icon.use_count();
103 if (count != 1) {
104 // in existing icon change texture to non existing one
105 icon->tex_id = 0;
106
107 std::string descr =
108 ((count > 2) ? (std::to_string(count - 1) + "x") : "") + // count
109 std::to_string(icon->size.x) + "x" + std::to_string(icon->size.y); // resolution
110 if (message.empty())
111 message = descr;
112 else
113 message += ", " + descr;
114 }
115 }
116
117 if (!message.empty())
118 BOOST_LOG_TRIVIAL(warning) << "There is still used icons(" << message << ").";
119}
STL namespace.

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
2532{
2533 CutMesh& tm = cut.mesh;
2534 // create backup for case that there is no intersection
2535 CutMesh backup_copy = tm;
2536
2537 class ExistIntersectionClipVisitor: public CGAL::Polygon_mesh_processing::Corefinement::Default_visitor<CutMesh>
2538 {
2539 bool* exist_intersection;
2540 public:
2541 ExistIntersectionClipVisitor(bool *exist_intersection): exist_intersection(exist_intersection){}
2542 void intersection_point_detected(std::size_t, int , HI, HI, const CutMesh&, const CutMesh&, bool, bool)
2543 { *exist_intersection = true;}
2544 };
2545 bool exist_intersection = false;
2546 ExistIntersectionClipVisitor visitor{&exist_intersection};
2547
2548 // namep parameters for model tm and function clip
2549 const auto &np_tm = CGAL::parameters::visitor(visitor)
2550 .throw_on_self_intersection(false);
2551
2552 // name parameters for model clipper and function clip
2553 const auto &np_c = CGAL::parameters::throw_on_self_intersection(false);
2554 // Can't use 'do_not_modify', when Ture than clipper has to be closed !!
2555 // .do_not_modify(true);
2556 // .throw_on_self_intersection(false); is set automaticaly by param 'do_not_modify'
2557 // .clip_volume(false); is set automaticaly by param 'do_not_modify'
2558
2559 bool suc = CGAL::Polygon_mesh_processing::clip(tm, clipper, np_tm, np_c);
2560
2561 // true if the output surface mesh is manifold.
2562 // If false is returned tm and clipper are only corefined.
2563 assert(suc);
2564 // decide what TODO when can't clip source object !?!
2565 if (!exist_intersection || !suc) {
2566 // TODO: test if cut is fully in or fully out!!
2567 cut.mesh = backup_copy;
2568 return false;
2569 }
2570 return true;
2571}
CGAL::Surface_mesh< EpicKernel::Point_3 > CutMesh
Definition CutSurface.cpp:72

References priv::SurfacePatch::mesh.

Referenced by diff_models().

+ Here is the caller graph for this function:

◆ collect_close_points()

Points priv::collect_close_points ( const ExPolygons expolygons,
double  distance = .6 
)
324 {
325 if (expolygons.empty()) return {};
326 if (distance < 0.) return {};
327
328 // IMPROVE: use int(insted of double) lines and tree
329 const ExPolygonsIndices ids(expolygons);
330 const std::vector<Linef> lines = Slic3r::to_linesf(expolygons, ids.get_count());
332 // Result close points
333 Points res;
334 size_t point_index = 0;
335 auto collect_close = [&res, &point_index, &lines, &tree, &distance, &ids, &expolygons](const Points &pts) {
336 for (const Point &p : pts) {
337 Vec2d p_d = p.cast<double>();
338 std::vector<size_t> close_lines = AABBTreeLines::all_lines_in_radius(lines, tree, p_d, distance);
339 for (size_t index : close_lines) {
340 // skip point neighbour lines indices
341 if (index == point_index) continue;
342 if (&p != &pts.front()) {
343 if (index == point_index - 1) continue;
344 } else if (index == (pts.size()-1)) continue;
345
346 // do not doubled side point of segment
347 const ExPolygonsIndex id = ids.cvt(index);
348 const ExPolygon &expoly = expolygons[id.expolygons_index];
349 const Polygon &poly = id.is_contour() ? expoly.contour : expoly.holes[id.hole_index()];
350 const Points &poly_pts = poly.points;
351 const Point &line_a = poly_pts[id.point_index];
352 const Point &line_b = (!ids.is_last_point(id)) ? poly_pts[id.point_index + 1] : poly_pts.front();
353 assert(line_a == lines[index].a.cast<int>());
354 assert(line_b == lines[index].b.cast<int>());
355 if (p == line_a || p == line_b) continue;
356 res.push_back(p);
357 }
358 ++point_index;
359 }
360 };
361 for (const ExPolygon &expoly : expolygons) {
362 collect_close(expoly.contour.points);
363 for (const Polygon &hole : expoly.holes)
364 collect_close(hole.points);
365 }
366 if (res.empty()) return {};
367 std::sort(res.begin(), res.end());
368 // only unique points
369 res.erase(std::unique(res.begin(), res.end()), res.end());
370 return res;
371}
Definition AABBTreeIndirect.hpp:40
Polygon contour
Definition ExPolygon.hpp:35
Polygons holes
Definition ExPolygon.hpp:36
Keep conversion from ExPolygonsIndex to Index and vice versa ExPolygonsIndex .. contour(or hole) poin...
Definition ExPolygonsIndex.hpp:38
Points points
Definition MultiPoint.hpp:18
Definition Point.hpp:158
std::vector< size_t > all_lines_in_radius(const std::vector< LineType > &lines, const TreeType &tree, const VectorType &point, typename VectorType::Scalar max_distance_squared)
Definition AABBTreeLines.hpp:224
AABBTreeIndirect::Tree< LineType::Dim, typename LineType::Scalar > build_aabb_tree_over_indexed_lines(const std::vector< LineType > &lines)
Definition AABBTreeLines.hpp:168
Linesf to_linesf(const ExPolygons &src, uint32_t count_lines=0)
Definition ExPolygon.hpp:147
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:58
const Polygons & holes(const ExPolygon &p)
Definition AGGRaster.hpp:22
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329
TPoint< P > front(const P &p)
Definition geometry_traits.hpp:872
Slic3r::Polygon & hole(Slic3r::ExPolygon &sh, unsigned long idx)
Definition geometries.hpp:200
Index into ExPolygons Identify expolygon, its contour (or hole) and point.
Definition ExPolygonsIndex.hpp:12

References Slic3r::AABBTreeLines::all_lines_in_radius(), Slic3r::AABBTreeLines::build_aabb_tree_over_indexed_lines(), Slic3r::ExPolygon::contour, Slic3r::ExPolygonsIndices::cvt(), Slic3r::ExPolygonsIndices::get_count(), Slic3r::ExPolygon::holes, Slic3r::ExPolygonsIndices::is_last_point(), Slic3r::MultiPoint::points, and Slic3r::to_linesf().

+ Here is the call 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
2978 {
2979 std::vector<HI> open_half_edges;
2980 for (SurfacePatch &patch : patches) {
2981 open_half_edges.clear();
2982 const CutMesh &mesh = patch.mesh;
2983 for (FI fi : mesh.faces()) {
2984 HI hi1 = mesh.halfedge(fi);
2985 assert(hi1.is_valid());
2986 HI hi2 = mesh.next(hi1);
2987 assert(hi2.is_valid());
2988 HI hi3 = mesh.next(hi2);
2989 assert(hi3.is_valid());
2990 // Is fi triangle?
2991 assert(mesh.next(hi3) == hi1);
2992 for (HI hi : {hi1, hi2, hi3}) {
2993 HI hi_op = mesh.opposite(hi);
2994 FI fi_op = mesh.face(hi_op);
2995 if (!fi_op.is_valid())
2996 open_half_edges.push_back(hi);
2997 }
2998 }
2999 patch.loops = create_loops(open_half_edges, mesh);
3000 }
3001}
CGAL::SM_Halfedge_index HI
Definition CutSurface.cpp:76
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:3365

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
1511{
1512 assert(!process.empty());
1513 assert(faces.empty());
1514 assert(outlines.empty());
1515 while (!process.empty()) {
1516 FI fi = process.front();
1517 process.pop();
1518
1519 FaceType &fi_type = face_type_map[fi];
1520 // Do not process twice
1521 if (fi_type == FaceType::inside_processed) continue;
1522 assert(fi_type == FaceType::inside);
1523 // flag face as processed
1524 fi_type = FaceType::inside_processed;
1525 faces.push_back(fi);
1526
1527 // check neighbor triangle
1528 HI hi = mesh.halfedge(fi);
1529 HI hi_end = hi;
1530 do {
1531 HI hi_opposite = mesh.opposite(hi);
1532 // open edge doesn't have opposit half edge
1533 if (!hi_opposite.is_valid()) {
1534 outlines.push_back(hi);
1535 hi = mesh.next(hi);
1536 continue;
1537 }
1538 FI fi_opposite = mesh.face(hi_opposite);
1539 if (!fi_opposite.is_valid()) {
1540 outlines.push_back(hi);
1541 hi = mesh.next(hi);
1542 continue;
1543 }
1544 FaceType side = face_type_map[fi_opposite];
1545 if (side == FaceType::inside) {
1546 process.emplace(fi_opposite);
1547 } else if (side == FaceType::outside) {
1548 // store outlines
1549 outlines.push_back(hi);
1550 }
1551 hi = mesh.next(hi);
1552 } while (hi != hi_end);
1553 }
1554}
FaceType
Flag for faces in CGAL mesh.
Definition CutSurface.cpp:199

References inside, inside_processed, outside, and process().

Referenced by create_cut_area_of_interests().

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

◆ compute_intersections()

Slic3r::Pointfs priv::compute_intersections ( const Slic3r::Lines lines)
111{
112 using namespace Slic3r;
113 // IMPROVE0: BoundingBoxes of Polygons
114 // IMPROVE1: Polygon's neighbor lines can't intersect
115 // e.g. use indices to Point to find same points
116 // IMPROVE2: Use BentleyOttmann algorithm
117 // https://doc.cgal.org/latest/Surface_sweep_2/index.html -- CGAL implementation is significantly slower
118 // https://stackoverflow.com/questions/4407493/is-there-a-robust-c-implementation-of-the-bentley-ottmann-algorithm
119 Pointfs pts;
120 Point i;
121 for (size_t li = 0; li < lines.size(); ++li) {
122 const Line &l = lines[li];
123 const Point &a = l.a;
124 const Point &b = l.b;
125 Point min(std::min(a.x(), b.x()), std::min(a.y(), b.y()));
126 Point max(std::max(a.x(), b.x()), std::max(a.y(), b.y()));
127 BoundingBox bb(min, max);
128 for (size_t li_ = li + 1; li_ < lines.size(); ++li_) {
129 const Line &l_ = lines[li_];
130 const Point &a_ = l_.a;
131 const Point &b_ = l_.b;
132 if (a == b_ || b == a_ || a == a_ || b == b_) continue;
133 Point min_(std::min(a_.x(), b_.x()), std::min(a_.y(), b_.y()));
134 Point max_(std::max(a_.x(), b_.x()), std::max(a_.y(), b_.y()));
135 BoundingBox bb_(min_, max_);
136 // intersect of BB compare min max
137 if (bb.overlap(bb_) &&
138 l.intersection(l_, &i))
139 pts.push_back(i.cast<double>());
140 }
141 }
142 return pts;
143}
Definition BoundingBox.hpp:181
Definition Line.hpp:155
Point b
Definition Line.hpp:198
Point a
Definition Line.hpp:197
bool intersection(const Line &line, Point *intersection) const
Definition Line.cpp:92
Definition avrdude-slic3r.cpp:16
std::vector< Vec2d > Pointfs
Definition Point.hpp:62
Kernel::Point_2 Point
Definition point_areas.cpp:20

References Slic3r::Line::a, Slic3r::Line::b, Slic3r::Line::intersection(), and Slic3r::BoundingBoxBase< PointType, APointsType >::overlap().

Referenced by Slic3r::intersection_points(), Slic3r::intersection_points(), Slic3r::intersection_points(), Slic3r::intersection_points(), and Slic3r::intersection_points().

+ Here is the call graph for this function:
+ 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
2808{
2809 size_t count = 0;
2810 for (const CutAOIs &cut : cuts) count += cut.size();
2811
2812 std::vector<BoundingBoxf3> bbs;
2813 bbs.reserve(count);
2814 for (size_t model_index = 0; model_index < cut_models.size(); ++model_index) {
2815 const CutMesh &cut_model = cut_models[model_index];
2816 const CutAOIs &cutAOIs = cuts[model_index];
2817 for (size_t cut_index = 0; cut_index < cutAOIs.size(); ++cut_index) {
2818 const CutAOI &cut = cutAOIs[cut_index];
2819 bbs.push_back(bounding_box(cut, cut_model));
2820 }
2821 }
2822 return bbs;
2823}
std::pair< std::vector< FI >, std::vector< HI > > CutAOI
Definition CutSurface.cpp:243
std::vector< CutAOI > CutAOIs
Definition CutSurface.cpp:245

References bounding_box().

Referenced by diff_models().

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

◆ create_bounding_rect()

ExPolygon priv::create_bounding_rect ( const ExPolygons shape)
682 {
683 BoundingBox bb = get_extents(shape);
684 Point size = bb.size();
685 if (size.x() < 10)
686 bb.max.x() += 10;
687 if (size.y() < 10)
688 bb.max.y() += 10;
689
690 Polygon rect({// CCW
691 bb.min,
692 {bb.max.x(), bb.min.y()},
693 bb.max,
694 {bb.min.x(), bb.max.y()}});
695
696 Point offset = bb.size() * 0.1;
697 Polygon hole({// CW
698 bb.min + offset,
699 {bb.min.x() + offset.x(), bb.max.y() - offset.y()},
700 bb.max - offset,
701 {bb.max.x() - offset.x(), bb.min.y() + offset.y()}});
702
703 return ExPolygon(rect, hole);
704}
PointType max
Definition BoundingBox.hpp:17
PointType size() const
Definition BoundingBox.cpp:144
PointType min
Definition BoundingBox.hpp:16
BoundingBox get_extents(const ExPolygon &expolygon)
Definition ExPolygon.cpp:352

References Slic3r::get_extents(), Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::offset(), and Slic3r::BoundingBoxBase< PointType, APointsType >::size().

Referenced by heal_dupl_inter().

+ 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
1652{
1653 // IMPROVE: Create better heuristic for count.
1654 size_t faces_per_cut = mesh.faces().size() / shapes.size();
1655 size_t outlines_per_cut = faces_per_cut / 2;
1656 size_t cuts_per_model = shapes.size() * 2;
1657
1658 CutAOIs result;
1659 result.reserve(cuts_per_model);
1660
1661 // It is faster to use one queue for all cuts
1662 std::queue<FI> process;
1663 for (FI fi : mesh.faces()) {
1664 if (face_type_map[fi] != FaceType::inside) continue;
1665
1666 CutAOI cut;
1667 std::vector<FI> &faces = cut.first;
1668 std::vector<HI> &outlines = cut.second;
1669
1670 // faces for one surface cut
1671 faces.reserve(faces_per_cut);
1672 // outline for one surface cut
1673 outlines.reserve(outlines_per_cut);
1674
1675 assert(process.empty());
1676 // Process queue of faces to separate to surface_cut
1677 process.push(fi);
1678 collect_surface_data(process, faces, outlines, face_type_map, mesh);
1679 assert(!faces.empty());
1680 assert(!outlines.empty());
1681 result.emplace_back(std::move(cut));
1682 }
1683 return result;
1684}
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:1506

References collect_surface_data(), inside, and process().

Referenced by cut_from_model().

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

◆ create_default_mesh()

TriangleMesh priv::create_default_mesh ( )
static

Create default mesh for embossed text.

Returns
Not empty model(index trinagle set - its)
472{
473 // When cant load any font use default object loaded from file
474 std::string path = Slic3r::resources_dir() + "/data/embossed_text.obj";
475 TriangleMesh triangle_mesh;
476 if (!load_obj(path.c_str(), &triangle_mesh)) {
477 // when can't load mesh use cube
478 return TriangleMesh(its_make_cube(36., 4., 2.5));
479 }
480 return triangle_mesh;
481}
Definition TriangleMesh.hpp:88
const std::string & resources_dir()
Definition utils.cpp:167
indexed_triangle_set its_make_cube(double xd, double yd, double zd)
Definition TriangleMesh.cpp:921
bool load_obj(const char *path, TriangleMesh *meshptr)
Definition OBJ.cpp:20

References Slic3r::its_make_cube(), Slic3r::load_obj(), and Slic3r::resources_dir().

+ Here is the call graph for this function:

◆ create_emboss_data_base()

DataBase priv::create_emboss_data_base ( const std::string &  text,
StyleManager style_manager,
std::shared_ptr< std::atomic< bool > > &  cancel 
)
static

Prepare data for emboss.

Parameters
textText to emboss
style_managerKeep actual selected style
cancelCancel for previous job
Returns
Base data for emboss text
3425{
3426 // create volume_name
3427 std::string volume_name = text; // copy
3428 // contain_enter?
3429 if (volume_name.find('\n') != std::string::npos)
3430 // change enters to space
3431 std::replace(volume_name.begin(), volume_name.end(), '\n', ' ');
3432
3433 if (!style_manager.is_active_font()) {
3434 style_manager.load_valid_style();
3435 assert(style_manager.is_active_font());
3436 if (!style_manager.is_active_font())
3437 return {}; // no active font in style, should never happend !!!
3438 }
3439
3440 const EmbossStyle &es = style_manager.get_style();
3441 // actualize font path - during changes in gui it could be corrupted
3442 // volume must store valid path
3443 assert(style_manager.get_wx_font().IsOk());
3444 assert(es.path.compare(WxFontUtils::store_wxFont(style_manager.get_wx_font())) == 0);
3445 TextConfiguration tc{es, text};
3446
3447 // Cancel previous Job, when it is in process
3448 // worker.cancel(); --> Use less in this case I want cancel only previous EmbossJob no other jobs
3449 // Cancel only EmbossUpdateJob no others
3450 if (cancel != nullptr)
3451 cancel->store(true);
3452 // create new shared ptr to cancel new job
3453 cancel = std::make_shared<std::atomic<bool>>(false);
3454 return Slic3r::GUI::Emboss::DataBase{style_manager.get_font_file_with_cache(), tc, volume_name, cancel};
3455}
Slic3r::Emboss::FontFileWithCache & get_font_file_with_cache()
Definition EmbossStyleManager.hpp:121
bool is_active_font()
Definition EmbossStyleManager.cpp:268
const EmbossStyle & get_style() const
Definition EmbossStyleManager.hpp:112
void load_valid_style()
load some valid style
Definition EmbossStyleManager.cpp:156
const wxFont & get_wx_font() const
Definition EmbossStyleManager.hpp:119
static std::string store_wxFont(const wxFont &font)
Definition WxFontUtils.cpp:168
Style of embossed text (Path + Type) must define how to open font for using on different OS NOTE: OnE...
Definition TextConfiguration.hpp:155
std::string path
Definition TextConfiguration.hpp:161
Define how to create 'Text volume' It is stored into .3mf by TextConfigurationSerialization It is par...
Definition TextConfiguration.hpp:215

References Slic3r::GUI::Emboss::StyleManager::get_font_file_with_cache(), Slic3r::GUI::Emboss::StyleManager::get_style(), Slic3r::GUI::Emboss::StyleManager::get_wx_font(), Slic3r::GUI::Emboss::StyleManager::is_active_font(), Slic3r::GUI::Emboss::StyleManager::load_valid_style(), Slic3r::EmbossStyle::path, and Slic3r::GUI::WxFontUtils::store_wxFont().

Referenced by Slic3r::GUI::GLGizmoEmboss::create_volume(), Slic3r::GUI::GLGizmoEmboss::create_volume(), and Slic3r::GUI::GLGizmoEmboss::process().

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

◆ create_emboss_projection()

OrthoProject3d priv::create_emboss_projection ( bool  is_outside,
float  emboss,
Transform3d  tr,
SurfaceCut cut 
)
static

Create tranformation for emboss Cutted surface.

Parameters
is_outsideTrue .. raise, False .. engrave
embossDepth of embossing
trText voliume transformation inside object
cutCutted surface from model
Returns
Projection
717{
718 // Offset of clossed side to model
719 const float surface_offset = 0.015f; // [in mm]
720 float
721 front_move = (is_outside) ? emboss : surface_offset,
722 back_move = -((is_outside) ? surface_offset : emboss);
723 its_transform(cut, tr.pretranslate(Vec3d(0., 0., front_move)));
724 Vec3d from_front_to_back(0., 0., back_move - front_move);
725 return OrthoProject3d(from_front_to_back);
726}
Definition Emboss.hpp:341
EIGEN_DEVICE_FUNC Transform & pretranslate(const MatrixBase< OtherDerived > &other)
void its_transform(indexed_triangle_set &its, T *trafo3x4)
Definition stl.h:266

References its_transform(), and Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::pretranslate().

Referenced by cut_surface().

+ 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
2439{
2440 auto get_intersection_source = [&tm2](const Source& s1, const Source& s2)->FI{
2441 // when one of sources is face than return it
2442 FI fi1 = tm2.face(s1.hi);
2443 if (s1.sdim == 2) return fi1;
2444 FI fi2 = tm2.face(s2.hi);
2445 if (s2.sdim == 2) return fi2;
2446 // both vertices are made by same source triangle
2447 if (fi1 == fi2) return fi1;
2448
2449 // when one from sources is edge second one decide side of triangle triangle
2450 HI hi1_opposit = tm2.opposite(s1.hi);
2451 FI fi1_opposit;
2452 if (hi1_opposit.is_valid())
2453 fi1_opposit = tm2.face(hi1_opposit);
2454 if (fi2 == fi1_opposit) return fi2;
2455
2456 HI hi2_opposit = tm2.opposite(s2.hi);
2457 FI fi2_opposit;
2458 if (hi2_opposit.is_valid())
2459 fi2_opposit = tm2.face(hi2_opposit);
2460 if (fi1 == fi2_opposit) return fi1;
2461 if (fi1_opposit.is_valid() && fi1_opposit == fi2_opposit)
2462 return fi1_opposit;
2463
2464 // when intersection is vertex need loop over neighbor
2465 for (FI fi_around_hi1 : tm2.faces_around_target(s1.hi)) {
2466 for (FI fi_around_hi2 : tm2.faces_around_target(s2.hi)) {
2467 if (fi_around_hi1 == fi_around_hi2)
2468 return fi_around_hi1;
2469 }
2470 }
2471
2472 // should never rich it
2473 // Exist case when do not know source triangle for decide side of intersection
2474 assert(false);
2475 return FI();
2476 };
2477
2478 for (FI fi : tm1.faces()) map[fi] = FaceType::not_constrained;
2479 for (EI ei1 : tm1.edges()) {
2480 if (!get(ecm, ei1)) continue;
2481
2482 // get faces from tm1 (f1a + f1b)
2483 HI hi1 = tm1.halfedge(ei1);
2484 assert(hi1.is_valid());
2485 FI f1a = tm1.face(hi1);
2486 assert(f1a.is_valid());
2487 HI hi_op = tm1.opposite(hi1);
2488 assert(hi_op.is_valid());
2489 FI f1b = tm1.face(hi_op);
2490 assert(f1b.is_valid());
2491
2492 // get faces from tm2 (f2a + f2b)
2493 VI vi1_source = tm1.source(hi1);
2494 assert(vi1_source.is_valid());
2495 VI vi1_target = tm1.target(hi1);
2496 assert(vi1_target.is_valid());
2497
2498 const Source &s_s = sources[vi1_source];
2499 const Source &s_t = sources[vi1_target];
2500 FI fi2 = get_intersection_source(s_s, s_t);
2501
2502 // in release solve situation that face was NOT deduced
2503 if (!fi2.is_valid()) continue;
2504
2505 HI hi2 = tm2.halfedge(fi2);
2506 std::array<const P3 *, 3> t;
2507 size_t ti =0;
2508 for (VI vi2 : tm2.vertices_around_face(hi2))
2509 t[ti++] = &tm2.point(vi2);
2510
2511 // triangle tip from face f1a
2512 VI vi1a_tip = tm1.target(tm1.next(hi1));
2513 assert(vi1a_tip.is_valid());
2514 const P3 &p = tm1.point(vi1a_tip);
2515
2516 // check if f1a is behinde f2a
2517 // inside mean it will be used
2518 // outside will be discarded
2519 if (CGAL::orientation(*t[0], *t[1], *t[2], p) == CGAL::POSITIVE) {
2520 map[f1a] = FaceType::inside;
2521 map[f1b] = FaceType::outside;
2522 } else {
2523 map[f1a] = FaceType::outside;
2524 map[f1b] = FaceType::inside;
2525 }
2526 }
2527}
constexpr auto get(span< E, S > s) -> decltype(s[N])
Definition span.hpp:590
IGL_INLINE void edges(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
Definition edges.cpp:13
int sdim
Definition CutSurface.cpp:2298
HI hi
Definition CutSurface.cpp:2298
Definition CutSurface.cpp:2298

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
3366{
3367 Loops loops;
3368 Loops unclosed;
3369 for (HI hi : outlines) {
3370 VI vi_s = mesh.source(hi);
3371 VI vi_t = mesh.target(hi);
3372 Loop *loop_move = nullptr;
3373 Loop *loop_connect = nullptr;
3374 for (std::vector<VI> &cut : unclosed) {
3375 if (cut.back() != vi_s) continue;
3376 if (cut.front() == vi_t) {
3377 // cut closing
3378 loop_move = &cut;
3379 } else {
3380 loop_connect = &cut;
3381 }
3382 break;
3383 }
3384 if (loop_move != nullptr) {
3385 // index of closed cut
3386 size_t index = loop_move - &unclosed.front();
3387 // move cut to result
3388 loops.emplace_back(std::move(*loop_move));
3389 // remove it from unclosed cut
3390 unclosed.erase(unclosed.begin() + index);
3391 } else if (loop_connect != nullptr) {
3392 // try find tail to connect cut
3393 Loop *loop_tail = nullptr;
3394 for (Loop &cut : unclosed) {
3395 if (cut.front() != vi_t) continue;
3396 loop_tail = &cut;
3397 break;
3398 }
3399 if (loop_tail != nullptr) {
3400 // index of tail
3401 size_t index = loop_tail - &unclosed.front();
3402 // move to connect vector
3403 loop_connect->insert(loop_connect->end(),
3404 make_move_iterator(loop_tail->begin()),
3405 make_move_iterator(loop_tail->end()));
3406 // remove tail from unclosed cut
3407 unclosed.erase(unclosed.begin() + index);
3408 } else {
3409 loop_connect->push_back(vi_t);
3410 }
3411 } else { // not found
3412 bool create_cut = true;
3413 // try to insert to front of cut
3414 for (Loop &cut : unclosed) {
3415 if (cut.front() != vi_t) continue;
3416 cut.insert(cut.begin(), vi_s);
3417 create_cut = false;
3418 break;
3419 }
3420 if (create_cut)
3421 unclosed.emplace_back(std::vector{vi_s, vi_t});
3422 }
3423 }
3424 assert(unclosed.empty());
3425 return loops;
3426}
std::vector< Loop > Loops
Definition CutSurface.cpp:268

Referenced by collect_open_edges().

+ Here is the caller graph for this function:

◆ create_mesh()

template<typename Fnc >
static TriangleMesh priv::create_mesh ( DataBase input,
Fnc  was_canceled,
Job::Ctl ctl 
)
static

Referenced by Slic3r::GUI::Emboss::CreateVolumeJob::process(), and Slic3r::GUI::Emboss::CreateObjectJob::process().

+ Here is the caller graph for this function:

◆ create_message()

void priv::create_message ( const std::string &  message)
static
854 {
855 show_error(nullptr, message.c_str());
856}
void show_error(wxWindow *parent, const wxString &message, bool monospaced_font)
Definition GUI.cpp:224

References Slic3r::GUI::show_error().

Referenced by create_volume(), Slic3r::GUI::Emboss::CreateVolumeJob::finalize(), Slic3r::GUI::Emboss::CreateObjectJob::finalize(), process(), and update_volume().

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

◆ create_projection_for_cut()

OrthoProject priv::create_projection_for_cut ( Transform3d  tr,
double  shape_scale,
const std::pair< float, float > &  z_range 
)
static

Create projection for cut surface from mesh.

Parameters
trVolume transformation in object
shape_scaleConvert shape to milimeters
z_rangeBounding box 3d of model volume for projection ranges
Returns
Orthogonal cut_projection
694{
695 double min_z = z_range.first - priv::safe_extension;
696 double max_z = z_range.second + priv::safe_extension;
697 assert(min_z < max_z);
698 // range between min and max value
699 double projection_size = max_z - min_z;
700 Matrix3d transformation_for_vector = tr.linear();
701 // Projection must be negative value.
702 // System of text coordinate
703 // X .. from left to right
704 // Y .. from bottom to top
705 // Z .. from text to eye
706 Vec3d untransformed_direction(0., 0., projection_size);
707 Vec3d project_direction = transformation_for_vector * untransformed_direction;
708
709 // Projection is in direction from far plane
710 tr.translate(Vec3d(0., 0., min_z));
711 tr.scale(shape_scale);
712 return OrthoProject(tr, project_direction);
713}
Definition Emboss.hpp:349
EIGEN_DEVICE_FUNC Transform & scale(const MatrixBase< OtherDerived > &other)
EIGEN_DEVICE_FUNC Transform & translate(const MatrixBase< OtherDerived > &other)
constexpr float safe_extension
Definition EmbossJob.cpp:29

References Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::linear(), safe_extension, Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::scale(), and Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::translate().

Referenced by cut_surface().

+ Here is the call graph for this function:
+ 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

1557{
1558 const VertexShapeMap &vert_shape_map = mesh.property_map<VI, const IntersectingElement*>(vert_shape_map_name).first;
1559 const EdgeBoolMap &ecm = mesh.property_map<EI, bool>(is_constrained_edge_name).first;
1560
1561 // check if vertex was made by edge_2 which is diagonal of quad
1562 auto is_reducible_vertex = [&vert_shape_map](VI reduction_from) -> bool {
1563 const IntersectingElement *ie = vert_shape_map[reduction_from];
1564 if (ie == nullptr) return false;
1566 return type == IntersectingElement::Type::edge_2;
1567 };
1568
1575 auto add_reduction = [&] //&reduction_map, &mesh, &face_type_map, &is_reducible_vertex
1576 (HI hi) {
1577 VI erase = mesh.target(hi);
1578 VI left = mesh.source(hi);
1579 assert(is_reducible_vertex(erase));
1580 assert(!is_reducible_vertex(left));
1581 VI &vi = reduction_map[erase];
1582 // check if it is first add
1583 if (vi.is_valid())
1584 return;
1585
1586 // check that all triangles after reduction has 'erase' and 'left' vertex
1587 // on same side of opposite line of vertex in triangle
1588 Vec3d v_erase = to_vec3d(mesh.point(erase));
1589 Vec3d v_left = to_vec3d(mesh.point(left));
1590 for (FI fi : mesh.faces_around_target(hi)) {
1591 if (!fi.is_valid())
1592 continue;
1593 // get vertices of rest
1594 VI vi_a, vi_b;
1595 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi))) {
1596 if (!vi.is_valid())
1597 continue;
1598 if (vi == erase)
1599 continue;
1600 if (!vi_a.is_valid())
1601 vi_a = vi;
1602 else {
1603 assert(!vi_b.is_valid());
1604 vi_b = vi;
1605 }
1606 }
1607 assert(vi_b.is_valid());
1608 // do not check triangle, which will be removed
1609 if (vi_a == left || vi_b == left)
1610 continue;
1611
1612 Vec3d v_a = to_vec3d(mesh.point(vi_a));
1613 Vec3d v_b = to_vec3d(mesh.point(vi_b));
1614 // Vectors of triangle edges
1615 Vec3d v_ab = v_b - v_a;
1616 Vec3d v_ae = v_erase - v_a;
1617 Vec3d v_al = v_left - v_a;
1618
1619 Vec3d n1 = v_ab.cross(v_ae);
1620 Vec3d n2 = v_ab.cross(v_al);
1621 // check that normal has same direction
1622 if (((n1.x() > 0) != (n2.x() > 0)) ||
1623 ((n1.y() > 0) != (n2.y() > 0)) ||
1624 ((n1.z() > 0) != (n2.z() > 0)))
1625 return; // this reduction will create CCW triangle
1626 }
1627
1628 reduction_map[erase] = left;
1629 // I have no better rule than take the first
1630 // for decide which reduction will be better
1631 // But it could be use only one of them
1632 };
1633
1634 for (EI ei : mesh.edges()) {
1635 if (!ecm[ei]) continue;
1636 HI hi = mesh.halfedge(ei);
1637 VI vi = mesh.target(hi);
1638 if (is_reducible_vertex(vi)) add_reduction(hi);
1639
1640 HI hi_op = mesh.opposite(hi);
1641 VI vi_op = mesh.target(hi_op);
1642 if (is_reducible_vertex(vi_op)) add_reduction(hi_op);
1643 }
1644#ifdef DEBUG_OUTPUT_DIR
1645 store(mesh, reduction_map, DEBUG_OUTPUT_DIR + "reduces/");
1646#endif // DEBUG_OUTPUT_DIR
1647}
void erase(std::vector< VecType > &vec, const std::vector< bool > &flags)
Definition RaycastManager.cpp:301
const std::string is_constrained_edge_name
Definition CutSurface.cpp:225
CGAL::SM_Edge_index EI
Definition CutSurface.cpp:77
CutMesh::Property_map< EI, bool > EdgeBoolMap
Definition CutSurface.cpp:224
Type get_type() const
Definition CutSurface.cpp:177
Type
Definition CutSurface.cpp:161

References priv::IntersectingElement::edge_2, erase, 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 
)
1828{
1829 // IMPROVE: Use float precission (it is enough)
1830 SearchData sd;
1831 sd.lines.reserve(mask.size());
1832 sd.cvt.reserve(mask.size());
1833 size_t index = 0;
1834 auto add_lines = [&sd, &index, &mask]
1835 (const Polygon &poly) {
1836 Vec2d prev = poly.back().cast<double>();
1837 bool use_point = mask[index + poly.points.size() - 1];
1838 for (const Point &p : poly.points) {
1839 if (!use_point) {
1840 use_point = mask[index];
1841 if (use_point) prev = p.cast<double>();
1842 } else if (!mask[index]) {
1843 use_point = false;
1844 } else {
1845 Vec2d p_d = p.cast<double>();
1846 sd.lines.emplace_back(prev, p_d);
1847 sd.cvt.push_back(index);
1848 prev = p_d;
1849 }
1850 ++index;
1851 }
1852 };
1853
1854 for (const ExPolygon &shape : shapes) {
1855 add_lines(shape.contour);
1856 for (const Polygon &hole : shape.holes) add_lines(hole);
1857 }
1859 return sd;
1860}
std::vector< size_t > cvt
Definition CutSurface.cpp:1793
std::vector< Linef > lines
Definition CutSurface.cpp:1791
AABBTreeIndirect::Tree< 2, double > tree
Definition CutSurface.cpp:1795
Definition CutSurface.cpp:1789

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_shape()

template<typename Fnc >
static ExPolygons priv::create_shape ( DataBase input,
Fnc  was_canceled 
)
static

Referenced by cut_surface().

+ Here is the caller graph for this function:

◆ create_style()

EmbossStyle priv::create_style ( std::wstring  name,
std::wstring  path 
)
853 {
854 return { boost::nowide::narrow(name.c_str()),
855 boost::nowide::narrow(path.c_str()),
856 EmbossStyle::Type::file_path, FontProp() };
857}
char * narrow(char *output, size_t output_size, wchar_t const *source)
Convert NULL terminated UTF source string to NULL terminated output string of size at most output_siz...
Definition convert.hpp:73
User modifiable property of text style NOTE: OnEdit fix serializations: EmbossStylesSerializable,...
Definition TextConfiguration.hpp:20

References boost::nowide::narrow().

+ Here is the call 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
2610{
2611 auto is_counted = mesh.add_property_map<VI, bool>("v:is_counted").first;
2612 uint32_t count_vertices = 0;
2613 if (rmap == nullptr) {
2614 for (FI fi : fis)
2615 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi)))
2616 if (!is_counted[vi]) {
2617 is_counted[vi] = true;
2618 ++count_vertices;
2619 }
2620 } else {
2621 for (FI fi : fis)
2622 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi))) {
2623 // Will vertex be reduced?
2624 if ((*rmap)[vi].is_valid()) continue;
2625 if (!is_counted[vi]) {
2626 is_counted[vi] = true;
2627 ++count_vertices;
2628 }
2629 }
2630 }
2631 mesh.remove_property_map(is_counted);
2632
2633 uint32_t count_faces = fis.size();
2634 // IMPROVE: Value is greater than neccessary, count edges used twice
2635 uint32_t count_edges = count_faces*3;
2636
2637 CutMesh cm;
2638 cm.reserve(count_vertices, count_edges, count_faces);
2639
2640 // vertex conversion function from mesh VI to result VI
2641 CvtVI2VI mesh2result = mesh.add_property_map<VI,VI>("v:mesh2result").first;
2642
2643 if (rmap == nullptr) {
2644 for (FI fi : fis) {
2645 std::array<VI, 3> t;
2646 int index = 0;
2647 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi))) {
2648 VI &vi_cvt = mesh2result[vi];
2649 if (!vi_cvt.is_valid()) {
2650 vi_cvt = VI(cm.vertices().size());
2651 cm.add_vertex(mesh.point(vi));
2652 }
2653 t[index++] = vi_cvt;
2654 }
2655 cm.add_face(t[0], t[1], t[2]);
2656 }
2657 } else {
2658 for (FI fi :fis) {
2659 std::array<VI, 3> t;
2660 int index = 0;
2661 bool exist_reduction = false;
2662 for (VI vi : mesh.vertices_around_face(mesh.halfedge(fi))) {
2663 VI vi_r = (*rmap)[vi];
2664 if (vi_r.is_valid()) {
2665 exist_reduction = true;
2666 vi = vi_r;
2667 }
2668 VI &vi_cvt = mesh2result[vi];
2669 if (!vi_cvt.is_valid()) {
2670 vi_cvt = VI(cm.vertices().size());
2671 cm.add_vertex(mesh.point(vi));
2672 }
2673 t[index++] = vi_cvt;
2674 }
2675
2676 // prevent add reduced triangle
2677 if (exist_reduction &&
2678 (t[0] == t[1] ||
2679 t[1] == t[2] ||
2680 t[2] == t[0]))
2681 continue;
2682
2683 cm.add_face(t[0], t[1], t[2]);
2684 }
2685 }
2686
2687 assert(count_vertices == cm.vertices().size());
2688 assert((rmap == nullptr && count_faces == cm.faces().size()) ||
2689 (rmap != nullptr && count_faces >= cm.faces().size()));
2690 assert(count_edges >= cm.edges().size());
2691
2692 // convert VI from this patch to source VI, when exist
2693 CvtVI2VI cvt = cm.add_property_map<VI, VI>(patch_source_name).first;
2694 // vi_s .. VertexIndex into mesh (source)
2695 // vi_d .. new VertexIndex in cm (destination)
2696 for (VI vi_s : mesh.vertices()) {
2697 VI vi_d = mesh2result[vi_s];
2698 if (!vi_d.is_valid()) continue;
2699 cvt[vi_d] = vi_s;
2700 }
2701 mesh.remove_property_map(mesh2result);
2702 return {std::move(cm)};
2703}
bool is_valid(const FontFile &font, unsigned int index)
Definition Emboss.cpp:233

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
2826 {
2827 Trees result;
2828 result.reserve(models.size());
2829 for (const CutMesh &model : models) {
2830 Tree tree;
2831 tree.insert(faces(model).first, faces(model).second, model);
2832 tree.build();
2833 result.emplace_back(std::move(tree));
2834 }
2835 return result;
2836}
std::vector< Tree > Trees
Definition CutSurface.cpp:2733
CGAL::AABB_tree< Traits > Tree
Definition CutSurface.cpp:2732

◆ create_volume()

void priv::create_volume ( TriangleMesh &&  mesh,
const ObjectID object_id,
const ModelVolumeType  type,
const Transform3d  trmat,
const DataBase data 
)
static

Add new volume to object.

Parameters
meshtriangles of new volume
object_idObject where to add volume
typeType of new volume
trmatTransformation of volume inside of object
dataText configuration and New VolumeName
603{
604 GUI_App &app = wxGetApp();
605 Plater *plater = app.plater();
607 GLCanvas3D *canvas = plater->canvas3D();
608 ModelObjectPtrs &objects = plater->model().objects;
609
610 ModelObject *obj = nullptr;
611 size_t object_idx = 0;
612 for (; object_idx < objects.size(); ++object_idx) {
613 ModelObject *o = objects[object_idx];
614 if (o->id() == object_id) {
615 obj = o;
616 break;
617 }
618 }
619
620 // Parent object for text volume was propably removed.
621 // Assumption: User know what he does, so text volume is no more needed.
622 if (obj == nullptr)
623 return priv::create_message("Bad object to create volume.");
624
625 if (mesh.its.empty())
626 return priv::create_message("Can't create empty volume.");
627
628 plater->take_snapshot(_L("Add Emboss text Volume"));
629
630 // NOTE: be carefull add volume also center mesh !!!
631 // So first add simple shape(convex hull is also calculated)
632 ModelVolume *volume = obj->add_volume(make_cube(1., 1., 1.), type);
633
634 // TODO: Refactor to create better way to not set cube at begining
635 // Revert mesh centering by set mesh after add cube
636 volume->set_mesh(std::move(mesh));
637 volume->calculate_convex_hull();
638
639
640 // set a default extruder value, since user can't add it manually
641 volume->config.set_key_value("extruder", new ConfigOptionInt(0));
642
643 // do not allow model reload from disk
644 volume->source.is_from_builtin_objects = true;
645
646 volume->name = data.volume_name; // copy
647 volume->text_configuration = data.text_configuration; // copy
648
649 // discard information about rotation, should not be stored in volume
650 volume->text_configuration->style.prop.angle.reset();
651
652 volume->set_transformation(trmat);
653
654 // update printable state on canvas
655 if (type == ModelVolumeType::MODEL_PART) {
656 volume->get_object()->ensure_on_bed();
658 }
659
660 // update volume name in object list
661 // updata selection after new volume added
662 // change name of volume in right panel
663 // select only actual volume
664 // when new volume is created change selection to this volume
665 auto add_to_selection = [volume](const ModelVolume *vol) { return vol == volume; };
666 wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection(object_idx, add_to_selection);
667 if (!sel.IsEmpty()) obj_list->select_item(sel.front());
668
670
671 // Now is valid text volume selected open emboss gizmo
672 GLGizmosManager &manager = canvas->get_gizmos_manager();
675
676 // update model and redraw scene
677 //canvas->reload_scene(true);
678 plater->update();
679}
Definition Config.hpp:720
Definition GLCanvas3D.hpp:185
void update_instance_printable_state_for_object(size_t obj_idx)
Definition GLCanvas3D.cpp:1682
const GLGizmosManager & get_gizmos_manager() const
Definition GLCanvas3D.hpp:764
Definition GLGizmosManager.hpp:63
@ Emboss
Definition GLGizmosManager.hpp:81
bool open_gizmo(EType type)
Definition GLGizmosManager.cpp:182
EType get_current_type() const
Definition GLGizmosManager.hpp:192
Definition GUI_App.hpp:117
ObjectList * obj_list()
Definition GUI_App.cpp:2953
Plater * plater()
Definition GUI_App.cpp:2963
Definition GUI_ObjectList.hpp:78
void selection_changed()
Definition GUI_ObjectList.cpp:728
wxDataViewItemArray reorder_volumes_and_get_selection(size_t obj_idx, std::function< bool(const ModelVolume *)> add_to_selection=nullptr)
Definition GUI_ObjectList.cpp:4906
void select_item(const wxDataViewItem &item)
Definition GUI_ObjectList.cpp:4007
Definition Plater.hpp:134
void update(unsigned int flags=0)
Definition Plater.cpp:6068
const Model & model() const
Definition Plater.cpp:5222
void take_snapshot(const std::string &snapshot_name)
Definition Plater.cpp:6891
GLCanvas3D * canvas3D()
Definition Plater.cpp:7226
Definition Model.hpp:328
ModelVolume * add_volume(const TriangleMesh &mesh)
Definition Model.cpp:717
Definition Model.hpp:753
ObjectID id() const
Definition ObjectID.hpp:55
indexed_triangle_set its
Definition TriangleMesh.hpp:155
static ObjectList * obj_list()
Definition GUI_Factories.cpp:179
static Plater * plater()
Definition GUI_Factories.cpp:174
TriangleMesh make_cube(double x, double y, double z)
Definition TriangleMesh.hpp:328
std::vector< ModelObject * > ModelObjectPtrs
Definition Model.hpp:105
constexpr auto data(C &c) -> decltype(c.data())
Definition span.hpp:195
IGL_INLINE void volume(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, Eigen::PlainObjectBase< Derivedvol > &vol)
Definition volume.cpp:15
static void create_message(const std::string &message)
Definition EmbossJob.cpp:854
#define _L(s)
Definition I18N.hpp:3

References _L, Slic3r::ModelObject::add_volume(), Slic3r::GUI::Plater::canvas3D(), create_message(), Slic3r::GUI::GLGizmosManager::Emboss, Slic3r::GUI::GLGizmosManager::get_current_type(), Slic3r::GUI::GLCanvas3D::get_gizmos_manager(), Slic3r::ObjectBase::id(), Slic3r::make_cube(), Slic3r::GUI::Plater::model(), Slic3r::MODEL_PART, Slic3r::GUI::GUI_App::obj_list(), Slic3r::GUI::obj_list(), Slic3r::Model::objects, Slic3r::GUI::GLGizmosManager::open_gizmo(), Slic3r::GUI::GUI_App::plater(), Slic3r::GUI::plater(), Slic3r::GUI::ObjectList::reorder_volumes_and_get_selection(), Slic3r::GUI::ObjectList::select_item(), Slic3r::GUI::ObjectList::selection_changed(), Slic3r::GUI::Plater::take_snapshot(), Slic3r::GUI::Plater::update(), and Slic3r::GUI::GLCanvas3D::update_instance_printable_state_for_object().

Referenced by Slic3r::GUI::Emboss::CreateVolumeJob::finalize(), and Slic3r::GUI::Emboss::CreateSurfaceVolumeJob::finalize().

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

◆ 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
1401{
1402 // pointer to edge or face shape_map
1403 VertexShapeMap vert_shape_map = cgal_model.add_property_map<VI, const IntersectingElement*>(vert_shape_map_name, nullptr).first;
1404
1405 // detect anomalities in visitor.
1406 bool is_valid = true;
1407 // NOTE: map are created when convert shapes to cgal model
1408 const EdgeShapeMap& edge_shape_map = cgal_shape.property_map<EI, IntersectingElement>(edge_shape_map_name).first;
1409 const FaceShapeMap& face_shape_map = cgal_shape.property_map<FI, IntersectingElement>(face_shape_map_name).first;
1410 Visitor visitor{cgal_model, cgal_shape, edge_shape_map, face_shape_map, vert_shape_map, &is_valid};
1411
1412 // a property map containing the constrained-or-not status of each edge
1413 EdgeBoolMap ecm = cgal_model.add_property_map<EI, bool>(is_constrained_edge_name, false).first;
1414 const auto &p = CGAL::parameters::visitor(visitor)
1415 .edge_is_constrained_map(ecm)
1416 .throw_on_self_intersection(false);
1417 const auto& q = CGAL::parameters::do_not_modify(true);
1418 CGAL::Polygon_mesh_processing::corefine(cgal_model, cgal_shape, p, q);
1419
1420 if (!is_valid) return {};
1421
1422 FaceTypeMap face_type_map = cgal_model.add_property_map<FI, FaceType>(face_type_map_name, FaceType::not_constrained).first;
1423
1424 // Select inside and outside face in model
1425 set_face_type(face_type_map, cgal_model, vert_shape_map, ecm, cgal_shape, s2i);
1426#ifdef DEBUG_OUTPUT_DIR
1427 store(cgal_model, face_type_map, DEBUG_OUTPUT_DIR + "constrained/"); // only debug
1428#endif // DEBUG_OUTPUT_DIR
1429
1430 // flood fill the other faces inside the region.
1431 flood_fill_inner(cgal_model, face_type_map);
1432
1433#ifdef DEBUG_OUTPUT_DIR
1434 store(cgal_model, face_type_map, DEBUG_OUTPUT_DIR + "filled/", true); // only debug
1435#endif // DEBUG_OUTPUT_DIR
1436
1437 // IMPROVE: AOIs area could be created during flood fill
1438 return create_cut_area_of_interests(cgal_model, shapes, face_type_map);
1439}
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:1441
CutMesh::Property_map< EI, IntersectingElement > EdgeShapeMap
Definition CutSurface.cpp:183
CutAOIs create_cut_area_of_interests(const CutMesh &mesh, const ExPolygons &shapes, FaceTypeMap &face_type_map)
Create areas from mesh surface.
Definition CutSurface.cpp:1649
CutMesh::Property_map< FI, IntersectingElement > FaceShapeMap
Definition CutSurface.cpp:184
const std::string face_type_map_name
Definition CutSurface.cpp:211
const std::string face_shape_map_name
Definition CutSurface.cpp:191
CutMesh::Property_map< FI, FaceType > FaceTypeMap
Definition CutSurface.cpp:210
const std::string edge_shape_map_name
Definition CutSurface.cpp:190
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:1373
Track source of intersection Help for anotate inner and outer faces.
Definition CutSurface.cpp:1101

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, is_valid(), 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:

◆ cut_surface()

TriangleMesh priv::cut_surface ( DataBase input1,
const SurfaceVolumeData input2,
std::function< bool()>  was_canceled 
)
static

Cut surface into triangle mesh.

Parameters
input1(can't be const - cache of font)
input2SurfaceVolume data
was_canceledCheck to interupt execution
Returns
Extruded object from cuted surace
730{
731 ExPolygons shapes = create_shape(input1, was_canceled);
732 if (shapes.empty())
733 throw JobException(_u8L("Font doesn't have any shape for given text.").c_str());
734
735 if (was_canceled()) return {};
736
737 // Define alignment of text - left, right, center, top bottom, ....
738 BoundingBox bb = get_extents(shapes);
739 Point projection_center = bb.center();
740 for (ExPolygon &shape : shapes) shape.translate(-projection_center);
741 bb.translate(-projection_center);
742
743 const FontFile &ff = *input1.font_file.font_file;
744 const FontProp &fp = input1.text_configuration.style.prop;
745 double shape_scale = get_shape_scale(fp, ff);
746
747 const SurfaceVolumeData::ModelSources &sources = input2.sources;
748 const SurfaceVolumeData::ModelSource *biggest = nullptr;
749
750 size_t biggest_count = 0;
751 // convert index from (s)ources to (i)ndexed (t)riangle (s)ets
752 std::vector<size_t> s_to_itss(sources.size(), std::numeric_limits<size_t>::max());
753 std::vector<indexed_triangle_set> itss;
754 itss.reserve(sources.size());
755 for (const SurfaceVolumeData::ModelSource &s : sources) {
756 Transform3d mesh_tr_inv = s.tr.inverse();
757 Transform3d cut_projection_tr = mesh_tr_inv * input2.text_tr;
758 std::pair<float, float> z_range{0., 1.};
759 OrthoProject cut_projection = create_projection_for_cut(cut_projection_tr, shape_scale, z_range);
760 // copy only part of source model
761 indexed_triangle_set its = its_cut_AoI(s.mesh->its, bb, cut_projection);
762 if (its.indices.empty()) continue;
763 if (biggest_count < its.vertices.size()) {
764 biggest_count = its.vertices.size();
765 biggest = &s;
766 }
767 size_t source_index = &s - &sources.front();
768 size_t its_index = itss.size();
769 s_to_itss[source_index] = its_index;
770 itss.emplace_back(std::move(its));
771 }
772 if (itss.empty())
773 throw JobException(_u8L("There is no volume in projection direction.").c_str());
774
775 Transform3d tr_inv = biggest->tr.inverse();
776 Transform3d cut_projection_tr = tr_inv * input2.text_tr;
777
778 size_t itss_index = s_to_itss[biggest - &sources.front()];
779 BoundingBoxf3 mesh_bb = bounding_box(itss[itss_index]);
780 for (const SurfaceVolumeData::ModelSource &s : sources) {
781 size_t itss_index = s_to_itss[&s - &sources.front()];
782 if (itss_index == std::numeric_limits<size_t>::max()) continue;
783 if (&s == biggest)
784 continue;
785
786 Transform3d tr = s.tr * tr_inv;
787 bool fix_reflected = true;
788 indexed_triangle_set &its = itss[itss_index];
789 its_transform(its, tr, fix_reflected);
790 BoundingBoxf3 bb = bounding_box(its);
791 mesh_bb.merge(bb);
792 }
793
794 // tr_inv = transformation of mesh inverted
795 Transform3d emboss_tr = cut_projection_tr.inverse();
796 BoundingBoxf3 mesh_bb_tr = mesh_bb.transformed(emboss_tr);
797 std::pair<float, float> z_range{mesh_bb_tr.min.z(), mesh_bb_tr.max.z()};
798 OrthoProject cut_projection = create_projection_for_cut(cut_projection_tr, shape_scale, z_range);
799 float projection_ratio = (-z_range.first + safe_extension) / (z_range.second - z_range.first + 2 * safe_extension);
800
801 bool is_text_reflected = Slic3r::has_reflection(input2.text_tr);
802 if (is_text_reflected) {
803 // revert order of points in expolygons
804 // CW --> CCW
805 for (ExPolygon &shape : shapes) {
806 shape.contour.reverse();
807 for (Slic3r::Polygon &hole : shape.holes)
808 hole.reverse();
809 }
810 }
811
812 // Use CGAL to cut surface from triangle mesh
813 SurfaceCut cut = cut_surface(shapes, itss, cut_projection, projection_ratio);
814
815 if (is_text_reflected) {
816 for (SurfaceCut::Contour &c : cut.contours)
817 std::reverse(c.begin(), c.end());
818 for (Vec3i &t : cut.indices)
819 std::swap(t[0], t[1]);
820 }
821
822 if (cut.empty()) throw JobException(_u8L("There is no valid surface for text projection.").c_str());
823 if (was_canceled()) return {};
824
825 // !! Projection needs to transform cut
826 OrthoProject3d projection = create_emboss_projection(input2.is_outside, fp.emboss, emboss_tr, cut);
827 indexed_triangle_set new_its = cut2model(cut, projection);
828 assert(!new_its.empty());
829 if (was_canceled()) return {};
830 return TriangleMesh(std::move(new_its));
831}
#define _u8L(s)
macro used to mark string used at localization, return same string
Definition SLAPrint.cpp:29
void merge(const PointType &point)
Definition BoundingBox.cpp:105
PointType center() const
Definition BoundingBox.cpp:194
void translate(coordf_t x, coordf_t y)
Definition BoundingBox.hpp:41
BoundingBoxf3 transformed(const Transform3d &matrix) const
Definition BoundingBox.cpp:227
Definition EmbossJob.cpp:122
void swap(scoped_array< T > &a, scoped_array< T > &b)
Definition Memory.h:602
double get_shape_scale(const FontProp &fp, const FontFile &ff)
Calculate scale for glyph shape convert from shape points to mm.
Definition Emboss.cpp:1362
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:13
indexed_triangle_set cut2model(const SurfaceCut &cut, const Emboss::IProject3d &projection)
Create model from surface cuts by projection.
Definition CutSurface.cpp:615
indexed_triangle_set its_cut_AoI(const indexed_triangle_set &its, const BoundingBox &bb, const Emboss::IProjection &projection)
Separate (A)rea (o)f (I)nterest .. AoI from model NOTE: Only 2d filtration, do not filtrate by Z coor...
Definition CutSurface.cpp:857
bool has_reflection(const Transform3d &transform)
Check whether transformation matrix contains odd number of mirroring. NOTE: In code is sometime funct...
Definition Point.hpp:153
SurfaceCut cut_surface(const ExPolygons &shapes, const std::vector< indexed_triangle_set > &models, const Emboss::IProjection &projection, float projection_ratio)
Cut surface shape from models.
Definition CutSurface.cpp:520
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
static ExPolygons create_shape(DataBase &input, Fnc was_canceled)
static OrthoProject3d create_emboss_projection(bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut)
Create tranformation for emboss Cutted surface.
Definition EmbossJob.cpp:715
static OrthoProject create_projection_for_cut(Transform3d tr, double shape_scale, const std::pair< float, float > &z_range)
Create projection for cut surface from mesh.
Definition EmbossJob.cpp:690
keep information from file about font (store file data itself)
Definition Emboss.hpp:62
std::shared_ptr< const FontFile > font_file
Definition Emboss.hpp:107
FontProp prop
Definition TextConfiguration.hpp:168
float emboss
Definition TextConfiguration.hpp:30
TextConfiguration text_configuration
Definition EmbossJob.hpp:27
Slic3r::Emboss::FontFileWithCache font_file
Definition EmbossJob.hpp:25
std::vector< ModelSource > ModelSources
Definition EmbossJob.hpp:168
ModelSources sources
Definition EmbossJob.hpp:169
bool is_outside
Definition EmbossJob.hpp:159
Transform3d tr
Definition EmbossJob.hpp:166
Transform3d text_tr
Definition EmbossJob.hpp:154
std::vector< Index > Contour
Definition CutSurface.hpp:19
EmbossStyle style
Definition TextConfiguration.hpp:217
Definition stl.h:157

References _u8L, Slic3r::bounding_box(), Slic3r::BoundingBoxBase< PointType, APointsType >::center(), Slic3r::SurfaceCut::contours, create_emboss_projection(), create_projection_for_cut(), create_shape(), Slic3r::cut2model(), Slic3r::cut_surface(), Slic3r::FontProp::emboss, indexed_triangle_set::empty(), Slic3r::Emboss::FontFileWithCache::font_file, Slic3r::GUI::Emboss::DataBase::font_file, Slic3r::get_extents(), Slic3r::Emboss::get_shape_scale(), Slic3r::has_reflection(), indexed_triangle_set::indices, Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::inverse(), Slic3r::GUI::Emboss::SurfaceVolumeData::is_outside, Slic3r::its_cut_AoI(), its_transform(), Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::EmbossStyle::prop, Slic3r::MultiPoint::reverse(), safe_extension, Slic3r::GUI::Emboss::SurfaceVolumeData::sources, Slic3r::TextConfiguration::style, Slic3r::GUI::Emboss::DataBase::text_configuration, Slic3r::GUI::Emboss::SurfaceVolumeData::text_tr, Slic3r::GUI::Emboss::SurfaceVolumeData::ModelSource::tr, Slic3r::BoundingBoxf3::transformed(), Slic3r::BoundingBoxBase< PointType, APointsType >::translate(), and indexed_triangle_set::vertices.

Referenced by Slic3r::GUI::Emboss::CreateSurfaceVolumeJob::process(), and Slic3r::GUI::Emboss::UpdateSurfaceVolumeJob::process().

+ 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
3007{
3008 // IMPROVE: when models contain ONE mesh. It is only about convert cuts to patches
3009 // and reduce unneccessary triangles on contour
3010
3011 //Convert model_index and cut_index into one index
3012 priv::ModelCut2index m2i(cuts);
3013
3014 // create bounding boxes for cuts
3015 std::vector<BoundingBoxf3> bbs = create_bbs(cuts, cut_models);
3016 Trees trees(models.size());
3017
3018 SurfacePatches patches;
3019
3020 // queue of patches for one AOI (permanent with respect to for loop)
3021 SurfacePatchesEx aoi_patches;
3022
3023 //SurfacePatches aoi_patches;
3024 patches.reserve(m2i.get_count()); // only approximation of count
3025 size_t index = 0;
3026 for (size_t model_index = 0; model_index < models.size(); ++model_index) {
3027 CutAOIs &model_cuts = cuts[model_index];
3028 CutMesh &cut_model_ = cut_models[model_index];
3029 const CutMesh &cut_model = cut_model_;
3030 ReductionMap vertex_reduction_map = cut_model_.add_property_map<VI, VI>(vertex_reduction_map_name).first;
3031 create_reduce_map(vertex_reduction_map, cut_model);
3032
3033 for (size_t cut_index = 0; cut_index < model_cuts.size(); ++cut_index, ++index) {
3034 const CutAOI &cut = model_cuts[cut_index];
3035 SurfacePatchEx patch_ex;
3036 SurfacePatch &patch = patch_ex.patch;
3037 patch = create_surface_patch(cut.first, cut_model_, &vertex_reduction_map);
3038 patch.bb = bbs[index];
3039 patch.aoi_id = cut_index;
3040 patch.model_id = model_index;
3041 patch.shape_id = get_shape_point_index(cut, cut_model);
3042 patch.is_whole_aoi = true;
3043
3044 aoi_patches.clear();
3045 aoi_patches.push_back(patch_ex);
3046 for (size_t model_index2 = 0; model_index2 < models.size(); ++model_index2) {
3047 // do not clip source model itself
3048 if (model_index == model_index2) continue;
3049 for (SurfacePatchEx &patch_ex : aoi_patches) {
3050 SurfacePatch &patch = patch_ex.patch;
3051 if (has_bb_intersection(patch.bb, model_index2, bbs, m2i) &&
3052 clip_cut(patch, models[model_index2])){
3053 patch_ex.just_cliped = true;
3054 } else {
3055 // build tree on demand
3056 // NOTE: it is possible not neccessary: e.g. one model
3057 Tree &tree = trees[model_index2];
3058 if (tree.empty()) {
3059 const CutMesh &model = models[model_index2];
3060 auto f_range = faces(model);
3061 tree.insert(f_range.first, f_range.second, model);
3062 tree.build();
3063 }
3064 if (is_patch_inside_of_model(patch, tree, projection))
3065 patch_ex.full_inside = true;
3066 }
3067 }
3068 // erase full inside
3069 for (size_t i = aoi_patches.size(); i != 0; --i) {
3070 auto it = aoi_patches.begin() + (i - 1);
3071 if (it->full_inside) aoi_patches.erase(it);
3072 }
3073
3074 // detection of full AOI inside of model
3075 if (aoi_patches.empty()) break;
3076
3077 // divide cliped into parts
3078 size_t end = aoi_patches.size();
3079 for (size_t i = 0; i < end; ++i)
3080 if (aoi_patches[i].just_cliped)
3081 divide_patch(i, aoi_patches);
3082 }
3083
3084 if (!aoi_patches.empty()) {
3085 patches.reserve(patches.size() + aoi_patches.size());
3086 for (SurfacePatchEx &patch : aoi_patches)
3087 patches.push_back(std::move(patch.patch));
3088
3089 }
3090 }
3091 cut_model_.remove_property_map(vertex_reduction_map);
3092 }
3093
3094 // Also use outline inside of patches(made by non manifold models)
3095 // IMPROVE: trace outline from AOIs
3096 collect_open_edges(patches);
3097 return patches;
3098}
Keep conversion from VCutAOIs to Index and vice versa Model_index .. contour(or hole) poin from ExPol...
Definition CutSurface.cpp:323
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:1556
std::vector< SurfacePatchEx > SurfacePatchesEx
Definition CutSurface.cpp:2717
const std::string vertex_reduction_map_name
Definition CutSurface.cpp:221
size_t aoi_id
Definition CutSurface.cpp:300
bool full_inside
Definition CutSurface.cpp:2713
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:2881
void collect_open_edges(SurfacePatches &patches)
Fill outline in patches by open edges.
Definition CutSurface.cpp:2978
SurfacePatch patch
Definition CutSurface.cpp:2710
bool just_cliped
Definition CutSurface.cpp:2715
BoundingBoxf3 bb
Definition CutSurface.cpp:294
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:2917
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:2853
BBS create_bbs(const VCutAOIs &cuts, const CutMeshes &cut_models)
Create bounding boxes for AOI.
Definition CutSurface.cpp:2806
std::vector< SurfacePatch > SurfacePatches
Definition CutSurface.cpp:307
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:2531
size_t model_id
Definition CutSurface.cpp:298
CvtVI2VI ReductionMap
Definition CutSurface.cpp:220
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:2838
size_t shape_id
Definition CutSurface.cpp:302
bool is_whole_aoi
Definition CutSurface.cpp:305
SurfacePatch create_surface_patch(const std::vector< FI > &fis, CutMesh &mesh, const ReductionMap *rmap=nullptr)
Create patch.
Definition CutSurface.cpp:2607
Definition CutSurface.cpp:2709

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
2918{
2919 SurfacePatchEx &patch_ex = patches[i];
2920 assert(patch_ex.just_cliped);
2921 patch_ex.just_cliped = false;
2922
2923 SurfacePatch& patch = patch_ex.patch;
2924 CutMesh& cm = patch.mesh;
2925 assert(!cm.faces().empty());
2926 std::string patch_number_name = "f:patch_number";
2927 CutMesh::Property_map<FI,bool> is_processed = cm.add_property_map<FI, bool>(patch_number_name, false).first;
2928
2929 const CvtVI2VI& cvt_from = patch.mesh.property_map<VI, VI>(patch_source_name).first;
2930
2931 std::vector<FI> fis;
2932 fis.reserve(cm.faces().size());
2933
2934 SurfacePatchesEx new_patches;
2935 std::vector<FI> queue;
2936 // IMPROVE: create groups around triangles and than connect groups
2937 for (FI fi_cm : cm.faces()) {
2938 if (is_processed[fi_cm]) continue;
2939 assert(queue.empty());
2940 queue.push_back(fi_cm);
2941 if (!fis.empty()) {
2942 // Be carefull after push to patches,
2943 // all ref on patch contain non valid values
2944 SurfacePatchEx patch_ex_n;
2945 patch_ex_n.patch = separate_patch(fis, patch, cvt_from);
2946 patch_ex_n.patch.is_whole_aoi = false;
2947 new_patches.push_back(std::move(patch_ex_n));
2948 fis.clear();
2949 }
2950 // flood fill from triangle fi_cm to surrounding
2951 do {
2952 FI fi_q = queue.back();
2953 queue.pop_back();
2954 if (is_processed[fi_q]) continue;
2955 is_processed[fi_q] = true;
2956 fis.push_back(fi_q);
2957 HI hi = cm.halfedge(fi_q);
2958 for (FI fi : cm.faces_around_face(hi)) {
2959 // by documentation The face descriptor may be the null face, and it may be several times the same face descriptor.
2960 if (!fi.is_valid()) continue;
2961 if (!is_processed[fi]) queue.push_back(fi);
2962 }
2963 } while (!queue.empty());
2964 }
2965 cm.remove_property_map(is_processed);
2966 assert(!fis.empty());
2967
2968 // speed up for only one patch - no dividing (the most common)
2969 if (new_patches.empty()) {
2970 patch.bb = bounding_box(cm);
2971 patch.is_whole_aoi = false;
2972 } else {
2973 patch = separate_patch(fis, patch, cvt_from);
2974 patches.insert(patches.end(), new_patches.begin(), new_patches.end());
2975 }
2976}
SurfacePatch separate_patch(const std::vector< FI > &fis, SurfacePatch &patch, const CvtVI2VI &cvt_from)
Separate triangles singned with number n.
Definition CutSurface.cpp:2898

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_button()

bool priv::draw_button ( const IconManager::VIcons icons,
IconType  type,
bool  disable = false 
)
static
3411{
3412 return Slic3r::GUI::button(
3413 get_icon(icons, type, IconState::activable),
3414 get_icon(icons, type, IconState::hovered),
3415 get_icon(icons, type, IconState::disabled),
3416 disable
3417 );
3418}
bool button(const IconManager::Icon &activ, const IconManager::Icon &hover, const IconManager::Icon &disable, bool disabled)
Use icon as button with 3 states activ hover and disabled.
Definition IconManager.cpp:195
const IconManager::Icon & get_icon(const IconManager::VIcons &icons, IconType type, IconState state)
Definition GLGizmoEmboss.cpp:3409

References Slic3r::GUI::button(), and get_icon().

Referenced by Slic3r::GUI::GLGizmoEmboss::draw_bold_button(), Slic3r::GUI::GLGizmoEmboss::draw_delete_style_button(), Slic3r::GUI::GLGizmoEmboss::draw_font_list(), Slic3r::GUI::GLGizmoEmboss::draw_font_list_line(), Slic3r::GUI::GLGizmoEmboss::draw_italic_button(), Slic3r::GUI::GLGizmoEmboss::draw_style_add_button(), Slic3r::GUI::GLGizmoEmboss::draw_style_rename_button(), Slic3r::GUI::GLGizmoEmboss::draw_style_save_button(), and Slic3r::GUI::GLGizmoEmboss::revertible().

+ 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
141{
142 // Check input
143 if (!icon.is_valid()) {
144 assert(false);
145 BOOST_LOG_TRIVIAL(warning) << "Drawing invalid Icon.";
146 ImGui::Text("?");
147 return;
148 }
149
150 // size UV texture coors [in texture ratio]
151 ImVec2 size_uv(icon.br.x - icon.tl.x, icon.br.y - icon.tl.y);
152 ImVec2 one_px(size_uv.x / icon.size.x, size_uv.y / icon.size.y);
153
154 // use top left corner of first icon
155 IconManager::Icon icon_px = icon; // copy
156 // reduce uv coors to one pixel
157 icon_px.tl = ImVec2(0, 0);
158 icon_px.br = one_px;
159 draw(icon_px);
160}
IMGUI_API void Text(const char *fmt,...) IM_FMTARGS(1)
Definition imgui_widgets.cpp:260
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:164
Data for render texture with icon.
Definition IconManager.hpp:52
ImVec2 br
Definition IconManager.hpp:58
ImVec2 size
Definition IconManager.hpp:54
bool is_valid() const
Definition IconManager.hpp:62
ImVec2 tl
Definition IconManager.hpp:57

References Slic3r::GUI::IconManager::Icon::br, Slic3r::GUI::draw(), Slic3r::GUI::IconManager::Icon::is_valid(), Slic3r::GUI::IconManager::Icon::size, ImGui::Text(), Slic3r::GUI::IconManager::Icon::tl, ImVec2::x, and ImVec2::y.

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)
966 {
967 std::vector<Vec3d> points;
968 points.reserve(mesh.vertices().size());
969 // copy points
970 for (VI vi : mesh.vertices()) {
971 const P3 &p = mesh.point(vi);
972 points.emplace_back(p.x(), p.y(), p.z());
973 }
974 std::sort(points.begin(), points.end(), [](const Vec3d &v1, const Vec3d &v2) {
975 return v1.x() < v2.x() ||
976 (v1.x() == v2.x() &&
977 (v1.y() < v2.y() ||
978 (v1.y() == v2.y() &&
979 v1.z() < v2.z())));
980 });
981 // find first duplicit
982 auto it = std::adjacent_find(points.begin(), points.end());
983 return it != points.end();
984}

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 
)
2022{
2023 const Points& points = (id.polygon_index == 0) ?
2024 shape.contour.points :
2025 shape.holes[id.polygon_index - 1].points;
2026 // border of indexes for Polygon
2027 uint32_t first_index = index - id.point_index;
2028 uint32_t last_index = first_index + points.size();
2029
2030 uint32_t act_index = index;
2031 const ProjectionDistance* act_pd = &pd;
2032
2033 // Copy starting pd to result
2034 result[act_index] = pd;
2035
2036 auto exist_next = [&distances, &act_index, &act_pd, &result]
2037 (uint32_t nxt_index) {
2038 const ProjectionDistance *nxt_pd = get_closest_projection(distances[nxt_index] ,act_pd->distance);
2039 // exist next projection distance ?
2040 if (nxt_pd == nullptr) return false;
2041
2042 // check no rewrite result
2043 assert(result[nxt_index].aoi_index == std::numeric_limits<uint32_t>::max());
2044 // copy founded projection to result
2045 result[nxt_index] = *nxt_pd; // copy
2046
2047 // next
2048 act_index = nxt_index;
2049 act_pd = &result[nxt_index];
2050 return true;
2051 };
2052
2053 // last index in circle
2054 uint32_t finish_index = (index == first_index) ? (last_index - 1) :
2055 (index - 1);
2056 // Positive iteration inside polygon
2057 do {
2058 uint32_t nxt_index = act_index + 1;
2059 // close loop of indexes inside of contour
2060 if (nxt_index == last_index) nxt_index = first_index;
2061 // check that exist next
2062 if (!exist_next(nxt_index)) break;
2063 } while (act_index != finish_index);
2064
2065 // when all results for polygon are set no neccessary to iterate negative
2066 if (act_index == finish_index) return;
2067
2068 act_index = index;
2069 act_pd = &pd;
2070 // Negative iteration inside polygon
2071 do {
2072 uint32_t nxt_index = (act_index == first_index) ?
2073 (last_index-1) : (act_index - 1);
2074 // When iterate negative it must be split to parts
2075 // and can't iterate in circle
2076 assert(nxt_index != index);
2077 // check that exist next
2078 if (!exist_next(nxt_index)) break;
2079 } while (true);
2080}

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 
)
2089{
2090 uint32_t expolygons_index = s2i.cvt(start_index).expolygons_index;
2091 uint32_t first_shape_index = s2i.cvt({expolygons_index, 0, 0});
2092 do {
2093 fill_polygon_distances(*start_pd, start_index, s2i.cvt(start_index),result, shape, distances);
2094 // seaching only inside shape, return index of closed finished point
2095 auto find_close_finished_point = [&first_shape_index, &shape, &result]
2096 (const Point &p) -> ClosePoint {
2097 uint32_t index = first_shape_index;
2098 ClosePoint cp;
2099 auto check_finished_points = [&cp, &result, &index, &p]
2100 (const Points& pts) {
2101 for (const Point &p_ : pts) {
2102 // finished point with some distances
2103 if (result[index].aoi_index == std::numeric_limits<uint32_t>::max()) {
2104 ++index;
2105 continue;
2106 }
2107 float distance = calc_size_sq(p_ - p);
2108 if (cp.dist_sq > distance) {
2109 cp.dist_sq = distance;
2110 cp.index = index;
2111 }
2112 ++index;
2113 }
2114 };
2115 check_finished_points(shape.contour.points);
2116 for (const Polygon &h : shape.holes)
2117 check_finished_points(h.points);
2118 return cp;
2119 };
2120
2121 // find next closest pair of points
2122 // (finished + unfinished) in ExPolygon
2123 start_index = std::numeric_limits<uint32_t>::max(); // unfinished_index
2124 uint32_t finished_index = std::numeric_limits<uint32_t>::max();
2125 float dist_sq = std::numeric_limits<float>::max();
2126
2127 // first index in shape
2128 uint32_t index = first_shape_index;
2129 auto check_unfinished_points = [&index, &result, &distances, &find_close_finished_point, &dist_sq, &start_index, &finished_index]
2130 (const Points& pts) {
2131 for (const Point &p : pts) {
2132 // try find unfinished
2133 if (result[index].aoi_index !=
2134 std::numeric_limits<uint32_t>::max() ||
2135 distances[index].empty()) {
2136 ++index;
2137 continue;
2138 }
2139 ClosePoint cp = find_close_finished_point(p);
2140 if (dist_sq > cp.dist_sq) {
2141 dist_sq = cp.dist_sq;
2142 start_index = index;
2143 finished_index = cp.index;
2144 }
2145 ++index;
2146 }
2147 };
2148 // for each unfinished points
2149 check_unfinished_points(shape.contour.points);
2150 for (const Polygon &h : shape.holes)
2151 check_unfinished_points(h.points);
2152 } while (start_index != std::numeric_limits<uint32_t>::max());
2153}
float calc_size_sq(const Point &p)
Definition CutSurface.cpp:1821

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

Referenced by choose_best_distance().

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

◆ finalize()

bool priv::finalize ( bool  canceled,
std::exception_ptr &  eptr,
const DataBase input 
)
static
845{
846 // doesn't care about exception when process was canceled by user
847 if (canceled || input.cancel->load()) {
848 eptr = nullptr;
849 return false;
850 }
851 return !process(eptr);
852}

References input(), and process().

Referenced by Slic3r::GUI::Emboss::CreateVolumeJob::finalize(), Slic3r::GUI::Emboss::CreateObjectJob::finalize(), Slic3r::GUI::Emboss::UpdateJob::finalize(), Slic3r::GUI::Emboss::CreateSurfaceVolumeJob::finalize(), and Slic3r::GUI::Emboss::UpdateSurfaceVolumeJob::finalize().

+ 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 
)
2160{
2161 // result
2162 ClosePoint cp;
2163 // for all finished points
2164 for (uint32_t shape_index = 0; shape_index < shapes.size(); ++shape_index) {
2165 if (!finished_shapes[shape_index]) continue;
2166 const ExPolygon &shape = shapes[shape_index];
2167 uint32_t index = s2i.cvt({shape_index, 0, 0});
2168 auto find_close_point_in_points = [&p, &cp, &index, &result]
2169 (const Points &pts){
2170 for (const Point &p_ : pts) {
2171 // Exist result (is finished) ?
2172 if (result[index].aoi_index ==
2173 std::numeric_limits<uint32_t>::max()) {
2174 ++index;
2175 continue;
2176 }
2177 float distance_sq = calc_size_sq(p - p_);
2178 if (cp.dist_sq > distance_sq) {
2179 cp.dist_sq = distance_sq;
2180 cp.index = index;
2181 }
2182 ++index;
2183 }
2184 };
2185 find_close_point_in_points(shape.contour.points);
2186 // shape could be inside of another shape's hole
2187 for (const Polygon& h:shape.holes)
2188 find_close_point_in_points(h.points);
2189 }
2190 return cp;
2191}
Definition CutSurface.cpp:1782

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 
)
1914{
1915 SearchData sd = create_search_data(shapes, mask);
1916 size_t line_idx = std::numeric_limits<size_t>::max();
1917 Vec2d hit_point;
1918 Vec2d p_d = p.cast<double>();
1919 [[maybe_unused]] double distance_sq =
1921 sd.lines, sd.tree, p_d, line_idx, hit_point);
1922 assert(distance_sq > 0);
1923
1924 // IMPROVE: one could use line ratio to find closest point
1925 return get_closest_point_index(sd, line_idx, hit_point, shapes, s2i);
1926}
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:207
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:1862
SearchData create_search_data(const ExPolygons &shapes, const std::vector< bool > &mask)
Definition CutSurface.cpp:1826

References create_search_data(), get_closest_point_index(), priv::SearchData::lines, 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 
)
1933{
1934 assert(mask.size() == s2i.get_count());
1935 assert(done_shapes.size() == shapes.size());
1936 std::vector<bool> unfinished_mask = mask; // copy
1937
1938 size_t index = 0;
1939 for (size_t shape_index = 0; shape_index < shapes.size(); shape_index++) {
1940 size_t count = count_points(shapes[shape_index]);
1941 if (done_shapes[shape_index]) {
1942 for (size_t i = 0; i < count; ++i, ++index)
1943 unfinished_mask[index] = false;
1944 } else {
1945 index += count;
1946 }
1947 }
1948 assert(index == s2i.get_count());
1949 SearchData sd = create_search_data(shapes, unfinished_mask);
1950
1951 struct ClosestPair
1952 {
1953 size_t finish_idx = std::numeric_limits<size_t>::max();
1954 size_t unfinished_line_idx = std::numeric_limits<size_t>::max();
1955 Vec2d hit_point = Vec2d();
1956 double distance_sq = std::numeric_limits<double>::max();
1957 } cp;
1958
1959 index = 0;
1960 for (size_t shape_index = 0; shape_index < shapes.size(); shape_index++) {
1961 const ExPolygon shape = shapes[shape_index];
1962 if (!done_shapes[shape_index]) {
1963 index += count_points(shape);
1964 continue;
1965 }
1966
1967 auto search_in_polygon = [&index, &cp, &sd, &mask](const Polygon& polygon) {
1968 for (size_t i = 0; i < polygon.size(); ++i, ++index) {
1969 if (mask[index] == false) continue;
1970 Vec2d p_d = polygon[i].cast<double>();
1971 size_t line_idx = std::numeric_limits<size_t>::max();
1972 Vec2d hit_point;
1974 sd.lines, sd.tree, p_d, line_idx, hit_point, cp.distance_sq);
1975 if (distance_sq < 0 ||
1976 distance_sq >= cp.distance_sq) continue;
1977 assert(line_idx < sd.lines.size());
1978 cp.distance_sq = distance_sq;
1979 cp.unfinished_line_idx = line_idx;
1980 cp.hit_point = hit_point;
1981 cp.finish_idx = index;
1982 }
1983 };
1984 search_in_polygon(shape.contour);
1985 for (const Polygon& hole: shape.holes)
1986 search_in_polygon(hole);
1987 }
1988 assert(index == s2i.get_count());
1989 // check that exists result
1990 if (cp.finish_idx == std::numeric_limits<size_t>::max()) {
1991 return std::make_pair(std::numeric_limits<size_t>::max(),
1992 std::numeric_limits<size_t>::max());
1993 }
1994
1995 size_t unfinished_idx = get_closest_point_index(sd, cp.unfinished_line_idx, cp.hit_point, shapes, s2i);
1996 return std::make_pair(cp.finish_idx, unfinished_idx);
1997}
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:51

References Slic3r::ExPolygon::contour, 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:

◆ find_closest_volume()

void priv::find_closest_volume ( const Selection selection,
const Vec2d screen_center,
const Camera camera,
const ModelObjectPtrs objects,
Vec2d closest_center,
const GLVolume **  closest_volume 
)
static

Find volume in selected object with closest convex hull to screen center. Return.

Parameters
selectionDefine where to search for closest
screen_centerCanvas center(dependent on camera settings)
objectsActual objects
closest_centerOUT: coordinate of controid of closest volume
closest_volumeOUT: closest volume
3555{
3556 assert(closest_center != nullptr);
3557 assert(closest_volume != nullptr);
3558 assert(*closest_volume == nullptr);
3559 const Selection::IndicesList &indices = selection.get_volume_idxs();
3560 assert(!indices.empty()); // no selected volume
3561 if (indices.empty()) return;
3562
3563 double center_sq_distance = std::numeric_limits<double>::max();
3564 for (unsigned int id : indices) {
3565 const GLVolume *gl_volume = selection.get_volume(id);
3566 const ModelVolume *volume = get_model_volume(*gl_volume, objects);
3567 if (volume == nullptr || !volume->is_model_part()) continue;
3568 Slic3r::Polygon hull = CameraUtils::create_hull2d(camera, *gl_volume);
3569 Vec2d c = hull.centroid().cast<double>();
3570 Vec2d d = c - screen_center;
3571 bool is_bigger_x = std::fabs(d.x()) > std::fabs(d.y());
3572 if ((is_bigger_x && d.x() * d.x() > center_sq_distance) ||
3573 (!is_bigger_x && d.y() * d.y() > center_sq_distance)) continue;
3574
3575 double distance = d.squaredNorm();
3576 if (center_sq_distance < distance) continue;
3577 center_sq_distance = distance;
3578 *closest_center = c;
3579 *closest_volume = gl_volume;
3580 }
3581}
Point centroid() const
Definition Polygon.cpp:138

References Slic3r::Polygon::centroid(), Slic3r::GUI::CameraUtils::create_hull2d(), Slic3r::GUI::get_model_volume(), Slic3r::GUI::Selection::get_volume(), and Slic3r::GUI::Selection::get_volume_idxs().

Referenced by Slic3r::GUI::GLGizmoEmboss::create_volume().

+ 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
1443{
1444 std::vector<FI> process;
1445 // guess count of connected not constrained triangles
1446 size_t guess_size = 128;
1447 process.reserve(guess_size);
1448
1449 // check if neighbor(one of three in triangle) has type inside
1450 auto has_inside_neighbor = [&mesh, &face_type_map](FI fi) {
1451 HI hi = mesh.halfedge(fi);
1452 HI hi_end = hi;
1453 auto exist_next = [&hi, &hi_end, &mesh]() -> bool {
1454 hi = mesh.next(hi);
1455 return hi != hi_end;
1456 };
1457 // loop over 3 half edges of face
1458 do {
1459 HI hi_opposite = mesh.opposite(hi);
1460 // open edge doesn't have opposit half edge
1461 if (!hi_opposite.is_valid()) continue;
1462 FI fi_opposite = mesh.face(hi_opposite);
1463 if (!fi_opposite.is_valid()) continue;
1464 if (face_type_map[fi_opposite] == FaceType::inside) return true;
1465 } while (exist_next());
1466 return false;
1467 };
1468
1469 for (FI fi : mesh.faces()) {
1470 FaceType type = face_type_map[fi];
1471 if (type != FaceType::not_constrained) continue;
1472 if (!has_inside_neighbor(fi)) continue;
1473 assert(process.empty());
1474 process.push_back(fi);
1475 //store(mesh, face_type_map, DEBUG_OUTPUT_DIR + "progress.off");
1476
1477 while (!process.empty()) {
1478 FI process_fi = process.back();
1479 process.pop_back();
1480 // Do not fill twice
1481 FaceType& process_type = face_type_map[process_fi];
1482 if (process_type == FaceType::inside) continue;
1483 process_type = FaceType::inside;
1484
1485 // check neighbor triangle
1486 HI hi = mesh.halfedge(process_fi);
1487 HI hi_end = hi;
1488 auto exist_next = [&hi, &hi_end, &mesh]() -> bool {
1489 hi = mesh.next(hi);
1490 return hi != hi_end;
1491 };
1492 do {
1493 HI hi_opposite = mesh.opposite(hi);
1494 // open edge doesn't have opposit half edge
1495 if (!hi_opposite.is_valid()) continue;
1496 FI fi_opposite = mesh.face(hi_opposite);
1497 if (!fi_opposite.is_valid()) continue;
1498 FaceType type_opposite = face_type_map[fi_opposite];
1499 if (type_opposite == FaceType::not_constrained)
1500 process.push_back(fi_opposite);
1501 } while (exist_next());
1502 }
1503 }
1504}

References inside, not_constrained, and process().

Referenced by cut_from_model().

+ Here is the call graph for this function:
+ 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 
)
1867{
1868 const Linef &line = sd.lines[line_idx];
1869 Vec2d dir = line.a - line.b;
1870 Vec2d dir_abs = dir.cwiseAbs();
1871 // use x coordinate
1872 int i = (dir_abs.x() > dir_abs.y())? 0 :1;
1873
1874 bool use_index = abs(line.a[i] - hit_point[i]) >
1875 abs(line.b[i] - hit_point[i]);
1876 size_t point_index = sd.cvt[line_idx];
1877
1878 // Lambda used only for check result
1879 [[maybe_unused]] auto is_same = [&s2i, &shapes]
1880 (const Vec2d &p, size_t i) -> bool {
1881 auto id = s2i.cvt(i);
1882 const ExPolygon &shape = shapes[id.expolygons_index];
1883 const Polygon &poly = (id.polygon_index == 0) ?
1884 shape.contour :
1885 shape.holes[id.polygon_index - 1];
1886 Vec2i p_ = p.cast<int>();
1887 return p_ == poly[id.point_index];
1888 };
1889
1890 if (use_index) {
1891 assert(is_same(line.b, point_index));
1892 return point_index;
1893 }
1894 auto id = s2i.cvt(point_index);
1895 if (id.point_index != 0) {
1896 assert(is_same(line.a, point_index - 1));
1897 return point_index - 1;
1898 }
1899 const ExPolygon &shape = shapes[id.expolygons_index];
1900 size_t count_polygon_points = (id.polygon_index == 0) ?
1901 shape.contour.size() :
1902 shape.holes[id.polygon_index - 1].size();
1903 size_t prev_point_index = point_index + (count_polygon_points - 1);
1904 assert(is_same(line.a, prev_point_index));
1905 // return previous point index
1906 return prev_point_index;
1907}
Definition Line.hpp:243
Vec2d b
Definition Line.hpp:249
Vec2d a
Definition Line.hpp:248
size_t size() const
Definition MultiPoint.hpp:39
bool is_same(const Range< ItA > &A, const Range< ItB > &B)
Definition CSGMeshCopy.hpp:55

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 
)
2001{
2002 // minimal distance
2003 float min_d = std::numeric_limits<float>::max();
2004 const ProjectionDistance *min_pd = nullptr;
2005 for (const ProjectionDistance &pd : distance) {
2006 float d = std::fabs(pd.distance - wanted_distance);
2007 // There should be limit for maximal distance
2008 if (min_d > d) {
2009 min_d = d;
2010 min_pd = &pd;
2011 }
2012 }
2013 return min_pd;
2014}

Referenced by choose_best_distance(), and fill_polygon_distances().

+ Here is the caller graph for this function:

◆ get_glyph() [1/2]

std::optional< Glyph > priv::get_glyph ( const stbtt_fontinfo font_info,
int  unicode_letter,
float  flatness 
)
725{
726 int glyph_index = stbtt_FindGlyphIndex(&font_info, unicode_letter);
727 if (glyph_index == 0) {
728 //wchar_t wchar = static_cast<wchar_t>(unicode_letter);
729 //<< "Character unicode letter ("
730 //<< "decimal value = " << std::dec << unicode_letter << ", "
731 //<< "hexadecimal value = U+" << std::hex << unicode_letter << std::dec << ", "
732 //<< "wchar value = " << wchar
733 //<< ") is NOT defined inside of the font. \n";
734 return {};
735 }
736
737 Glyph glyph;
738 stbtt_GetGlyphHMetrics(&font_info, glyph_index, &glyph.advance_width, &glyph.left_side_bearing);
739
740 stbtt_vertex *vertices;
741 int num_verts = stbtt_GetGlyphShape(&font_info, glyph_index, &vertices);
742 if (num_verts <= 0) return glyph; // no shape
743 ScopeGuard sg1([&vertices]() { free(vertices); });
744
745 int *contour_lengths = NULL;
746 int num_countour_int = 0;
747 stbtt__point *points = stbtt_FlattenCurves(vertices, num_verts,
748 flatness, &contour_lengths, &num_countour_int, font_info.userdata);
749 if (!points) return glyph; // no valid flattening
750 ScopeGuard sg2([&contour_lengths, &points]() {
751 free(contour_lengths);
752 free(points);
753 });
754
755 size_t num_contour = static_cast<size_t>(num_countour_int);
756 Polygons glyph_polygons;
757 glyph_polygons.reserve(num_contour);
758 size_t pi = 0; // point index
759 for (size_t ci = 0; ci < num_contour; ++ci) {
760 int length = contour_lengths[ci];
761 // check minimal length for triangle
762 if (length < 4) {
763 // weird font
764 pi+=length;
765 continue;
766 }
767 // last point is first point
768 --length;
769 Points pts;
770 pts.reserve(length);
771 for (int i = 0; i < length; ++i)
772 pts.emplace_back(to_point(points[pi++]));
773
774 // last point is first point --> closed contour
775 assert(pts.front() == to_point(points[pi]));
776 ++pi;
777
778 // change outer cw to ccw and inner ccw to cw order
779 std::reverse(pts.begin(), pts.end());
780 glyph_polygons.emplace_back(pts);
781 }
782 if (!glyph_polygons.empty())
783 glyph.shape = Emboss::heal_shape(glyph_polygons);
784 return glyph;
785}
Definition Utils.hpp:282
void free(void *)
STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices)
void * userdata
Definition imstb_truetype.h:716
STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
Definition imstb_truetype.h:825
ExPolygons heal_shape(const Polygons &shape)
Fix duplicit points and self intersections in polygons. Also try to reduce amount of points and remov...
Definition Emboss.cpp:532
int advance_width
Definition Emboss.hpp:51
ExPolygons shape
Definition Emboss.hpp:48
int left_side_bearing
Definition Emboss.hpp:51
Definition Emboss.hpp:45
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:15
double length(const Points &pts)
Definition MultiPoint.hpp:116
const double pi
Definition agg_basics.h:268
Point to_point(const stbtt__point &point)
Definition Emboss.cpp:859

References Slic3r::Emboss::Glyph::advance_width, free(), Slic3r::Emboss::heal_shape(), Slic3r::Emboss::Glyph::left_side_bearing, Slic3r::length(), Slic3r::Emboss::Glyph::shape, stbtt_FindGlyphIndex(), stbtt_GetGlyphHMetrics(), stbtt_GetGlyphShape(), to_point(), and stbtt_fontinfo::userdata.

Referenced by get_glyph(), Slic3r::Emboss::letter2glyph(), and Slic3r::Emboss::text2shapes().

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

◆ get_glyph() [2/2]

const Glyph * priv::get_glyph ( int  unicode,
const FontFile font,
const FontProp font_prop,
Glyphs cache,
fontinfo_opt font_info_opt 
)
793{
794 // TODO: Use resolution by printer configuration, or add it into FontProp
795 const float RESOLUTION = 0.0125f; // [in mm]
796 auto glyph_item = cache.find(unicode);
797 if (glyph_item != cache.end()) return &glyph_item->second;
798
799 unsigned int font_index = font_prop.collection_number.value_or(0);
800 if (!is_valid(font, font_index)) return nullptr;
801
802 if (!font_info_opt.has_value()) {
803
804 font_info_opt = priv::load_font_info(font.data->data(), font_index);
805 // can load font info?
806 if (!font_info_opt.has_value()) return nullptr;
807 }
808
809 float flatness = font.infos[font_index].ascent * RESOLUTION / font_prop.size_in_mm;
810
811 // Fix for very small flatness because it create huge amount of points from curve
812 if (flatness < RESOLUTION) flatness = RESOLUTION;
813
814 std::optional<Glyph> glyph_opt =
815 priv::get_glyph(*font_info_opt, unicode, flatness);
816
817 // IMPROVE: multiple loadig glyph without data
818 // has definition inside of font?
819 if (!glyph_opt.has_value()) return nullptr;
820
821 if (font_prop.char_gap.has_value())
822 glyph_opt->advance_width += *font_prop.char_gap;
823
824 // scale glyph size
825 glyph_opt->advance_width =
826 static_cast<int>(glyph_opt->advance_width / SHAPE_SCALE);
827 glyph_opt->left_side_bearing =
828 static_cast<int>(glyph_opt->left_side_bearing / SHAPE_SCALE);
829
830 if (!glyph_opt->shape.empty()) {
831 if (font_prop.boldness.has_value()) {
832 float delta = *font_prop.boldness / SHAPE_SCALE /
833 font_prop.size_in_mm;
834 glyph_opt->shape = Slic3r::union_ex(offset_ex(glyph_opt->shape, delta));
835 }
836 if (font_prop.skew.has_value()) {
837 double ratio = *font_prop.skew;
838 auto skew = [&ratio](Polygon &polygon) {
839 for (Slic3r::Point &p : polygon.points)
840 p.x() += static_cast<Point::coord_type>(std::round(p.y() * ratio));
841 };
842 for (ExPolygon &expolygon : glyph_opt->shape) {
843 skew(expolygon.contour);
844 for (Polygon &hole : expolygon.holes) skew(hole);
845 }
846 }
847 }
848 auto it = cache.insert({unicode, std::move(*glyph_opt)});
849 assert(it.second);
850 return &it.first->second;
851}
EIGEN_DEVICE_FUNC const RoundReturnType round() const
Definition ArrayCwiseUnaryOps.h:374
const Scalar & y
Definition MathFunctions.h:552
static constexpr double SHAPE_SCALE
Definition Emboss.hpp:23
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, ClipperLib::PolyFillType fill_type)
Definition ClipperUtils.cpp:774
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:421
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297
std::optional< Glyph > get_glyph(const stbtt_fontinfo &font_info, int unicode_letter, float flatness)
Definition Emboss.cpp:724
fontinfo_opt load_font_info(const unsigned char *data, unsigned int index=0)
Definition Emboss.cpp:240
std::vector< Info > infos
Definition Emboss.hpp:78
std::unique_ptr< std::vector< unsigned char > > data
Definition Emboss.hpp:67
std::optional< float > boldness
Definition TextConfiguration.hpp:41
std::optional< int > char_gap
Definition TextConfiguration.hpp:23
std::optional< float > skew
Definition TextConfiguration.hpp:46
std::optional< unsigned int > collection_number
Definition TextConfiguration.hpp:61
float size_in_mm
Definition TextConfiguration.hpp:85

References Slic3r::FontProp::boldness, Slic3r::FontProp::char_gap, Slic3r::FontProp::collection_number, Slic3r::Emboss::FontFile::data, get_glyph(), Slic3r::Emboss::FontFile::infos, is_valid(), load_font_info(), Slic3r::offset_ex(), Slic3r::Emboss::SHAPE_SCALE, Slic3r::FontProp::size_in_mm, Slic3r::FontProp::skew, and Slic3r::union_ex().

+ Here is the call graph for this function:

◆ get_icon()

const IconManager::Icon & priv::get_icon ( const IconManager::VIcons icons,
IconType  type,
IconState  state 
)
3409{ return *icons[(unsigned) type][(unsigned) state]; }

Referenced by Slic3r::GUI::GLGizmoEmboss::draw_advanced(), Slic3r::GUI::GLGizmoEmboss::draw_bold_button(), draw_button(), Slic3r::GUI::GLGizmoEmboss::draw_italic_button(), and Slic3r::GUI::GLGizmoEmboss::draw_text_input().

+ 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
2882{
2883 // map is created during intersection by corefine visitor
2884 const VertexShapeMap &vert_shape_map = model.property_map<VI, const IntersectingElement *>(vert_shape_map_name).first;
2885 // for each half edge of outline
2886 for (HI hi : cut.second) {
2887 VI vi = model.source(hi);
2888 const IntersectingElement *ie = vert_shape_map[vi];
2889 if (ie == nullptr) continue;
2890 assert(ie->shape_point_index != std::numeric_limits<uint32_t>::max());
2891 return ie->shape_point_index;
2892 }
2893 // can't found any intersecting element in cut
2894 assert(false);
2895 return 0;
2896}

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
121 {
122 static std::vector<std::pair<int, bool>> color = {std::make_pair(0, false)};
123 static std::vector<std::pair<int, bool>> white = {std::make_pair(1, false)};
124 static std::vector<std::pair<int, bool>> gray = {std::make_pair(2, false)};
125 static std::vector<std::pair<int, bool>> color_wite_gray = {
126 std::make_pair(1, false), // Activable
127 std::make_pair(0, false), // Hovered
128 std::make_pair(2, false) // Disabled
129 };
130
131 switch (type) {
132 case IconManager::RasterType::color: return color;
133 case IconManager::RasterType::white_only_data: return white;
134 case IconManager::RasterType::gray_only_data: return gray;
135 case IconManager::RasterType::color_wite_gray: return color_wite_gray;
136 default: return color;
137 }
138}

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:

◆ get_volume()

ModelVolume * priv::get_volume ( ModelObjectPtrs objects,
const ObjectID volume_id 
)
static

Select Volume from objects.

Parameters
objectsAll objects in scene
volume_idIdentifier of volume in object
Returns
Pointer to volume when exist otherwise nullptr
683{
684 for (ModelObject *obj : objects)
685 for (ModelVolume *vol : obj->volumes)
686 if (vol->id() == volume_id) return vol;
687 return nullptr;
688};

◆ 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
2842{
2843 const auto&offsets = m2i.get_offsets();
2844 // for cut index with model_index2
2845 size_t start = offsets[model_index];
2846 size_t next = model_index + 1;
2847 size_t end = (next < offsets.size()) ? offsets[next] : m2i.get_count();
2848 for (size_t bb_index = start; bb_index < end; bb_index++)
2849 if (bb.intersects(bbs[bb_index])) return true;
2850 return false;
2851}
bool intersects(const BoundingBox3Base< PointType > &other) const
Definition BoundingBox.hpp:139
const std::vector< uint32_t > & get_offsets() const
Definition CutSurface.cpp:333

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
39{
40 for (const auto &c : constrained) {
41 auto key = std::make_pair(c.second, c.first);
42 auto it = std::lower_bound(constrained.begin(), constrained.end(),
43 key);
44 if (it != constrained.end() && *it == key) return true;
45 }
46 return false;
47}

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
59{
60 Lines lines;
61 lines.reserve(constrained_half_edges.size());
62 for (const auto &he : constrained_half_edges)
63 lines.emplace_back(points[he.first], points[he.second]);
64 return !intersection_points(lines).empty();
65}
Pointfs intersection_points(const Lines &lines)
Definition IntersectionPoints.cpp:146
std::vector< Line > Lines
Definition Line.hpp:17

References Slic3r::intersection_points().

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

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

◆ heal_dupl_inter()

bool priv::heal_dupl_inter ( ExPolygons shape,
unsigned  max_iteration 
)
590{
591 if (shape.empty()) return true;
592
593 // create loop permanent memory
595 Points intersections;
596 while (--max_iteration) {
598 Pointfs intersections_f = intersection_points(shape);
599
600 // convert intersections into Points
601 assert(intersections.empty());
602 intersections.reserve(intersections_f.size());
603 std::transform(intersections_f.begin(), intersections_f.end(), std::back_inserter(intersections),
604 [](const Vec2d &p) { return Point(std::floor(p.x()), std::floor(p.y())); });
605
606 // intersections should be unique poits
607 std::sort(intersections.begin(), intersections.end());
608 auto it = std::unique(intersections.begin(), intersections.end());
609 intersections.erase(it, intersections.end());
610
611 Points duplicates = collect_duplicates(to_points(shape));
612 // duplicates are already uniqua and sorted
613
614 // Check whether shape is already healed
615 if (intersections.empty() && duplicates.empty())
616 return true;
617
618 assert(holes.empty());
619 holes.reserve(intersections.size() + duplicates.size());
620
621 remove_spikes_in_duplicates(shape, duplicates);
622
623 // Fix self intersection in result by subtracting hole 2x2
624 for (const Point &p : intersections) {
626 hole.translate(p);
627 holes.push_back(hole);
628 }
629
630 // Fix duplicit points by hole 3x3 around duplicit point
631 for (const Point &p : duplicates) {
633 hole.translate(p);
634 holes.push_back(hole);
635 }
636
637 shape = Slic3r::diff_ex(shape, holes, ApplySafetyOffset::Yes);
638
639 // prepare for next loop
640 holes.clear();
641 intersections.clear();
642 }
643
644 //priv::visualize_heal("C:/data/temp/heal.svg", shape);
645 assert(false);
646 shape = {priv::create_bounding_rect(shape)};
647 return false;
648}
void translate(double x, double y)
Definition MultiPoint.hpp:29
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:726
Points collect_duplicates(Points pts)
Definition Point.cpp:69
Points to_points(const ExPolygons &src)
Definition ExPolygon.hpp:196
const Points pts_2x2({Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)})
void remove_spikes_in_duplicates(ExPolygons &expolygons, const Points &duplicates)
Definition Emboss.cpp:201
ExPolygon create_bounding_rect(const ExPolygons &shape)
Definition Emboss.cpp:682
const Points pts_3x3({Point(-1, -1), Point(1, -1), Point(1, 1), Point(-1, 1)})
bool remove_same_neighbor(Polygon &points)
Definition Emboss.cpp:275

References Slic3r::collect_duplicates(), create_bounding_rect(), Slic3r::diff_ex(), Slic3r::holes(), Slic3r::intersection_points(), pts_2x2(), pts_3x3(), remove_same_neighbor(), remove_spikes_in_duplicates(), Slic3r::to_points(), and Slic3r::MultiPoint::translate().

Referenced by Slic3r::Emboss::heal_shape().

+ 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
25 {
26 const Points &pts = polygon.points;
27 uint32_t size = static_cast<uint32_t>(pts.size());
28 uint32_t prev_index = offset + size - 1;
29 for (uint32_t i = 0; i < size; ++i) {
30 uint32_t index = offset + i;
31 edges.push_back({prev_index, index});
32 prev_index = index;
33 }
34 offset += size;
35}

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
10 {
11 const Points &pts = polygon.points;
12 uint32_t size = static_cast<uint32_t>(pts.size());
13 uint32_t last_index = offset + size - 1;
14 uint32_t prev_index = changes[last_index];
15 for (uint32_t i = 0; i < size; ++i) {
16 uint32_t index = changes[offset + i];
17 // when duplicit points are neighbor
18 if (prev_index == index) continue;
19 edges.push_back({prev_index, index});
20 prev_index = index;
21 }
22 offset += size;
23}

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 Vec3i 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
713 {
714 for (size_t side = 0; side < 4; side++) {
715 bool result = true;
716 for (auto vi : t) {
717 if (!is_on_sides[vi][side]) {
718 result = false;
719 break;
720 }
721 }
722 if (result) return true;
723 }
724 return false;
725}

◆ 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
1312{
1313 VI vi_from = mesh.source(hi);
1314 VI vi_to = mesh.target(hi);
1315 // This face has a constrained edge.
1316 const IntersectingElement &shape_from = *vertex_shape_map[vi_from];
1317 const IntersectingElement &shape_to = *vertex_shape_map[vi_to];
1318 assert(shape_from.shape_point_index != std::numeric_limits<uint32_t>::max());
1319 assert(shape_from.attr != (unsigned char) IntersectingElement::Type::undefined);
1320 assert(shape_to.shape_point_index != std::numeric_limits<uint32_t>::max());
1321 assert(shape_to.attr != (unsigned char) IntersectingElement::Type::undefined);
1322
1323 // index into contour
1324 uint32_t i_from = shape_from.shape_point_index;
1325 uint32_t i_to = shape_to.shape_point_index;
1326 IntersectingElement::Type type_from = shape_from.get_type();
1327 IntersectingElement::Type type_to = shape_to.get_type();
1328 if (i_from == i_to && type_from == type_to) {
1329 // intersecting element must be face
1330 assert(type_from == IntersectingElement::Type::face_1 ||
1331 type_from == IntersectingElement::Type::face_2);
1332
1333 // count of vertices is twice as count of point in the contour
1334 uint32_t i = i_from * 2;
1335 // j is next contour point in vertices
1336 uint32_t j = i + 2;
1337 if (shape_from.is_last()) {
1338 ExPolygonsIndex point_id = shape2index.cvt(i_from);
1339 point_id.point_index = 0;
1340 j = shape2index.cvt(point_id)*2;
1341 }
1342
1343 // opposit point(in triangle face) to edge
1344 const P3 &p = mesh.point(mesh.target(mesh.next(hi)));
1345
1346 // abc is source triangle face
1347 CGAL::Sign abcp = type_from == IntersectingElement::Type::face_1 ?
1348 CGAL::orientation(shape_mesh.point(VI(i)),
1349 shape_mesh.point(VI(i + 1)),
1350 shape_mesh.point(VI(j)), p) :
1351 // type_from == IntersectingElement::Type::face_2
1352 CGAL::orientation(shape_mesh.point(VI(j)),
1353 shape_mesh.point(VI(i + 1)),
1354 shape_mesh.point(VI(j + 1)), p);
1355 return abcp == CGAL::POSITIVE;
1356 } else if (i_from < i_to || (i_from == i_to && type_from < type_to)) {
1357 bool is_last = shape_to.is_last() && shape_from.is_first();
1358 // check continuity of indicies
1359 assert(i_from == i_to || is_last || (i_from + 1) == i_to);
1360 return !is_last;
1361 } else {
1362 assert(i_from > i_to || (i_from == i_to && type_from > type_to));
1363 bool is_last = shape_to.is_first() && shape_from.is_last();
1364 // check continuity of indicies
1365 assert(i_from == i_to || is_last || (i_to + 1) == i_from);
1366 return is_last;
1367 }
1368
1369 assert(false);
1370 return false;
1371}
uint32_t point_index
Definition ExPolygonsIndex.hpp:22
bool is_first() const
Definition CutSurface.cpp:178
bool is_last() const
Definition CutSurface.cpp:179

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
706{
707 const Vec3d& p = point_normal.first;
708 const Vec3d& n = point_normal.second;
709 double signed_distance = (v - p).dot(n);
710 return signed_distance > 1e-5;
711};
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:143

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
3114{
3115 // NonInterupted contour is without other point and contain all from shape
3116 const VertexShapeMap &vert_shape_map = mesh.property_map<VI, const IntersectingElement*>(vert_shape_map_name).first;
3117 for (HI hi : cutAOI.second) {
3118 const IntersectingElement *ie_s = vert_shape_map[mesh.source(hi)];
3119 const IntersectingElement *ie_t = vert_shape_map[mesh.target(hi)];
3120 if (ie_s == nullptr || ie_t == nullptr)
3121 return false;
3122
3123 assert(ie_s->attr != (unsigned char) IntersectingElement::Type::undefined);
3124 assert(ie_t->attr != (unsigned char) IntersectingElement::Type::undefined);
3125
3126 // check if it is neighbor indices
3127 uint32_t i_s = ie_s->shape_point_index;
3128 uint32_t i_t = ie_t->shape_point_index;
3129 assert(i_s != std::numeric_limits<uint32_t>::max());
3130 assert(i_t != std::numeric_limits<uint32_t>::max());
3131 if (i_s == std::numeric_limits<uint32_t>::max() ||
3132 i_t == std::numeric_limits<uint32_t>::max())
3133 return false;
3134
3135 // made by same index
3136 if (i_s == i_t) continue;
3137
3138 // order from source to target
3139 if (i_s > i_t) {
3140 std::swap(i_s, i_t);
3141 std::swap(ie_s, ie_t);
3142 }
3143 // Must be after fix order !!
3144 bool is_last_polygon_segment = ie_s->is_first() && ie_t->is_last();
3145 if (is_last_polygon_segment) {
3146 std::swap(i_s, i_t);
3147 std::swap(ie_s, ie_t);
3148 }
3149
3150 // Is continous indices
3151 if (!is_last_polygon_segment &&
3152 (ie_s->is_last() || (i_s + 1) != i_t))
3153 return false;
3154
3155 IntersectingElement::Type t_s = ie_s->get_type();
3156 IntersectingElement::Type t_t = ie_t->get_type();
3157 if (t_s == IntersectingElement::Type::undefined ||
3158 t_t == IntersectingElement::Type::undefined)
3159 return false;
3160
3161 // next segment must start with edge intersection
3162 if (t_t != IntersectingElement::Type::edge_1)
3163 return false;
3164
3165 // After face1 must be edge2 or face2
3166 if (t_s == IntersectingElement::Type::face_1)
3167 return false;
3168 }
3169
3170 // When all open edges are on contour than there is NO holes is shape
3171 auto is_open = [&mesh](HI hi)->bool {
3172 HI opposite = mesh.opposite(hi);
3173 return !mesh.face(opposite).is_valid();
3174 };
3175
3176 std::vector<HI> opens; // copy
3177 opens.reserve(cutAOI.second.size());
3178 for (HI hi : cutAOI.second) // from lower to bigger
3179 if (is_open(hi)) opens.push_back(hi);
3180 std::sort(opens.begin(), opens.end());
3181
3182 for (FI fi: cutAOI.first) {
3183 HI face_hi = mesh.halfedge(fi);
3184 for (HI hi : mesh.halfedges_around_face(face_hi)) {
3185 if (!is_open(hi)) continue;
3186 // open edge
3187 auto lb = std::lower_bound(opens.begin(), opens.end(), hi);
3188 if (lb == opens.end() || *lb != hi)
3189 return false; // not in contour
3190 }
3191 }
3192 return true;
3193}
ColorRGB opposite(const ColorRGB &color)
Definition Color.cpp:265

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
3104{
3105 if (!patch.is_whole_aoi) return false;
3106 return is_over_whole_expoly(cutAOIs[patch.model_id][patch.aoi_id],
3107 shapes[patch.shape_id],
3108 meshes[patch.model_id]);
3109}
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:3111

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
2856{
2857 // TODO: Solve model with hole in projection direction !!!
2858 const P3 &a = patch.mesh.point(VI(0));
2859 Vec3d a_ = to_vec3d(a);
2860 Vec3d b_ = projection.project(a_);
2861 P3 b(b_.x(), b_.y(), b_.z());
2862
2863 Ray ray_query(a, b);
2864 size_t count = tree.number_of_intersected_primitives(ray_query);
2865 bool is_in = (count % 2) == 1;
2866
2867 // try opposit direction result should be same, otherwise open model is used
2868 //Vec3f c_ = a_ - (b_ - a_); // opposit direction
2869 //P3 c(c_.x(), c_.y(), c_.z());
2870 //Ray ray_query2(a, b);
2871 //size_t count2 = tree.number_of_intersected_primitives(ray_query2);
2872 //bool is_in2 = (count2 % 2) == 1;
2873 assert(((tree.number_of_intersected_primitives(
2874 Ray(a, P3(2 * a.x() - b.x(),
2875 2 * a.y() - b.y(),
2876 2 * a.z() - b.z()))) %
2877 2) == 1) == is_in);
2878 return is_in;
2879}
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:2731

References 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_text_empty()

static bool priv::is_text_empty ( const std::string &  text)
static
1286{ return text.empty() || text.find_first_not_of(" \n\t\r") == std::string::npos; }

Referenced by Slic3r::GUI::GLGizmoEmboss::close(), and Slic3r::GUI::GLGizmoEmboss::draw_text_input().

+ Here is the caller graph for this function:

◆ is_unique()

bool priv::is_unique ( const Points points)
inline
49 {
50 Points pts = points; // copy
51 std::sort(pts.begin(), pts.end());
52 auto it = std::adjacent_find(pts.begin(), pts.end());
53 return it == pts.end();
54}

Referenced by Slic3r::GUI::GLGizmoEmboss::draw_style_rename_popup(), Slic3r::GUI::GLGizmoEmboss::draw_style_save_as_popup(), and Slic3r::Triangulation::triangulate().

+ Here is the caller graph for this function:

◆ is_valid()

bool priv::is_valid ( const FontFile font,
unsigned int  index 
)
233 {
234 if (font.data == nullptr) return false;
235 if (font.data->empty()) return false;
236 if (index >= font.infos.size()) return false;
237 return true;
238}

References Slic3r::Emboss::FontFile::data, and Slic3r::Emboss::FontFile::infos.

Referenced by Slic3r::Emboss::create_range_text(), cut_from_model(), get_glyph(), priv::Visitor::intersection_point_detected(), Slic3r::Emboss::letter2glyph(), and Slic3r::Emboss::text2shapes().

+ Here is the caller graph for this function:

◆ load_font_info()

fontinfo_opt priv::load_font_info ( const unsigned char *  data,
unsigned int  index = 0 
)
242{
243 int font_offset = stbtt_GetFontOffsetForIndex(data, index);
244 if (font_offset < 0) {
245 assert(false);
246 // "Font index(" << index << ") doesn't exist.";
247 return {};
248 }
249 stbtt_fontinfo font_info;
250 if (stbtt_InitFont(&font_info, data, font_offset) == 0) {
251 // Can't initialize font.
252 assert(false);
253 return {};
254 }
255 return font_info;
256}
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
Definition imstb_truetype.h:715

References stbtt_GetFontOffsetForIndex(), and stbtt_InitFont().

Referenced by Slic3r::Emboss::create_font_file(), Slic3r::Emboss::create_range_text(), get_glyph(), Slic3r::Emboss::is_italic(), and Slic3r::Emboss::letter2glyph().

+ Here is the call graph for this function:
+ 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
3570{
3571 SurfaceCut result;
3572 for (SurfacePatch &patch : patches) {
3573 size_t index = &patch - &patches.front();
3574 if (!mask[index]) continue;
3575 append(result, patch2cut(patch));
3576 }
3577 return result;
3578}
SurfaceCut patch2cut(SurfacePatch &patch)
Convert patch to indexed_triangle_set.
Definition CutSurface.cpp:3496

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
3497{
3498 CutMesh &mesh = patch.mesh;
3499
3500 std::string convert_map_name = "v:convert";
3501 CutMesh::Property_map<VI, SurfaceCut::Index> convert_map =
3502 mesh.add_property_map<VI, SurfaceCut::Index>(convert_map_name).first;
3503
3504 size_t indices_size = mesh.faces().size();
3505 size_t vertices_size = mesh.vertices().size();
3506
3507 SurfaceCut sc;
3508 sc.indices.reserve(indices_size);
3509 sc.vertices.reserve(vertices_size);
3510 for (VI vi : mesh.vertices()) {
3511 // vi order is is not sorted
3512 // assert(vi.idx() == sc.vertices.size());
3513 // vi is not continous
3514 // assert(vi.idx() < vertices_size);
3515 convert_map[vi] = sc.vertices.size();
3516 const P3 &p = mesh.point(vi);
3517 sc.vertices.emplace_back(p.x(), p.y(), p.z());
3518 }
3519
3520 for (FI fi : mesh.faces()) {
3521 HI hi = mesh.halfedge(fi);
3522 assert(mesh.next(hi).is_valid());
3523 assert(mesh.next(mesh.next(hi)).is_valid());
3524 // Is fi triangle?
3525 assert(mesh.next(mesh.next(mesh.next(hi))) == hi);
3526
3527 // triangle indicies
3528 Vec3i ti;
3529 size_t i = 0;
3530 for (VI vi : { mesh.source(hi),
3531 mesh.target(hi),
3532 mesh.target(mesh.next(hi))})
3533 ti[i++] = convert_map[vi];
3534 sc.indices.push_back(ti);
3535 }
3536
3537 sc.contours.reserve(patch.loops.size());
3538 for (const Loop &loop : patch.loops) {
3539 sc.contours.push_back({});
3540 std::vector<SurfaceCut::Index> &contour = sc.contours.back();
3541 contour.reserve(loop.size());
3542 for (VI vi : loop) contour.push_back(convert_map[vi]);
3543 }
3544
3545 // Not neccessary, clean and free memory
3546 mesh.remove_property_map(convert_map);
3547 return sc;
3548}
const Polygon & contour(const ExPolygon &p)
Definition AGGRaster.hpp:21
IGL_INLINE void loop(const int n_verts, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< SType > &S, Eigen::PlainObjectBase< DerivedNF > &NF)
Definition loop.cpp:21
Loops loops
Definition CutSurface.cpp:291

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

Referenced by merge_patches().

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

◆ polygons2model_duplicit()

indexed_triangle_set priv::polygons2model_duplicit ( const ExPolygons shape2d,
const IProjection projection,
const Points points,
const Points duplicits 
)
1448{
1449 // CW order of triangle indices
1450 std::vector<uint32_t> changes = Triangulation::create_changes(points, duplicits);
1451 std::vector<Vec3i> shape_triangles = Triangulation::triangulate(shape2d, points, changes);
1452 uint32_t count_point = *std::max_element(changes.begin(), changes.end()) + 1;
1453
1454 indexed_triangle_set result;
1455 result.vertices.reserve(2 * count_point);
1456 std::vector<Vec3f> &front_points = result.vertices;
1457 std::vector<Vec3f> back_points;
1458 back_points.reserve(count_point);
1459
1460 uint32_t max_index = std::numeric_limits<uint32_t>::max();
1461 for (uint32_t i = 0; i < changes.size(); ++i) {
1462 uint32_t index = changes[i];
1463 if (max_index != std::numeric_limits<uint32_t>::max() &&
1464 index <= max_index) continue; // duplicit point
1465 assert(index == max_index + 1);
1466 assert(front_points.size() == index);
1467 assert(back_points.size() == index);
1468 max_index = index;
1469 const Point &p = points[i];
1470 auto p2 = projection.create_front_back(p);
1471 front_points.push_back(p2.first.cast<float>());
1472 back_points.push_back(p2.second.cast<float>());
1473 }
1474 assert(max_index+1 == count_point);
1475
1476 // insert back points, front are already in
1477 result.vertices.insert(result.vertices.end(),
1478 std::make_move_iterator(back_points.begin()),
1479 std::make_move_iterator(back_points.end()));
1480
1481 result.indices.reserve(shape_triangles.size() * 2 + points.size() * 2);
1482 // top triangles - change to CCW
1483 for (const Vec3i &t : shape_triangles)
1484 result.indices.emplace_back(t.x(), t.z(), t.y());
1485 // bottom triangles - use CW
1486 for (const Vec3i &t : shape_triangles)
1487 result.indices.emplace_back(t.x() + count_point, t.y() + count_point,
1488 t.z() + count_point);
1489
1490 // quads around - zig zag by triangles
1491 size_t polygon_offset = 0;
1492 auto add_quads = [&polygon_offset, &result, count_point, &changes]
1493 (const Polygon &polygon) {
1494 uint32_t polygon_points = polygon.points.size();
1495 // previous index
1496 uint32_t prev = changes[polygon_offset + polygon_points - 1];
1497 for (uint32_t p = 0; p < polygon_points; ++p) {
1498 uint32_t index = changes[polygon_offset + p];
1499 if (prev == index) continue;
1500 add_quad(prev, index, result, count_point);
1501 prev = index;
1502 }
1503 polygon_offset += polygon_points;
1504 };
1505
1506 for (const ExPolygon &expolygon : shape2d) {
1507 add_quads(expolygon.contour);
1508 for (const Polygon &hole : expolygon.holes) add_quads(hole);
1509 }
1510 return result;
1511}
virtual std::pair< Vec3d, Vec3d > create_front_back(const Point &p) const =0
convert 2d point to 3d points
static Indices triangulate(const Points &points, const HalfEdges &half_edges)
Connect points by triangulation to create filled surface by triangles Input points have to be unique ...
Definition Triangulation.cpp:85
static Changes create_changes(const Points &points, const Points &duplicits)
Create conversion map from original index into new with respect of duplicit point.
Definition Triangulation.cpp:303

References add_quad(), Slic3r::Triangulation::create_changes(), Slic3r::Emboss::IProjection::create_front_back(), indexed_triangle_set::indices, Slic3r::Triangulation::triangulate(), and indexed_triangle_set::vertices.

Referenced by Slic3r::Emboss::polygons2model().

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

◆ polygons2model_unique()

indexed_triangle_set priv::polygons2model_unique ( const ExPolygons shape2d,
const IProjection projection,
const Points points 
)
1389{
1390 // CW order of triangle indices
1391 std::vector<Vec3i> shape_triangles=Triangulation::triangulate(shape2d, points);
1392 uint32_t count_point = points.size();
1393
1394 indexed_triangle_set result;
1395 result.vertices.reserve(2 * count_point);
1396 std::vector<Vec3f> &front_points = result.vertices; // alias
1397 std::vector<Vec3f> back_points;
1398 back_points.reserve(count_point);
1399
1400 for (const Point &p : points) {
1401 auto p2 = projection.create_front_back(p);
1402 front_points.push_back(p2.first.cast<float>());
1403 back_points.push_back(p2.second.cast<float>());
1404 }
1405
1406 // insert back points, front are already in
1407 result.vertices.insert(result.vertices.end(),
1408 std::make_move_iterator(back_points.begin()),
1409 std::make_move_iterator(back_points.end()));
1410 result.indices.reserve(shape_triangles.size() * 2 + points.size() * 2);
1411 // top triangles - change to CCW
1412 for (const Vec3i &t : shape_triangles)
1413 result.indices.emplace_back(t.x(), t.z(), t.y());
1414 // bottom triangles - use CW
1415 for (const Vec3i &t : shape_triangles)
1416 result.indices.emplace_back(t.x() + count_point,
1417 t.y() + count_point,
1418 t.z() + count_point);
1419
1420 // quads around - zig zag by triangles
1421 size_t polygon_offset = 0;
1422 auto add_quads = [&polygon_offset,&result, &count_point]
1423 (const Polygon& polygon) {
1424 uint32_t polygon_points = polygon.points.size();
1425 // previous index
1426 uint32_t prev = polygon_offset + polygon_points - 1;
1427 for (uint32_t p = 0; p < polygon_points; ++p) {
1428 uint32_t index = polygon_offset + p;
1429 add_quad(prev, index, result, count_point);
1430 prev = index;
1431 }
1432 polygon_offset += polygon_points;
1433 };
1434
1435 for (const ExPolygon &expolygon : shape2d) {
1436 add_quads(expolygon.contour);
1437 for (const Polygon &hole : expolygon.holes) add_quads(hole);
1438 }
1439
1440 return result;
1441}

References add_quad(), Slic3r::Emboss::IProjection::create_front_back(), indexed_triangle_set::indices, Slic3r::Triangulation::triangulate(), and indexed_triangle_set::vertices.

Referenced by Slic3r::Emboss::polygons2model().

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

◆ process()

bool priv::process ( std::exception_ptr &  eptr)
static
833 {
834 if (!eptr) return false;
835 try {
836 std::rethrow_exception(eptr);
837 } catch (priv::JobException &e) {
838 create_message(e.what());
839 eptr = nullptr;
840 }
841 return true;
842}

References create_message().

Referenced by collect_surface_data(), create_cut_area_of_interests(), finalize(), and flood_fill_inner().

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

◆ pts_2x2()

const Points priv::pts_2x2 ( {Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)}  )

Referenced by heal_dupl_inter(), and remove_self_intersections().

+ Here is the caller graph for this function:

◆ pts_3x3()

const Points priv::pts_3x3 ( {Point(-1, -1), Point(1, -1), Point(1, 1), Point(-1, 1)}  )

Referenced by heal_dupl_inter(), and Slic3r::Emboss::heal_shape().

+ Here is the caller graph for this function:

◆ remove_bad() [1/2]

void priv::remove_bad ( ExPolygons expolygons)
265 {
266 expolygons.erase(
267 std::remove_if(expolygons.begin(), expolygons.end(),
268 [](const ExPolygon &p) { return p.contour.size() < 3; }),
269 expolygons.end());
270
271 for (ExPolygon &expolygon : expolygons)
272 remove_bad(expolygon.holes);
273}
void remove_bad(Polygons &polygons)
Definition Emboss.cpp:258

References remove_bad().

+ Here is the call graph for this function:

◆ remove_bad() [2/2]

void priv::remove_bad ( Polygons polygons)
258 {
259 polygons.erase(
260 std::remove_if(polygons.begin(), polygons.end(),
261 [](const Polygon &p) { return p.size() < 3; }),
262 polygons.end());
263}

Referenced by remove_bad(), and remove_spikes_in_duplicates().

+ Here is the caller graph for this function:

◆ remove_same_neighbor() [1/3]

bool priv::remove_same_neighbor ( ExPolygons expolygons)
307 {
308 if(expolygons.empty()) return false;
309 bool remove_from_holes = false;
310 bool remove_from_contour = false;
311 for (ExPolygon &expoly : expolygons) {
312 remove_from_contour |= remove_same_neighbor(expoly.contour);
313 remove_from_holes |= remove_same_neighbor(expoly.holes);
314 }
315 // Removing of expolygons without contour
316 if (remove_from_contour)
317 expolygons.erase(
318 std::remove_if(expolygons.begin(), expolygons.end(),
319 [](const ExPolygon &p) { return p.contour.points.size() <=2; }),
320 expolygons.end());
321 return remove_from_holes || remove_from_contour;
322}

References remove_same_neighbor().

+ Here is the call graph for this function:

◆ remove_same_neighbor() [2/3]

bool priv::remove_same_neighbor ( Slic3r::Polygon polygon)
276{
277 Points &points = polygon.points;
278 if (points.empty()) return false;
279 auto last = std::unique(points.begin(), points.end());
280
281 // remove first and last neighbor duplication
282 if (const Point& last_point = *(last - 1);
283 last_point == points.front()) {
284 --last;
285 }
286
287 // no duplicits
288 if (last == points.end()) return false;
289
290 points.erase(last, points.end());
291 return true;
292}

References Slic3r::MultiPoint::points.

Referenced by Slic3r::Emboss::divide_segments_for_close_point(), heal_dupl_inter(), remove_same_neighbor(), remove_same_neighbor(), and remove_self_intersections().

+ Here is the caller graph for this function:

◆ remove_same_neighbor() [3/3]

bool priv::remove_same_neighbor ( Polygons polygons)
294 {
295 if (polygons.empty()) return false;
296 bool exist = false;
297 for (Polygon& polygon : polygons)
298 exist |= remove_same_neighbor(polygon);
299 // remove empty polygons
300 polygons.erase(
301 std::remove_if(polygons.begin(), polygons.end(),
302 [](const Polygon &p) { return p.points.size() <= 2; }),
303 polygons.end());
304 return exist;
305}

References remove_same_neighbor().

+ Here is the call graph for this function:

◆ remove_self_intersections()

bool priv::remove_self_intersections ( ExPolygons shape,
unsigned  max_iteration = 10 
)
476 {
477 if (shape.empty())
478 return true;
479
480 Pointfs intersections_f = intersection_points(shape);
481 if (intersections_f.empty())
482 return true;
483
484 // create loop permanent memory
486 Points intersections;
487
488 while (--max_iteration) {
489 // convert intersections into Points
490 assert(intersections.empty());
491 intersections.reserve(intersections_f.size());
492 std::transform(intersections_f.begin(), intersections_f.end(), std::back_inserter(intersections),
493 [](const Vec2d &p) { return Point(std::floor(p.x()), std::floor(p.y())); });
494
495 // intersections should be unique poits
496 std::sort(intersections.begin(), intersections.end());
497 auto it = std::unique(intersections.begin(), intersections.end());
498 intersections.erase(it, intersections.end());
499
500 assert(holes.empty());
501 holes.reserve(intersections.size());
502
503 // Fix self intersection in result by subtracting hole 2x2
504 for (const Point &p : intersections) {
506 hole.translate(p);
507 holes.push_back(hole);
508 }
509 // Union of overlapped holes is not neccessary
510 // Clipper calculate winding number separately for each input parameter
511 // if (holes.size() > 1) holes = Slic3r::union_(holes);
512 shape = Slic3r::diff_ex(shape, holes, ApplySafetyOffset::Yes);
513
514 // TODO: find where diff ex could create same neighbor
516
517 // find new intersections made by diff_ex
518 intersections_f = intersection_points(shape);
519 if (intersections_f.empty())
520 return true;
521 else {
522 // clear permanent vectors
523 holes.clear();
524 intersections.clear();
525 }
526 }
527 assert(max_iteration == 0);
528 assert(!intersections_f.empty());
529 return false;
530}

References Slic3r::diff_ex(), Slic3r::holes(), Slic3r::intersection_points(), pts_2x2(), remove_same_neighbor(), and Slic3r::MultiPoint::translate().

+ Here is the call graph for this function:

◆ remove_small_islands()

void priv::remove_small_islands ( ExPolygons shape,
double  minimal_area 
)
706 {
707 if (expolygons.empty())
708 return;
709
710 // remove small expolygons contours
711 auto expoly_it = std::remove_if(expolygons.begin(), expolygons.end(),
712 [&minimal_area](const ExPolygon &p) { return p.contour.area() < minimal_area; });
713 expolygons.erase(expoly_it, expolygons.end());
714
715 // remove small holes in expolygons
716 for (ExPolygon &expoly : expolygons) {
717 Polygons& holes = expoly.holes;
718 auto it = std::remove_if(holes.begin(), holes.end(),
719 [&minimal_area](const Polygon &p) { return -p.area() < minimal_area; });
720 holes.erase(it, holes.end());
721 }
722}

References Slic3r::holes().

+ Here is the call graph for this function:

◆ remove_spikes_in_duplicates()

void priv::remove_spikes_in_duplicates ( ExPolygons expolygons,
const Points duplicates 
)
201 {
202
203 auto check = [](Polygon &polygon, const Point &d) -> bool {
204 double spike_bevel = 1 / SHAPE_SCALE;
205 double spike_length = 5.;
206 const static SpikeDesc sd(spike_bevel, spike_length);
207 Points& pts = polygon.points;
208 bool exist_remove = false;
209 for (size_t i = 0; i < pts.size(); i++) {
210 if (pts[i] != d)
211 continue;
212 exist_remove |= remove_when_spike(polygon, i, sd);
213 }
214 return exist_remove && pts.size() < 3;
215 };
216
217 bool exist_remove = false;
218 for (ExPolygon &expolygon : expolygons) {
219 BoundingBox bb(to_points(expolygon.contour));
220 for (const Point &d : duplicates) {
221 if (!bb.contains(d))
222 continue;
223 exist_remove |= check(expolygon.contour, d);
224 for (Polygon &hole : expolygon.holes)
225 exist_remove |= check(hole, d);
226 }
227 }
228
229 if (exist_remove)
230 remove_bad(expolygons);
231}
bool remove_when_spike(Polygon &polygon, size_t index, const SpikeDesc &spike_desc)
Definition Emboss.cpp:117
Definition Emboss.cpp:77

References check(), Slic3r::BoundingBoxBase< PointType, APointsType >::contains(), Slic3r::MultiPoint::points, remove_bad(), remove_when_spike(), Slic3r::Emboss::SHAPE_SCALE, and Slic3r::to_points().

Referenced by heal_dupl_inter().

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

◆ remove_when_spike()

bool priv::remove_when_spike ( Polygon polygon,
size_t  index,
const SpikeDesc spike_desc 
)
117 {
118
119 std::optional<Point> add;
120 bool do_erase = false;
121 Points &pts = polygon.points;
122 {
123 size_t pts_size = pts.size();
124 if (pts_size < 3)
125 return false;
126
127 const Point &a = (index == 0) ? pts.back() : pts[index - 1];
128 const Point &b = pts[index];
129 const Point &c = (index == (pts_size - 1)) ? pts.front() : pts[index + 1];
130
131 // calc sides
132 Vec2d ba = (a - b).cast<double>();
133 Vec2d bc = (c - b).cast<double>();
134
135 double dot_product = ba.dot(bc);
136
137 // sqrt together after multiplication save one sqrt
138 double ba_size_sq = ba.squaredNorm();
139 double bc_size_sq = bc.squaredNorm();
140 double norm = sqrt(ba_size_sq * bc_size_sq);
141 double cos_angle = dot_product / norm;
142
143 // small angle are around 1 --> cos(0) = 1
144 if (cos_angle < spike_desc.cos_angle)
145 return false; // not a spike
146
147 // has to be in range <-1, 1>
148 // Due to preccission of floating point number could be sligtly out of range
149 if (cos_angle > 1.)
150 cos_angle = 1.;
151 // if (cos_angle < -1.)
152 // cos_angle = -1.;
153
154 // Current Spike angle
155 double angle = acos(cos_angle);
156 double wanted_size = spike_desc.half_bevel / cos(angle / 2.);
157 double wanted_size_sq = wanted_size * wanted_size;
158
159 bool is_ba_short = ba_size_sq < wanted_size_sq;
160 bool is_bc_short = bc_size_sq < wanted_size_sq;
161
162 auto a_side = [&b, &ba, &ba_size_sq, &wanted_size]() -> Point {
163 Vec2d ba_norm = ba / sqrt(ba_size_sq);
164 return b + (wanted_size * ba_norm).cast<coord_t>();
165 };
166 auto c_side = [&b, &bc, &bc_size_sq, &wanted_size]() -> Point {
167 Vec2d bc_norm = bc / sqrt(bc_size_sq);
168 return b + (wanted_size * bc_norm).cast<coord_t>();
169 };
170
171 if (is_ba_short && is_bc_short) {
172 // remove short spike
173 do_erase = true;
174 } else if (is_ba_short) {
175 // move point B on C-side
176 pts[index] = c_side();
177 } else if (is_bc_short) {
178 // move point B on A-side
179 pts[index] = a_side();
180 } else {
181 // move point B on C-side and add point on A-side(left - before)
182 pts[index] = c_side();
183 add = a_side();
184 if (*add == pts[index]) {
185 // should be very rare, when SpikeDesc has small base
186 // will be fixed by remove B point
187 add.reset();
188 do_erase = true;
189 }
190 }
191 }
192 if (do_erase) {
193 pts.erase(pts.begin() + index);
194 return true;
195 }
196 if (add.has_value())
197 pts.insert(pts.begin() + index, *add);
198 return false;
199}
EIGEN_DEVICE_FUNC const AcosReturnType acos() const
Definition ArrayCwiseUnaryOps.h:262
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
Definition ArrayCwiseUnaryOps.h:152
EIGEN_DEVICE_FUNC const CosReturnType cos() const
Definition ArrayCwiseUnaryOps.h:202
double cos_angle
Definition Emboss.cpp:79
double half_bevel
Definition Emboss.cpp:82

References acos(), add, Slic3r::angle(), cos(), priv::SpikeDesc::cos_angle, priv::SpikeDesc::half_bevel, Slic3r::MultiPoint::points, and sqrt().

Referenced by remove_spikes_in_duplicates().

+ 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 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
shapesAll patches
Returns
Mask of used patch
3203{
3204 // extension to cover numerical mistake made by back projection patch from 3d to 2d
3205 const float extend_delta = 5.f / Emboss::SHAPE_SCALE; // [Font points scaled by Emboss::SHAPE_SCALE]
3206
3207 // vector of patches for shape
3208 std::vector<std::vector<uint32_t>> used_shapes_patches(shapes.size());
3209 std::vector<bool> in_distances(patches.size(), {false});
3210 for (const ProjectionDistance &d : best_distances) {
3211 // exist valid projection for shape point?
3212 if (d.patch_index == std::numeric_limits<uint32_t>::max()) continue;
3213 if (in_distances[d.patch_index]) continue;
3214 in_distances[d.patch_index] = true;
3215
3216 ExPolygonsIndex id = s2i.cvt(&d - &best_distances.front());
3217 used_shapes_patches[id.expolygons_index].push_back(d.patch_index);
3218 }
3219
3220 // vector of patches for shape
3221 std::vector<std::vector<uint32_t>> shapes_patches(shapes.size());
3222 for (const SurfacePatch &patch : patches)
3223 shapes_patches[patch.shape_id].push_back(&patch - &patches.front());
3224
3225#ifdef DEBUG_OUTPUT_DIR
3226 std::string store_dir = DEBUG_OUTPUT_DIR + "select_patches/";
3227 prepare_dir(store_dir);
3228#endif // DEBUG_OUTPUT_DIR
3229
3230 for (size_t shape_index = 0; shape_index < shapes.size(); shape_index++) {
3231 const ExPolygon &shape = shapes[shape_index];
3232 std::vector<uint32_t> &used_shape_patches = used_shapes_patches[shape_index];
3233 if (used_shape_patches.empty()) continue;
3234 // is used all exist patches?
3235 if (used_shapes_patches.size() == shapes_patches[shape_index].size()) continue;
3236 if (used_shape_patches.size() == 1) {
3237 uint32_t patch_index = used_shape_patches.front();
3238 const SurfacePatch &patch = patches[patch_index];
3239 if (is_over_whole_expoly(patch, shapes, cutAOIs, meshes)) continue;
3240 }
3241
3242 // only shapes containing multiple patches
3243 // or not full filled are back projected (hard processed)
3244
3245 // intersection of converted patches to 2d
3246 ExPolygons fill;
3247 fill.reserve(used_shape_patches.size());
3248
3249 // Heuristics to predict which patch to be used need average patch depth
3250 Vec2d used_patches_depth(std::numeric_limits<double>::max(), std::numeric_limits<double>::min());
3251 for (uint32_t patch_index : used_shape_patches) {
3252 ExPolygon patch_area = to_expoly(patches[patch_index], projection, used_patches_depth);
3253 //*/
3254 ExPolygons patch_areas = offset_ex(patch_area, extend_delta);
3255 fill.insert(fill.end(), patch_areas.begin(), patch_areas.end());
3256 /*/
3257 // without save extension
3258 fill.push_back(patch_area);
3259 //*/
3260 }
3261 fill = union_ex(fill);
3262
3263 // not cutted area of expolygon
3264 ExPolygons rest = diff_ex(ExPolygons{shape}, fill, ApplySafetyOffset::Yes);
3265#ifdef DEBUG_OUTPUT_DIR
3266 BoundingBox shape_bb = get_extents(shape);
3267 SVG svg(store_dir + "shape_" + std::to_string(shape_index) + ".svg", shape_bb);
3268 svg.draw(fill, "darkgreen");
3269 svg.draw(rest, "green");
3270#endif // DEBUG_OUTPUT_DIR
3271
3272 // already filled by multiple patches
3273 if (rest.empty()) continue;
3274
3275 // find patches overlaped rest area
3276 struct PatchShape{
3277 uint32_t patch_index;
3278 ExPolygon shape;
3280 double depth_range_center_distance; // always positive
3281 };
3282 using PatchShapes = std::vector<PatchShape>;
3283 PatchShapes patch_shapes;
3284
3285 double used_patches_depth_center = (used_patches_depth[0] + used_patches_depth[1]) / 2;
3286
3287 // sort used_patches for faster search
3288 std::sort(used_shape_patches.begin(), used_shape_patches.end());
3289 for (uint32_t patch_index : shapes_patches[shape_index]) {
3290 // check is patch already used
3291 auto it = std::lower_bound(used_shape_patches.begin(), used_shape_patches.end(), patch_index);
3292 if (it != used_shape_patches.end() && *it == patch_index) continue;
3293
3294 // Heuristics to predict which patch to be used need average patch depth
3295 Vec2d patche_depth_range(std::numeric_limits<double>::max(), std::numeric_limits<double>::min());
3296 ExPolygon patch_shape = to_expoly(patches[patch_index], projection, patche_depth_range);
3297 double depth_center = (patche_depth_range[0] + patche_depth_range[1]) / 2;
3298 double depth_range_center_distance = std::fabs(used_patches_depth_center - depth_center);
3299
3300 ExPolygons patch_intersection = intersection_ex(ExPolygons{patch_shape}, rest);
3301 if (patch_intersection.empty()) continue;
3302
3303 patch_shapes.push_back({patch_index, patch_shape, patch_intersection, depth_range_center_distance});
3304 }
3305
3306 // nothing to add
3307 if (patch_shapes.empty()) continue;
3308 // only one solution to add
3309 if (patch_shapes.size() == 1) {
3310 used_shape_patches.push_back(patch_shapes.front().patch_index);
3311 continue;
3312 }
3313
3314 // Idea: Get depth range of used patches and add patches in order by distance to used depth center
3315 std::sort(patch_shapes.begin(), patch_shapes.end(), [](const PatchShape &a, const PatchShape &b)
3316 { return a.depth_range_center_distance < b.depth_range_center_distance; });
3317
3318#ifdef DEBUG_OUTPUT_DIR
3319 for (size_t i = patch_shapes.size(); i > 0; --i) {
3320 const PatchShape &p = patch_shapes[i - 1];
3321 int gray_level = (i * 200) / patch_shapes.size();
3322 std::stringstream color;
3323 color << "#" << std::hex << std::setfill('0') << std::setw(2) << gray_level << gray_level << gray_level;
3324 svg.draw(p.shape, color.str());
3325 Point text_pos = get_extents(p.shape).center().cast<int>();
3326 svg.draw_text(text_pos, std::to_string(i-1).c_str(), "orange", std::ceil(shape_bb.size().x() / 20 * 0.000001));
3327 //svg.draw(p.intersection, color.str());
3328 }
3329#endif // DEBUG_OUTPUT_DIR
3330
3331 for (const PatchShape &patch : patch_shapes) {
3332 // Check when exist some place to fill
3333 ExPolygons patch_intersection = intersection_ex(patch.intersection, rest);
3334 if (patch_intersection.empty()) continue;
3335
3336 // Extend for sure
3337 ExPolygons intersection = offset_ex(patch.intersection, extend_delta);
3338 rest = diff_ex(rest, intersection, ApplySafetyOffset::Yes);
3339
3340 used_shape_patches.push_back(patch.patch_index);
3341 if (rest.empty()) break;
3342 }
3343
3344 // QUESTION: How to select which patch to use? How to sort them?
3345 // Now is used back projection distance from used patches
3346 //
3347 // Idealy by outline depth: (need ray cast into patches)
3348 // how to calc wanted depth - idealy by depth of outline help to overlap
3349 // how to calc patch depth - depth in place of outline position
3350 // Which outline to use between
3351
3352 }
3353
3354 std::vector<bool> result(patches.size(), {false});
3355 for (const std::vector<uint32_t> &patches: used_shapes_patches)
3356 for (uint32_t patch_index : patches) {
3357 assert(patch_index < result.size());
3358 // check only onece insertation of patch
3359 assert(!result[patch_index]);
3360 result[patch_index] = true;
3361 }
3362 return result;
3363}
Definition SVG.hpp:14
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:686
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:755
ExPolygon to_expoly(const SurfacePatch &patch, const Project &projection, Vec2d &depth_range)
Unproject points from loops and create expolygons.
Definition CutSurface.cpp:3473

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::Emboss::SHAPE_SCALE, to_expoly(), and Slic3r::union_ex().

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
2901{
2902 assert(patch.mesh.is_valid());
2903 SurfacePatch patch_new = create_surface_patch(fis, patch.mesh);
2904 patch_new.bb = bounding_box(patch_new.mesh);
2905 patch_new.aoi_id = patch.aoi_id;
2906 patch_new.model_id = patch.model_id;
2907 patch_new.shape_id = patch.shape_id;
2908 // fix cvt
2909 CvtVI2VI cvt = patch_new.mesh.property_map<VI, VI>(patch_source_name).first;
2910 for (VI &vi : cvt) {
2911 if (!vi.is_valid()) continue;
2912 vi = cvt_from[vi];
2913 }
2914 return patch_new;
2915}

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
1379{
1380 for (EI ei : mesh.edges()) {
1381 if (!ecm[ei]) continue;
1382 HI hi = mesh.halfedge(ei);
1383 FI fi = mesh.face(hi);
1384 bool is_inside = is_face_inside(hi, mesh, shape_mesh, vertex_shape_map, shape2index);
1385 face_type_map[fi] = is_inside ? FaceType::inside : FaceType::outside;
1386 HI hi_op = mesh.opposite(hi);
1387 assert(hi_op.is_valid());
1388 if (!hi_op.is_valid()) continue;
1389 FI fi_op = mesh.face(hi_op);
1390 assert(fi_op.is_valid());
1391 if (!fi_op.is_valid()) continue;
1392 face_type_map[fi_op] = (!is_inside) ? FaceType::inside : FaceType::outside;
1393 }
1394}
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:1307

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]
872{
873 assert(max_angle < 90. && max_angle > 89.);
874 assert(skip_indicies.size() == its.indices.size());
875 float threshold = static_cast<float>(cos(max_angle / 180. * M_PI));
876 for (const stl_triangle_vertex_indices& face : its.indices) {
877 size_t index = &face - &its.indices.front();
878 if (skip_indicies[index]) continue;
879 Vec3f n = its_face_normal(its, face);
880 const Vec3f& v = its.vertices[face[0]];
881 const Vec3d vd = v.cast<double>();
882 // Improve: For Orthogonal Projection it is same for each vertex
883 Vec3d projectedd = projection.project(vd);
884 Vec3f projected = projectedd.cast<float>();
885 Vec3f project_dir = projected - v;
886 project_dir.normalize();
887 float cos_alpha = project_dir.dot(n);
888 if (cos_alpha > threshold) continue;
889 skip_indicies[index] = true;
890 }
891}
#define M_PI
Definition ExtrusionSimulator.cpp:20
Vec3f its_face_normal(const indexed_triangle_set &its, const stl_triangle_vertex_indices face)
Definition TriangleMesh.hpp:311

References cos(), indexed_triangle_set::indices, Slic3r::its_face_normal(), M_PI, Slic3r::Emboss::IProject3d::project(), and indexed_triangle_set::vertices.

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
731{
732 assert(skip_indicies.size() == its.indices.size());
733 // 1`*----* 2`
734 // / 2 /|
735 // 1 *----* |
736 // | | * 3`
737 // | |/
738 // 0 *----* 3
740 std::array<std::pair<Vec3d, Vec3d>, 4> bb;
741 int index = 0;
742 for (Point v :
743 {shapes_bb.min, Point{shapes_bb.min.x(), shapes_bb.max.y()},
744 shapes_bb.max, Point{shapes_bb.max.x(), shapes_bb.min.y()}})
745 bb[index++] = projection.create_front_back(v);
746
747 // define planes to test
748 // 0 .. under
749 // 1 .. left
750 // 2 .. above
751 // 3 .. right
752 size_t prev_i = 3;
753 // plane is defined by point and normal
754 PointNormals point_normals;
755 for (size_t i = 0; i < 4; i++) {
756 const Vec3d &p1 = bb[i].first;
757 const Vec3d &p2 = bb[i].second;
758 const Vec3d &p3 = bb[prev_i].first;
759 prev_i = i;
760
761 Vec3d v1 = p2 - p1;
762 v1.normalize();
763 Vec3d v2 = p3 - p1;
764 v2.normalize();
765
766 Vec3d normal = v2.cross(v1);
767 normal.normalize();
768
769 point_normals[i] = {p1, normal};
770 }
771
772 // check that projection is not left handed
773 // Fix for reflected projection
774 if (is_out_of(point_normals[2].first, point_normals[0])) {
775 // projection is reflected so normals are reflected
776 for (auto &pn : point_normals)
777 pn.second *= -1;
778 }
779
780 // same meaning as point normal
781 IsOnSides is_on_sides(its.vertices.size(), {false,false,false,false});
782
783 // inspect all vertices when it is out of bounding box
784 tbb::parallel_for(tbb::blocked_range<size_t>(0, its.vertices.size()),
785 [&its, &point_normals, &is_on_sides](const tbb::blocked_range<size_t> &range) {
786 for (size_t i = range.begin(); i < range.end(); ++i) {
787 Vec3d v = its.vertices[i].cast<double>();
788 // under + above
789 for (int side : {0, 2}) {
790 if (is_out_of(v, point_normals[side])) {
791 is_on_sides[i][side] = true;
792 // when it is under it can't be above
793 break;
794 }
795 }
796 // left + right
797 for (int side : {1, 3}) {
798 if (is_out_of(v, point_normals[side])) {
799 is_on_sides[i][side] = true;
800 // when it is on left side it can't be on right
801 break;
802 }
803 }
804 }
805 }); // END parallel for
806
807 // inspect all triangles, when it is out of bounding box
808 tbb::parallel_for(tbb::blocked_range<size_t>(0, its.indices.size()),
809 [&its, &is_on_sides, &skip_indicies](const tbb::blocked_range<size_t> &range) {
810 for (size_t i = range.begin(); i < range.end(); ++i) {
811 if (is_all_on_one_side(its.indices[i], is_on_sides))
812 skip_indicies[i] = true;
813 }
814 }); // END parallel for
815}
Vec< 3, T > normal(const std::array< Vec< 3, T >, 3 > &tri)
Definition Rotfinder.cpp:43
auto range(Cont &&cont)
Definition libslic3r.h:356
std::vector< std::array< bool, 4 > > IsOnSides
Definition CutSurface.cpp:694
std::array< PointNormal, 4 > PointNormals
Definition CutSurface.cpp:683
bool is_out_of(const Vec3d &v, const PointNormal &point_normal)
Check.
Definition CutSurface.cpp:705

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

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:

◆ start_create_object_job()

void priv::start_create_object_job ( DataBase emboss_data,
const Vec2d coor 
)
static

Start job for add object with text into scene.

Parameters
emboss_dataDefine params of text
coorScreen coordinat, where to create new object laying on bed
3458{
3459 // start creation of new object
3460 Plater *plater = wxGetApp().plater();
3461 const Camera &camera = plater->get_camera();
3462 const Pointfs &bed_shape = plater->build_volume().bed_shape();
3463
3464 // can't create new object with distance from surface
3465 FontProp &prop = emboss_data.text_configuration.style.prop;
3466 if (prop.distance.has_value()) prop.distance.reset();
3467
3468 // can't create new object with using surface
3469 if (prop.use_surface)
3470 prop.use_surface = false;
3471
3472 // Transform3d volume_tr = priv::create_transformation_on_bed(mouse_pos, camera, bed_shape, prop.emboss / 2);
3473 DataCreateObject data{std::move(emboss_data), coor, camera, bed_shape};
3474 auto job = std::make_unique<CreateObjectJob>(std::move(data));
3475 Worker &worker = plater->get_ui_job_worker();
3476 queue_job(worker, std::move(job));
3477}
const std::vector< Vec2d > & bed_shape() const
Definition BuildVolume.hpp:40
const BuildVolume & build_volume() const
Definition Plater.cpp:7535
Worker & get_ui_job_worker()
Definition Plater.cpp:6070
const Camera & get_camera() const
Definition Plater.cpp:7512
Definition Worker.hpp:13
bool queue_job(Worker &w, ProcessFn fn, FinishFn finishfn)
Definition Worker.hpp:59
bool use_surface
Definition TextConfiguration.hpp:36
std::optional< float > distance
Definition TextConfiguration.hpp:51
Hold neccessary data to create ModelObject in job Object is placed on bed under screen coor OR to cen...
Definition EmbossJob.hpp:75

References Slic3r::BuildVolume::bed_shape(), Slic3r::GUI::Plater::build_volume(), Slic3r::FontProp::distance, Slic3r::GUI::Plater::get_camera(), Slic3r::GUI::Plater::get_ui_job_worker(), Slic3r::GUI::plater(), Slic3r::EmbossStyle::prop, Slic3r::GUI::queue_job(), Slic3r::TextConfiguration::style, Slic3r::GUI::Emboss::DataBase::text_configuration, and Slic3r::FontProp::use_surface.

Referenced by Slic3r::GUI::GLGizmoEmboss::create_volume(), and Slic3r::GUI::GLGizmoEmboss::create_volume().

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

◆ start_create_volume_job()

void priv::start_create_volume_job ( const ModelObject object,
const Transform3d  volume_trmat,
DataBase emboss_data,
ModelVolumeType  volume_type 
)
static

Start job for add new volume to object with given transformation.

Parameters
objectDefine where to add
volume_trmatVolume transformation
emboss_dataDefine text
volume_typeType of volume
3483{
3484 bool &use_surface = emboss_data.text_configuration.style.prop.use_surface;
3485 std::unique_ptr<GUI::Job> job;
3486 if (use_surface) {
3487 // Model to cut surface from.
3489 if (sources.empty()) {
3490 use_surface = false;
3491 } else {
3492 bool is_outside = volume_type == ModelVolumeType::MODEL_PART;
3493 // check that there is not unexpected volume type
3494 assert(is_outside || volume_type == ModelVolumeType::NEGATIVE_VOLUME || volume_type == ModelVolumeType::PARAMETER_MODIFIER);
3495 SurfaceVolumeData sfvd{volume_trmat, is_outside, std::move(sources)};
3496 CreateSurfaceVolumeData surface_data{std::move(emboss_data), std::move(sfvd), volume_type, object->id()};
3497 job = std::make_unique<CreateSurfaceVolumeJob>(std::move(surface_data));
3498 }
3499 }
3500 if (!use_surface) {
3501 // create volume
3502 DataCreateVolume data{std::move(emboss_data), volume_type, object->id(), volume_trmat};
3503 job = std::make_unique<CreateVolumeJob>(std::move(data));
3504 }
3505
3506 Plater *plater = wxGetApp().plater();
3507 Worker &worker = plater->get_ui_job_worker();
3508 queue_job(worker, std::move(job));
3509}
ModelVolumePtrs volumes
Definition Model.hpp:337
SurfaceVolumeData::ModelSources create_sources(const ModelVolumePtrs &volumes, std::optional< size_t > text_volume_id)
Copied triangles from object to be able create mesh for cut surface from.
Definition EmbossJob.cpp:263
Hold neccessary data to create(cut) volume from surface object in job.
Definition EmbossJob.hpp:175
Hold neccessary data to create ModelVolume in job Volume is created on the surface of existing volume...
Definition EmbossJob.hpp:42
Definition EmbossJob.hpp:152

References Slic3r::GUI::Emboss::create_sources(), Slic3r::GUI::Plater::get_ui_job_worker(), Slic3r::MODEL_PART, Slic3r::NEGATIVE_VOLUME, Slic3r::PARAMETER_MODIFIER, Slic3r::GUI::plater(), Slic3r::EmbossStyle::prop, Slic3r::GUI::queue_job(), Slic3r::TextConfiguration::style, Slic3r::GUI::Emboss::DataBase::text_configuration, Slic3r::FontProp::use_surface, and Slic3r::ModelObject::volumes.

Referenced by Slic3r::GUI::GLGizmoEmboss::create_volume(), and start_create_volume_on_surface_job().

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

◆ start_create_volume_on_surface_job()

bool priv::start_create_volume_on_surface_job ( DataBase emboss_data,
ModelVolumeType  volume_type,
const Vec2d screen_coor,
const GLVolume gl_volume,
RaycastManager raycaster,
GLCanvas3D canvas 
)
static

Start job for add new volume on surface of object defined by screen coor.

Parameters
emboss_dataDefine params of text
volume_typeEmboss / engrave
screen_coorMouse position which define position
gl_volumeVolume to find surface for create
raycasterAbility to ray cast to model
canvasContain already used scene RayCasters
Returns
True when start creation, False when there is no hit surface by screen coor
3513{
3514 assert(gl_volume != nullptr);
3515 if (gl_volume == nullptr) return false;
3516 if (gl_volume->volume_idx() < 0) return false;
3517
3518 Plater *plater = wxGetApp().plater();
3519 const ModelObjectPtrs &objects = plater->model().objects;
3520
3521 int object_idx = gl_volume->object_idx();
3522 if (object_idx < 0 || static_cast<size_t>(object_idx) >= objects.size()) return false;
3523 ModelObject *obj = objects[object_idx];
3524 size_t vol_id = obj->volumes[gl_volume->volume_idx()]->id().id;
3525 auto cond = RaycastManager::AllowVolumes({vol_id});
3526
3527 RaycastManager::Meshes meshes = create_meshes(canvas, cond);
3528 raycaster.actualize(*obj, &cond, &meshes);
3529
3530 const Camera &camera = plater->get_camera();
3531 std::optional<RaycastManager::Hit> hit = ray_from_camera(raycaster, screen_coor, camera, &cond);
3532
3533 // context menu for add text could be open only by right click on an
3534 // object. After right click, object is selected and object_idx is set
3535 // also hit must exist. But there is options to add text by object list
3536 if (!hit.has_value())
3537 return false;
3538
3539 // Create result volume transformation
3540 Transform3d surface_trmat = create_transformation_onto_surface(hit->position, hit->normal, priv::up_limit);
3541 const FontProp &font_prop = emboss_data.text_configuration.style.prop;
3542 apply_transformation(font_prop, surface_trmat);
3543 Transform3d instance = gl_volume->get_instance_transformation().get_matrix();
3544 Transform3d volume_trmat = instance.inverse() * surface_trmat;
3545 start_create_volume_job(obj, volume_trmat, emboss_data, volume_type);
3546 return true;
3547}
int volume_idx() const
Definition 3DScene.hpp:277
int object_idx() const
Definition 3DScene.hpp:276
const Geometry::Transformation & get_instance_transformation() const
Definition 3DScene.hpp:213
Definition RaycastManager.hpp:101
void actualize(const ModelObject &object, const ISkip *skip=nullptr, Meshes *meshes=nullptr)
Actualize raycasters + transformation Detection of removed object Detection of removed instance Detec...
Definition RaycastManager.cpp:25
std::vector< Mesh > Meshes
Definition RaycastManager.hpp:24
Transform3d create_transformation_onto_surface(const Vec3d &position, const Vec3d &normal, double up_limit=0.9)
Create transformation for emboss text object to lay on surface point.
Definition Emboss.cpp:1591
void apply_transformation(const FontProp &font_prop, Transform3d &transformation)
Use data from font property to modify transformation.
Definition Emboss.cpp:1268
RaycastManager::Meshes create_meshes(GLCanvas3D &canvas, const RaycastManager::AllowVolumes &condition)
Use scene Raycasters and prepare data for actualize RaycasterManager.
Definition RaycastManager.cpp:316
std::optional< RaycastManager::Hit > ray_from_camera(const RaycastManager &raycaster, const Vec2d &mouse_pos, const Camera &camera, const RaycastManager::ISkip *skip)
Unproject on mesh by Mesh raycasters.
Definition RaycastManager.cpp:351
static void start_create_volume_job(const ModelObject *object, const Transform3d volume_trmat, DataBase &emboss_data, ModelVolumeType volume_type)
Start job for add new volume to object with given transformation.
Definition GLGizmoEmboss.cpp:3479
constexpr double up_limit
Definition GLGizmoEmboss.cpp:113

References Slic3r::GUI::RaycastManager::actualize(), Slic3r::Emboss::apply_transformation(), Slic3r::GUI::create_meshes(), Slic3r::Emboss::create_transformation_onto_surface(), Slic3r::GUI::Plater::get_camera(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Eigen::Transform< _Scalar, _Dim, _Mode, _Options >::inverse(), Slic3r::GUI::Plater::model(), Slic3r::GLVolume::object_idx(), Slic3r::Model::objects, Slic3r::GUI::plater(), Slic3r::EmbossStyle::prop, Slic3r::GUI::ray_from_camera(), start_create_volume_job(), Slic3r::TextConfiguration::style, Slic3r::GUI::Emboss::DataBase::text_configuration, up_limit, Slic3r::GLVolume::volume_idx(), and Slic3r::ModelObject::volumes.

Referenced by Slic3r::GUI::GLGizmoEmboss::create_volume(), and Slic3r::GUI::GLGizmoEmboss::create_volume().

+ 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
988{
989 if (shapes.empty()) return {};
990
991 CutMesh result;
992 EdgeShapeMap edge_shape_map = result.add_property_map<EI, IntersectingElement>(edge_shape_map_name).first;
993 FaceShapeMap face_shape_map = result.add_property_map<FI, IntersectingElement>(face_shape_map_name).first;
994
995 std::vector<VI> indices;
996 auto insert_contour = [&projection, &indices, &result,
997 &edge_shape_map, &face_shape_map]
998 (const Polygon &polygon) {
999 indices.clear();
1000 indices.reserve(polygon.points.size() * 2);
1001 size_t num_vertices_old = result.number_of_vertices();
1002 for (const Point &polygon_point : polygon.points) {
1003 auto [front, back] = projection.create_front_back(polygon_point);
1004 P3 v_front{front.x(), front.y(), front.z()};
1005 VI vi1 = result.add_vertex(v_front);
1006 assert(vi1.idx() == (indices.size() + num_vertices_old));
1007 indices.push_back(vi1);
1008
1009 P3 v_back{back.x(), back.y(), back.z()};
1010 VI vi2 = result.add_vertex(v_back);
1011 assert(vi2.idx() == (indices.size() + num_vertices_old));
1012 indices.push_back(vi2);
1013 }
1014
1015 auto find_edge = [&result](FI fi, VI from, VI to) {
1016 HI hi = result.halfedge(fi);
1017 for (; result.target(hi) != to; hi = result.next(hi));
1018 assert(result.source(hi) == from);
1019 assert(result.target(hi) == to);
1020 return result.edge(hi);
1021 };
1022
1023 uint32_t contour_index = static_cast<uint32_t>(num_vertices_old / 2);
1024 for (int32_t i = 0; i < int32_t(indices.size()); i += 2) {
1025 bool is_first = i == 0;
1026 bool is_last = size_t(i + 2) >= indices.size();
1027 int32_t j = is_last ? 0 : (i + 2);
1028
1029 FI fi1 = result.add_face(indices[i], indices[j], indices[i + 1]);
1030 EI ei1 = find_edge(fi1, indices[i + 1], indices[i]);
1031 EI ei2 = find_edge(fi1, indices[j], indices[i + 1]);
1032 FI fi2 = result.add_face(indices[j], indices[j + 1], indices[i + 1]);
1033 IntersectingElement element {contour_index, (unsigned char)IntersectingElement::Type::undefined};
1034 if (is_first) element.set_is_first();
1035 if (is_last) element.set_is_last();
1036 edge_shape_map[ei1] = element.set_type(IntersectingElement::Type::edge_1);
1037 face_shape_map[fi1] = element.set_type(IntersectingElement::Type::face_1);
1038 edge_shape_map[ei2] = element.set_type(IntersectingElement::Type::edge_2);
1039 face_shape_map[fi2] = element.set_type(IntersectingElement::Type::face_2);
1040 ++contour_index;
1041 }
1042 };
1043
1044 size_t count_point = count_points(shapes);
1045 result.reserve(result.number_of_vertices() + 2 * count_point,
1046 result.number_of_edges() + 4 * count_point,
1047 result.number_of_faces() + 2 * count_point);
1048
1049 // Identify polygon
1050 for (const ExPolygon &shape : shapes) {
1051 insert_contour(shape.contour);
1052 for (const Polygon &hole : shape.holes)
1053 insert_contour(hole);
1054 }
1055 assert(!exist_duplicit_vertex(result));
1056 return result;
1057}
TPoint< P > back(const P &p)
Definition geometry_traits.hpp:873
bool exist_duplicit_vertex(const CutMesh &mesh)
Definition CutSurface.cpp:966
__int32 int32_t
Definition unistd.h:75

References Slic3r::count_points(), Slic3r::Emboss::IProjection::create_front_back(), edge_shape_map_name, exist_duplicit_vertex(), face_shape_map_name, and priv::IntersectingElement::set_is_first().

+ 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
896{
897 const std::vector<stl_vertex> &vertices = its.vertices;
898 const std::vector<stl_triangle_vertex_indices> &indices = its.indices;
899
900 std::vector<bool> use_vetices(vertices.size(), {false});
901
902 size_t vertices_count = 0;
903 size_t faces_count = 0;
904 size_t edges_count = 0;
905
906 for (const auto &t : indices) {
907 size_t index = &t - &indices.front();
908 if (skip_indicies[index]) continue;
909 ++faces_count;
910 size_t count_used_vertices = 0;
911 for (const auto vi : t) {
912 if (!use_vetices[vi]) {
913 ++vertices_count;
914 use_vetices[vi] = true;
915 } else {
916 ++count_used_vertices;
917 }
918 }
919 switch (count_used_vertices) {
920 case 3: break; // all edges are already counted
921 case 2: edges_count += 2; break;
922 case 1:
923 case 0: edges_count += 3; break;
924 default: assert(false);
925 }
926 }
927 assert(vertices_count <= vertices.size());
928 assert(edges_count <= (indices.size() * 3));
929 assert(faces_count <= indices.size());
930
931 CutMesh result;
932 result.reserve(vertices_count, edges_count, faces_count);
933
934 std::vector<VI> to_filtrated_vertices_index(vertices.size());
935 size_t filtrated_vertices_index = 0;
936 for (size_t i = 0; i < vertices.size(); ++i)
937 if (use_vetices[i]) {
938 to_filtrated_vertices_index[i] = VI(filtrated_vertices_index);
939 ++filtrated_vertices_index;
940 }
941
942 for (const stl_vertex& v : vertices) {
943 if (!use_vetices[&v - &vertices.front()]) continue;
944 result.add_vertex(CutMesh::Point{v.x(), v.y(), v.z()});
945 }
946
947 if (!flip) {
948 for (const stl_triangle_vertex_indices &f : indices) {
949 if (skip_indicies[&f - &indices.front()]) continue;
950 result.add_face(to_filtrated_vertices_index[f[0]],
951 to_filtrated_vertices_index[f[1]],
952 to_filtrated_vertices_index[f[2]]);
953 }
954 } else {
955 for (const stl_triangle_vertex_indices &f : indices) {
956 if (skip_indicies[&f - &indices.front()]) continue;
957 result.add_face(to_filtrated_vertices_index[f[2]],
958 to_filtrated_vertices_index[f[1]],
959 to_filtrated_vertices_index[f[0]]);
960 }
961 }
962
963 return result;
964}
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:12

References Slic3r::f(), indexed_triangle_set::indices, and indexed_triangle_set::vertices.

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
3474{
3475 Polygons polys = unproject_loops(patch, projection, depth_range);
3476 // should not be used when no opposit triangle are counted so should not create overlaps
3478 ExPolygons expolys = Slic3r::union_ex(polys, fill_type);
3479 if (expolys.size() == 1)
3480 return expolys.front();
3481
3482 // It should be one expolygon
3483 assert(false);
3484
3485 if (expolys.empty()) return {};
3486 // find biggest
3487 const ExPolygon *biggest = &expolys.front();
3488 for (size_t index = 1; index < expolys.size(); ++index) {
3489 const ExPolygon *current = &expolys[index];
3490 if (biggest->contour.size() < current->contour.size())
3491 biggest = current;
3492 }
3493 return *biggest;
3494}
PolyFillType
Definition clipper.hpp:81
@ pftEvenOdd
Definition clipper.hpp:81
Polygons unproject_loops(const SurfacePatch &patch, const Project &projection, Vec2d &depth_range)
Unptoject points from outline loops of patch.
Definition CutSurface.cpp:3428

References Slic3r::ExPolygon::contour, ClipperLib::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_point()

Point priv::to_point ( const stbtt__point &  point)
859 {
860 return Point(static_cast<int>(std::round(point.x / SHAPE_SCALE)),
861 static_cast<int>(std::round(point.y / SHAPE_SCALE)));
862}

References Slic3r::Emboss::SHAPE_SCALE.

Referenced by get_glyph().

+ Here is the caller graph for this function:

◆ to_range_pi_pi()

template<typename T >
void priv::to_range_pi_pi ( T &  angle)
117{
118 if (angle > PI || angle < -PI) {
119 int count = static_cast<int>(std::round(angle / (2 * PI)));
120 angle -= static_cast<T>(count * 2 * PI);
121 }
122}
static constexpr double PI
Definition libslic3r.h:58

References Slic3r::angle(), and PI.

Referenced by Slic3r::GUI::GLGizmoEmboss::draw_advanced(), and Slic3r::GUI::GLGizmoEmboss::on_mouse_for_rotation().

+ 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
81{ 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:

◆ try_create_mesh()

template<typename Fnc >
static TriangleMesh priv::try_create_mesh ( DataBase input,
Fnc  was_canceled 
)
static

Try to create mesh from text.

Parameters
inputText to convert on mesh
  • Shape of characters + Property of font
fontFont file with cache NOTE: Cache glyphs is changed
was_canceledTo check if process was canceled
Returns
Triangle mesh model

Referenced by Slic3r::GUI::Emboss::UpdateJob::process().

+ 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
3429{
3430 assert(!patch.loops.empty());
3431 if (patch.loops.empty()) return {};
3432
3433 // NOTE: this method is working only when patch did not contain outward faces
3434 Polygons polys;
3435 polys.reserve(patch.loops.size());
3436 // project conture into 2d space to fillconvert outlines to
3437
3438 size_t count = 0;
3439 for (const Loop &l : patch.loops) count += l.size();
3440 std::vector<float> depths;
3441 depths.reserve(count);
3442
3443 Points pts;
3444 for (const Loop &l : patch.loops) {
3445 pts.clear();
3446 pts.reserve(l.size());
3447 for (VI vi : l) {
3448 const P3 &p3 = patch.mesh.point(vi);
3449 Vec3d p = to_vec3d(p3);
3450 double depth;
3451 std::optional<Vec2d> p2_opt = projection.unproject(p, &depth);
3452 if (depth_range[0] > depth) depth_range[0] = depth; // min
3453 if (depth_range[1] < depth) depth_range[1] = depth; // max
3454 // Check when appear that skip is enough for poit which can't be unprojected
3455 // - it could break contour
3456 assert(p2_opt.has_value());
3457 if (!p2_opt.has_value()) continue;
3458
3459 pts.push_back(p2_opt->cast<Point::coord_type>());
3460 depths.push_back(static_cast<float>(depth));
3461 }
3462 // minimal is triangle
3463 assert(pts.size() >= 3);
3464 if (pts.size() < 3) continue;
3465
3466 polys.emplace_back(pts);
3467 }
3468
3469 assert(!polys.empty());
3470 return polys;
3471}
virtual std::optional< Vec2d > unproject(const Vec3d &p, double *depth=nullptr) const =0
Back projection.

References 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:

◆ update_volume()

void priv::update_volume ( TriangleMesh &&  mesh,
const DataUpdate data,
Transform3d tr = nullptr 
)
static

Must be called on main thread.

Parameters
meshNew mesh data
dataText configuration, ...
meshTransformation of volume
566{
567 // for sure that some object will be created
568 if (mesh.its.empty())
569 return create_message("Empty mesh can't be created.");
570
571 Plater *plater = wxGetApp().plater();
572 GLCanvas3D *canvas = plater->canvas3D();
573
574 // Check emboss gizmo is still open
575 GLGizmosManager &manager = canvas->get_gizmos_manager();
577 return;
578
579 std::string snap_name = GUI::format(_L("Text: %1%"), data.text_configuration.text);
580 Plater::TakeSnapshot snapshot(plater, snap_name, UndoRedo::SnapshotType::GizmoAction);
581 ModelVolume *volume = get_volume(plater->model().objects, data.volume_id);
582
583 // could appear when user delete edited volume
584 if (volume == nullptr)
585 return;
586
587 if (tr) {
588 volume->set_transformation(*tr);
589 } else {
590 // apply fix matrix made by store to .3mf
591 const auto &tc = volume->text_configuration;
592 assert(tc.has_value());
593 if (tc.has_value() && tc->fix_3mf_tr.has_value())
594 volume->set_transformation(volume->get_matrix() * tc->fix_3mf_tr->inverse());
595 }
596
597 UpdateJob::update_volume(volume, std::move(mesh), data.text_configuration, data.volume_name);
598}
static void update_volume(ModelVolume *volume, TriangleMesh &&mesh, const TextConfiguration &text_configuration, std::string_view volume_name)
Update text volume.
Definition EmbossJob.cpp:519
Definition Plater.hpp:442
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:56

References _L, Slic3r::GUI::Plater::canvas3D(), create_message(), Slic3r::GUI::GLGizmosManager::Emboss, Slic3r::TextConfiguration::fix_3mf_tr, Slic3r::GUI::format(), Slic3r::GUI::GLGizmosManager::get_current_type(), Slic3r::GUI::GLCanvas3D::get_gizmos_manager(), Slic3r::GUI::get_volume(), Slic3r::UndoRedo::GizmoAction, Slic3r::GUI::Plater::model(), Slic3r::Model::objects, Slic3r::GUI::plater(), and Slic3r::GUI::Emboss::UpdateJob::update_volume().

Referenced by Slic3r::GUI::Emboss::UpdateJob::finalize(), and Slic3r::GUI::Emboss::UpdateSurfaceVolumeJob::finalize().

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

◆ visualize_heal()

void priv::visualize_heal ( const std::string &  svg_filepath,
const ExPolygons expolygons 
)
564 {
565 Points pts = to_points(expolygons);
566 BoundingBox bb(pts);
567 //double svg_scale = SHAPE_SCALE / unscale<double>(1.);
568 // bb.scale(svg_scale);
569 SVG svg(svg_filepath, bb);
570 svg.draw(expolygons);
571
572 Points duplicits = collect_duplicates(pts);
573 svg.draw(duplicits, "black", 7 / SHAPE_SCALE);
574
575 Pointfs intersections_f = intersection_points(expolygons);
576 Points intersections;
577 intersections.reserve(intersections_f.size());
578 std::transform(intersections_f.begin(), intersections_f.end(), std::back_inserter(intersections),
579 [](const Vec2d &p) { return p.cast<int>(); });
580 svg.draw(intersections, "red", 8 / SHAPE_SCALE);
581}

References Slic3r::collect_duplicates(), Slic3r::SVG::draw(), Slic3r::intersection_points(), Slic3r::Emboss::SHAPE_SCALE, and Slic3r::to_points().

+ Here is the call 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"

◆ limits

◆ patch_source_name

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

◆ safe_extension

constexpr float priv::safe_extension = 1.0f
constexpr

◆ up_limit

◆ 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"