OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::sla::anonymous_namespace{Rotfinder.cpp} Namespace Reference

Classes

struct  Facestats

Typedefs

using XYRotation = std::array<double, 2>

Functions

std::array< Vec3f, 3 > get_triangle_vertices (const TriangleMesh &mesh, size_t faceidx)
std::array< Vec3f, 3 > get_transformed_triangle (const TriangleMesh &mesh, const Transform3f &tr, size_t faceidx)
template<class T>
Vec< 3, T > normal (const std::array< Vec< 3, T >, 3 > &tri)
template<class T, class AccessFn>
T sum_score (AccessFn &&accessfn, size_t facecount, size_t Nthreads)
double get_misalginment_score (const TriangleMesh &mesh, const Transform3f &tr)
double get_supportedness_score (const Facestats &fc)
double get_supportedness_score (const TriangleMesh &mesh, const Transform3f &tr)
float find_ground_level (const TriangleMesh &mesh, const Transform3f &tr, size_t threads)
float get_supportedness_onfloor_score (const TriangleMesh &mesh, const Transform3f &tr)
Transform3f to_transform3f (const XYRotation &rot)
XYRotation from_transform3f (const Transform3f &tr)
bool is_on_floor (const SLAPrintObjectConfig &cfg)
std::vector< XYRotation > get_chull_rotations (const TriangleMesh &mesh, size_t max_count)
template<size_t N, class Fn, class It, class StopCond>
std::array< double, N > find_min_score (Fn &&fn, It from, It to, StopCond &&stopfn)

Variables

const Vec3f DOWN = {0.f, 0.f, -1.f}
constexpr double POINTS_PER_UNIT_AREA = 1.f

Typedef Documentation

◆ XYRotation

using Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::XYRotation = std::array<double, 2>

Function Documentation

◆ find_ground_level()

float Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::find_ground_level ( const TriangleMesh & mesh,
const Transform3f & tr,
size_t threads )
152{
153 size_t vsize = mesh.its.vertices.size();
154
155 auto minfn = [](float a, float b) { return std::min(a, b); };
156
157 auto accessfn = [&mesh, &tr] (size_t vi) {
158 return (tr * mesh.its.vertices[vi]).z();
159 };
160
161 auto zmin = std::numeric_limits<float>::max();
162 size_t granularity = vsize / threads;
163 return execution::reduce(ex_tbb, size_t(0), vsize, zmin, minfn, accessfn, granularity);
164}
indexed_triangle_set its
Definition TriangleMesh.hpp:164
T reduce(const EP &ep, I from, I to, const T &init, MergeFn &&mergefn, AccessFn &&accessfn, size_t granularity=1)
Definition Execution.hpp:61
static constexpr ExecutionTBB ex_tbb
Definition ExecutionTBB.hpp:22

References Slic3r::ex_tbb, find_ground_level(), Slic3r::TriangleMesh::its, and Slic3r::execution::reduce().

Referenced by find_ground_level(), and get_supportedness_onfloor_score().

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

◆ find_min_score()

template<size_t N, class Fn, class It, class StopCond>
std::array< double, N > Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::find_min_score ( Fn && fn,
It from,
It to,
StopCond && stopfn )
272{
273 std::array<double, N> ret = {};
274
275 double score = std::numeric_limits<double>::max();
276
277 size_t Nthreads = std::thread::hardware_concurrency();
278 size_t dist = std::distance(from, to);
279 std::vector<double> scores(dist, score);
280
282 ex_tbb, size_t(0), dist, [&stopfn, &scores, &fn, &from](size_t i) {
283 if (stopfn()) return;
284
285 scores[i] = fn(*(from + i));
286 },
287 dist / Nthreads);
288
289 auto it = std::min_element(scores.begin(), scores.end());
290
291 if (it != scores.end())
292 ret = *(from + std::distance(scores.begin(), it));
293
294 return ret;
295}
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:298
void for_each(const EP &ep, It from, It to, Fn &&fn, size_t granularity=1)
Definition Execution.hpp:46

References Slic3r::Geometry::dist(), Slic3r::ex_tbb, find_min_score(), and Slic3r::execution::for_each().

Referenced by find_min_score().

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

◆ from_transform3f()

XYRotation Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::from_transform3f ( const Transform3f & tr)
205{
206 Vec3d rot3 = Geometry::Transformation{tr.cast<double>()}.get_rotation();
207 return {rot3.x(), rot3.y()};
208}
Definition Geometry.hpp:419
Vec3d get_rotation() const
Definition Geometry.cpp:471
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition SpatIndex.hpp:18

