264{
265 assert(!
m_planes[plane_idx].features_extracted);
266
267 PlaneData& plane =
m_planes[plane_idx];
268 plane.surface_features.clear();
270
274 trafo.rotate(q);
276
277 std::vector<double> angles;
278 std::vector<double> lengths;
279
280 for (const std::vector<Vec3d>& border : plane.borders) {
281 if (border.size() <= 1)
282 continue;
283
285
286 if (border.size() > 4) {
288
289 if (err < 0.05) {
290
291
292
293 bool is_polygon = border.size()>4 && border.size()<=8;
294 bool lengths_match = std::all_of(border.begin()+2, border.end(), [is_polygon](
const Vec3d& pt) {
295 return Slic3r::is_approx((pt - *((&pt)-1)).squaredNorm(), (*((&pt)-1) - *((&pt)-2)).squaredNorm(), is_polygon ? 0.01 : 0.01);
296 });
297
298 if (lengths_match && (is_polygon || border.size() > 8)) {
299 if (is_polygon) {
300
301 for (int j=0; j<int(border.size()); ++j)
303 border[j==0 ? border.size()-1 : j-1], border[j],
304 std::make_optional(center)));
305 } else {
306
308 }
310 }
311 }
312 }
313
315
316
317
320
321
322
323
324
325 auto offset_to_index = [border_size = int(border.size())](
int idx,
int offset) ->
int {
326 assert(std::abs(
offset) < border_size);
328 if (out >= border_size)
329 out = out - border_size;
330 else if (out < 0)
331 out = border_size + out;
332
333 return out;
334 };
335
336
337 angles.clear();
338 lengths.clear();
339 int first_different_angle_idx = 0;
340 for (int i=0; i<int(border.size()); ++i) {
341 const Vec3d& v2 = border[i] - (i == 0 ? border[border.size()-1] : border[i-1]);
342 const Vec3d& v1 = (i == int(border.size()-1) ? border[0] : border[i+1]) - border[i];
346
347 angles.push_back(
angle);
348 lengths.push_back(v2.norm());
349 if (first_different_angle_idx == 0 && angles.size() > 1) {
350 if (! are_angles_same(angles.back(), angles[angles.size()-2]))
351 first_different_angle_idx = angles.size()-1;
352 }
353 }
354 assert(border.size() == angles.size());
355 assert(border.size() == lengths.size());
356
357
358
359
360 int start_idx = -1;
361 bool circle = false;
362 bool first_iter = true;
363 std::vector<SurfaceFeature> circles;
364 std::vector<SurfaceFeature>
edges;
365 std::vector<std::pair<int, int>> circles_idxs;
366
367 std::vector<Vec3d> single_circle;
368 double single_circle_length = 0.;
369 int first_pt_idx = offset_to_index(first_different_angle_idx, 1);
370 int i = first_pt_idx;
371 while (i != first_pt_idx || first_iter) {
372 if (are_angles_same(angles[i], angles[offset_to_index(i,-1)])
373 && i != offset_to_index(first_pt_idx, -1)
374 && i != start_idx ) {
375
376 if (! circle) {
377 circle = true;
378 single_circle.clear();
379 single_circle_length = 0.;
380 start_idx = offset_to_index(i, -2);
381 single_circle = { border[start_idx], border[offset_to_index(start_idx,1)] };
382 single_circle_length += lengths[offset_to_index(i, -1)];
383 }
384 single_circle.emplace_back(border[i]);
385 single_circle_length += lengths[i];
386 } else {
387 if (circle && single_circle.size() >= 5) {
388 single_circle.emplace_back(border[i]);
389 single_circle_length += lengths[i];
390
391 bool accept_circle = true;
392 {
393
394 int j = offset_to_index(start_idx, 3);
395 while (j != i) {
396 if (! are_lengths_same(lengths[offset_to_index(j,-1)], lengths[j])) {
397 accept_circle = false;
398 break;
399 }
400 j = offset_to_index(j, 1);
401 }
402 }
403
404 if (accept_circle) {
406
407
408
409 accept_circle &= err < 0.05;
410
411
412 accept_circle &= single_circle_length / radius > 0.9*
M_PI/2.;
413
414 if (accept_circle) {
415
416 circles_idxs.emplace_back(start_idx, i);
418 }
419 }
420 }
421 circle = false;
422 }
423
424 first_iter = false;
425 i = offset_to_index(i, 1);
426 }
427
428
429 if (circles_idxs.empty()) {
430
431 for (int i=1; i<int(border.size()); ++i)
434 } else if (circles_idxs.size() > 1 || circles_idxs.front().first != circles_idxs.front().second) {
435
436 int i = circles_idxs.front().second;
437 int circle_idx = 1;
438 while (true) {
439 i = offset_to_index(i, 1);
441 if (circle_idx < int(circles_idxs.size()) && i == circles_idxs[circle_idx].first) {
442 i = circles_idxs[circle_idx].second;
443 ++circle_idx;
444 }
445 if (i == circles_idxs.front().first)
446 break;
447 }
448 }
449
450
451 assert(std::all_of(
edges.begin(),
edges.end(),
452 [](
const SurfaceFeature&
f) { return f.get_type() == SurfaceFeatureType::Edge; }));
453 for (
int i=
edges.size()-1; i>=0; --i) {
454 const auto& [first_start, first_end] =
edges[i==0 ?
edges.size()-1 : i-1].get_edge();
455 const auto& [second_start, second_end] =
edges[i].get_edge();
456
458 &&
Slic3r::is_approx((first_end-first_start).normalized().
dot((second_end-second_start).normalized()), 1.)) {
459
462 }
463 }
464
465
466 assert(std::all_of(circles.begin(), circles.end(), [](
const SurfaceFeature&
f) {
467 return f.get_type() == SurfaceFeatureType::Circle;
468 }));
469 assert(std::all_of(
edges.begin(),
edges.end(), [](
const SurfaceFeature&
f) {
470 return f.get_type() == SurfaceFeatureType::Edge;
471 }));
472 plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(circles.begin()),
473 std::make_move_iterator(circles.end()));
474 plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(
edges.begin()),
475 std::make_move_iterator(
edges.end()));
476 }
477 }
478
479
480 Vec3d cog = Vec3d::Zero();
481 size_t counter = 0;
482 for (const std::vector<Vec3d>& b : plane.borders) {
483 for (
size_t i = 1; i <
b.size(); ++i) {
485 ++counter;
486 }
487 }
488 cog /= double(counter);
490 plane.normal, cog, std::optional<Vec3d>(), plane_idx + 0.0001));
491
492 plane.borders.clear();
493 plane.borders.shrink_to_fit();
494
495 plane.features_extracted = true;
496}
#define M_PI
Definition ExtrusionSimulator.cpp:20
static volatile int done
Definition bitbang.c:50
EIGEN_DEVICE_FUNC Transform inverse(TransformTraits traits=(TransformTraits) Mode) const
Definition Transform.h:1202
static EIGEN_DEVICE_FUNC const Transform Identity()
Returns an identity transformation.
Definition Transform.h:539
EIGEN_DEVICE_FUNC Derived & setFromTwoVectors(const MatrixBase< Derived1 > &a, const MatrixBase< Derived2 > &b)
Definition Quaternion.h:582
The quaternion class used to represent 3D orientations and rotations.
Definition Quaternion.h:233
static std::tuple< Vec3d, double, double > get_center_and_radius(const std::vector< Vec3d > &points, const Transform3d &trafo, const Transform3d &trafo_inv)
Definition Measure.cpp:19
Vec< 3, T > normal(const std::array< Vec< 3, T >, 3 > &tri)
Definition Rotfinder.cpp:43
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:81
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:416
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
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:12
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:271
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:143
IGL_INLINE void edges(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
Definition edges.cpp:13