References from_transform3f(), and Slic3r::Geometry::Transformation::get_rotation().

Referenced by from_transform3f(), and get_chull_rotations().

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

◆ get_chull_rotations()

std::vector< XYRotation > Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::get_chull_rotations ( const TriangleMesh & mesh,
size_t max_count )
220{
221 TriangleMesh chull = mesh.convex_hull_3d();
222 double chull2d_area = chull.convex_hull().area();
223 double area_threshold = chull2d_area / (scaled<double>(1e3) * scaled(1.));
224
225 size_t facecount = chull.its.indices.size();
226
227 struct RotArea { XYRotation rot; double area; };
228
229 auto inputs = reserve_vector<RotArea>(facecount);
230
231 auto rotcmp = [](const RotArea &r1, const RotArea &r2) {
232 double xdiff = r1.rot[X] - r2.rot[X], ydiff = r1.rot[Y] - r2.rot[Y];
233 return std::abs(xdiff) < EPSILON ? ydiff < 0. : xdiff < 0.;
234 };
235
236 auto eqcmp = [](const XYRotation &r1, const XYRotation &r2) {
237 double xdiff = r1[X] - r2[X], ydiff = r1[Y] - r2[Y];
238 return std::abs(xdiff) < EPSILON && std::abs(ydiff) < EPSILON;
239 };
240
241 for (size_t fi = 0; fi < facecount; ++fi) {
242 Facestats fc{get_triangle_vertices(chull, fi)};
243
244 if (fc.area > area_threshold) {
245 auto q = Eigen::Quaternionf{}.FromTwoVectors(fc.normal, DOWN);
246 XYRotation rot = from_transform3f(Transform3f::Identity() * q);
247 RotArea ra = {rot, fc.area};
248
249 auto it = std::lower_bound(inputs.begin(), inputs.end(), ra, rotcmp);
250
251 if (it == inputs.end() || !eqcmp(it->rot, rot))
252 inputs.insert(it, ra);
253 }
254 }
255
256 inputs.shrink_to_fit();
257 if (!max_count) max_count = inputs.size();
258 std::sort(inputs.begin(), inputs.end(),
259 [](const RotArea &ra, const RotArea &rb) {
260 return ra.area > rb.area;
261 });
262
263 auto ret = reserve_vector<XYRotation>(std::min(max_count, inputs.size()));
264 for (const RotArea &ra : inputs) ret.emplace_back(ra.rot);
265
266 return ret;
267}
#define EPSILON
Definition ColorUtils.cpp:64
static double area(const Points &pts)
Definition Polygon.cpp:65
Definition TriangleMesh.hpp:94
Polygon convex_hull() const
Definition TriangleMesh.cpp:436
TriangleMesh convex_hull_3d() const
Definition TriangleMesh.cpp:515
const Vec3f DOWN
Definition Rotfinder.cpp:36
XYRotation from_transform3f(const Transform3f &tr)
Definition Rotfinder.cpp:204
std::array< Vec3f, 3 > get_triangle_vertices(const TriangleMesh &mesh, size_t faceidx)
Definition Rotfinder.cpp:40
std::array< double, 2 > XYRotation
Definition Rotfinder.cpp:192
@ Y
Definition SupportTreeBuildsteps.hpp:37
@ X
Definition SupportTreeBuildsteps.hpp:37
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
double area(const ExPolygon &poly)
Definition ExPolygon.hpp:511
IntegerOnly< I, std::vector< T, Args... > > reserve_vector(I capacity)
Definition libslic3r.h:370
@ Y
Definition libslic3r.h:142
@ X
Definition libslic3r.h:141

References Slic3r::area(), Slic3r::Polygon::area(), Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::Facestats::area, Slic3r::TriangleMesh::convex_hull(), Slic3r::TriangleMesh::convex_hull_3d(), DOWN, EPSILON, from_transform3f(), get_chull_rotations(), get_triangle_vertices(), Slic3r::TriangleMesh::its, Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::Facestats::normal, Slic3r::reserve_vector(), Slic3r::scaled(), Slic3r::sla::X, and Slic3r::sla::Y.

Referenced by get_chull_rotations().

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

◆ get_misalginment_score()

double Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::get_misalginment_score ( const TriangleMesh & mesh,
const Transform3f & tr )
92{
93 if (mesh.its.vertices.empty()) return std::nan("");
94
95 auto accessfn = [&mesh, &tr](size_t fi) {
96 Facestats fc{get_transformed_triangle(mesh, tr, fi)};
97
98 float score = fc.area
99 * (std::abs(fc.normal.dot(Vec3f::UnitX()))
100 + std::abs(fc.normal.dot(Vec3f::UnitY()))
101 + std::abs(fc.normal.dot(Vec3f::UnitZ())));
102
103 // We should score against the alignment with the reference planes
104 return scaled<int_fast64_t>(score);
105 };
106
107 size_t facecount = mesh.its.indices.size();
108 size_t Nthreads = std::thread::hardware_concurrency();
109 double S = unscaled(sum_score<int_fast64_t>(accessfn, facecount, Nthreads));
110
111 return S / facecount;
112}
T sum_score(AccessFn &&accessfn, size_t facecount, size_t Nthreads)
Definition Rotfinder.cpp:65
std::array< Vec3f, 3 > get_transformed_triangle(const TriangleMesh &mesh, const Transform3f &tr, size_t faceidx)
Definition Rotfinder.cpp:49
constexpr Eigen::Matrix< Tout, 2, EigenArgs... > unscaled(const Slic3r::Point &v) noexcept
Definition Arrange.cpp:81

References Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::Facestats::area, get_misalginment_score(), get_transformed_triangle(), Slic3r::TriangleMesh::its, Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::Facestats::normal, Slic3r::scaled(), sum_score(), and Slic3r::unscaled().

Referenced by get_misalginment_score().

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

◆ get_supportedness_onfloor_score()

float Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::get_supportedness_onfloor_score ( const TriangleMesh & mesh,
const Transform3f & tr )
168{
169 if (mesh.its.vertices.empty()) return std::nan("");
170
171 size_t Nthreads = std::thread::hardware_concurrency();
172
173 float zmin = find_ground_level(mesh, tr, Nthreads);
174 float zlvl = zmin + 0.1f; // Set up a slight tolerance from z level
175
176 auto accessfn = [&mesh, &tr, zlvl](size_t fi) {
177 std::array<Vec3f, 3> tri = get_transformed_triangle(mesh, tr, fi);
178 Facestats fc{tri};
179
180 if (tri[0].z() <= zlvl && tri[1].z() <= zlvl && tri[2].z() <= zlvl)
181 return -2 * fc.area * POINTS_PER_UNIT_AREA;
182
183 return get_supportedness_score(fc);
184 };
185
186 size_t facecount = mesh.its.indices.size();
187 double S = unscaled(sum_score<int_fast64_t>(accessfn, facecount, Nthreads));
188
189 return S / facecount;
190}
constexpr double POINTS_PER_UNIT_AREA
Definition Rotfinder.cpp:37
float find_ground_level(const TriangleMesh &mesh, const Transform3f &tr, size_t threads)
Definition Rotfinder.cpp:149
double get_supportedness_score(const Facestats &fc)
Definition Rotfinder.cpp:115

References Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::Facestats::area, find_ground_level(), get_supportedness_onfloor_score(), get_supportedness_score(), get_transformed_triangle(), Slic3r::TriangleMesh::its, POINTS_PER_UNIT_AREA, sum_score(), and Slic3r::unscaled().

Referenced by get_supportedness_onfloor_score().

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

◆ get_supportedness_score() [1/2]

double Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::get_supportedness_score ( const Facestats & fc)
inline
116{
117 // Simply get the angle (acos of dot product) between the face normal and
118 // the DOWN vector.
119 float cosphi = fc.normal.dot(DOWN);
120 float phi = 1.f - std::acos(cosphi) / float(PI);
121
122 // Make the huge slopes more significant than the smaller slopes
123 phi = phi * phi * phi;
124
125 // Multiply with the square root of face area of the current face,
126 // the area is less important as it grows.
127 // This makes many smaller overhangs a bigger impact.
128 return std::sqrt(fc.area) * POINTS_PER_UNIT_AREA * phi;
129}
static constexpr double PI
Definition libslic3r.h:81

References Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::Facestats::area, DOWN, get_supportedness_score(), Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::Facestats::normal, PI, and POINTS_PER_UNIT_AREA.

Referenced by get_supportedness_onfloor_score(), get_supportedness_score(), and get_supportedness_score().

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

◆ get_supportedness_score() [2/2]

double Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::get_supportedness_score ( const TriangleMesh & mesh,
const Transform3f & tr )
133{
134 if (mesh.its.vertices.empty()) return std::nan("");
135
136 auto accessfn = [&mesh, &tr](size_t fi) {
137 Facestats fc{get_transformed_triangle(mesh, tr, fi)};
139 };
140
141 size_t facecount = mesh.its.indices.size();
142 size_t Nthreads = std::thread::hardware_concurrency();
143 double S = unscaled(sum_score<int_fast64_t>(accessfn, facecount, Nthreads));
144
145 return S / facecount;
146}

References get_supportedness_score(), get_transformed_triangle(), Slic3r::TriangleMesh::its, Slic3r::scaled(), sum_score(), and Slic3r::unscaled().

Here is the call graph for this function:

◆ get_transformed_triangle()

std::array< Vec3f, 3 > Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::get_transformed_triangle ( const TriangleMesh & mesh,
const Transform3f & tr,
size_t faceidx )
52{
53 const auto &tri = get_triangle_vertices(mesh, faceidx);
54 return {tr * tri[0], tr * tri[1], tr * tri[2]};
55}

References get_transformed_triangle(), and get_triangle_vertices().

Referenced by get_misalginment_score(), get_supportedness_onfloor_score(), get_supportedness_score(), and get_transformed_triangle().

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

◆ get_triangle_vertices()

std::array< Vec3f, 3 > Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::get_triangle_vertices ( const TriangleMesh & mesh,
size_t faceidx )
42{
43 const auto &face = mesh.its.indices[faceidx];
44 return {mesh.its.vertices[face(0)],
45 mesh.its.vertices[face(1)],
46 mesh.its.vertices[face(2)]};
47}

References get_triangle_vertices(), and Slic3r::TriangleMesh::its.

Referenced by get_chull_rotations(), get_transformed_triangle(), and get_triangle_vertices().

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

◆ is_on_floor()

bool Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::is_on_floor ( const SLAPrintObjectConfig & cfg)
inline
211{
212 auto opt_elevation = cfg.support_object_elevation.getFloat();
213 auto opt_padaround = cfg.pad_around_object.getBool();
214
215 return opt_elevation < EPSILON || opt_padaround;
216}

References EPSILON, and is_on_floor().

Referenced by is_on_floor().

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

◆ normal()

template<class T>
Vec< 3, T > Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::normal ( const std::array< Vec< 3, T >, 3 > & tri)
58{
59 Vec<3, T> U = tri[1] - tri[0];
60 Vec<3, T> V = tri[2] - tri[0];
61 return U.cross(V).normalized();
62}
Mat< N, 1, T > Vec
Definition Point.hpp:48

◆ sum_score()

template<class T, class AccessFn>
T Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::sum_score ( AccessFn && accessfn,
size_t facecount,
size_t Nthreads )
66{
67 T initv = 0.;
68 auto mergefn = [](T a, T b) { return a + b; };
69 size_t grainsize = facecount / Nthreads;
70 size_t from = 0, to = facecount;
71
72 return execution::reduce(ex_tbb, from, to, initv, mergefn, accessfn, grainsize);
73}

References Slic3r::ex_tbb, Slic3r::execution::reduce(), and sum_score().

Referenced by get_misalginment_score(), get_supportedness_onfloor_score(), get_supportedness_score(), and sum_score().

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

◆ to_transform3f()

Transform3f Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::to_transform3f ( const XYRotation & rot)
196{
197 Transform3f rt = Transform3f::Identity();
198 rt.rotate(Eigen::AngleAxisf(float(rot[1]), Vec3f::UnitY()));
199 rt.rotate(Eigen::AngleAxisf(float(rot[0]), Vec3f::UnitX()));
200
201 return rt;
202}
Eigen::Transform< float, 3, Eigen::Affine, Eigen::DontAlign > Transform3f
Definition Point.hpp:95

References to_transform3f().

Referenced by to_transform3f().

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

Variable Documentation

◆ DOWN

const Vec3f Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::DOWN = {0.f, 0.f, -1.f}
inline
36{0.f, 0.f, -1.f};

Referenced by get_chull_rotations(), and get_supportedness_score().

◆ POINTS_PER_UNIT_AREA

double Slic3r::sla::anonymous_namespace{Rotfinder.cpp}::POINTS_PER_UNIT_AREA = 1.f
constexpr