315{
316 assert(!
m_planes[plane_idx].features_extracted);
317
319 plane.surface_features.clear();
321
322 Eigen::Quaterniond q;
323 q.setFromTwoVectors(plane.normal, Vec3d::UnitZ());
325 trafo.rotate(q);
327
328 std::vector<double> angles;
329 std::vector<double> lengths;
330
331 for (const std::vector<Vec3d>& border : plane.borders) {
332 if (border.size() <= 1)
333 continue;
334
335 bool done = false;
336
337 if (border.size() > 4) {
339
340 if (err < 0.05) {
341
342
343
344 bool is_polygon = border.size()>4 && border.size()<=8;
345 bool lengths_match = std::all_of(border.begin()+2, border.end(), [is_polygon](
const Vec3d& pt) {
346 return Slic3r::is_approx((pt - *((&pt)-1)).squaredNorm(), (*((&pt)-1) - *((&pt)-2)).squaredNorm(), is_polygon ? 0.01 : 0.01);
347 });
348
349 if (lengths_match && (is_polygon || border.size() > 8)) {
350 if (is_polygon) {
351
352 for (int j=0; j<int(border.size()); ++j)
354 border[j==0 ? border.size()-1 : j-1], border[j],
355 std::make_optional(
center)));
356 } else {
357
359 }
360 done = true;
361 }
362 }
363 }
364
365 if (! done) {
366
367
368
369 auto are_angles_same = [](
double a,
double b) {
return Slic3r::is_approx(a,b,0.01); };
370 auto are_lengths_same = [](
double a,
double b) {
return Slic3r::is_approx(a,b,0.01); };
371
372
373
374
375
376 auto offset_to_index = [border_size = int(border.size())](
int idx,
int offset) ->
int {
377 assert(std::abs(
offset) < border_size);
379 if (out >= border_size)
380 out = out - border_size;
381 else if (out < 0)
382 out = border_size + out;
383
384 return out;
385 };
386
387
388 angles.clear();
389 lengths.clear();
390 int first_different_angle_idx = 0;
391 for (int i=0; i<int(border.size()); ++i) {
392 const Vec3d& v2 = border[i] - (i == 0 ? border[border.size()-1] : border[i-1]);
393 const Vec3d& v1 = (i == int(border.size()-1) ? border[0] : border[i+1]) - border[i];
397
398 angles.push_back(
angle);
399 lengths.push_back(v2.norm());
400 if (first_different_angle_idx == 0 && angles.size() > 1) {
401 if (! are_angles_same(angles.back(), angles[angles.size()-2]))
402 first_different_angle_idx = angles.size()-1;
403 }
404 }
405 assert(border.size() == angles.size());
406 assert(border.size() == lengths.size());
407
408
409
410
411 int start_idx = -1;
412 bool circle = false;
413 bool first_iter = true;
414 std::vector<SurfaceFeature> circles;
415 std::vector<SurfaceFeature> edges;
416 std::vector<std::pair<int, int>> circles_idxs;
417
418 std::vector<Vec3d> single_circle;
419 double single_circle_length = 0.;
420 int first_pt_idx = offset_to_index(first_different_angle_idx, 1);
421 int i = first_pt_idx;
422 while (i != first_pt_idx || first_iter) {
423 if (are_angles_same(angles[i], angles[offset_to_index(i,-1)])
424 && i != offset_to_index(first_pt_idx, -1)
425 && i != start_idx ) {
426
427 if (! circle) {
428 circle = true;
429 single_circle.clear();
430 single_circle_length = 0.;
431 start_idx = offset_to_index(i, -2);
432 single_circle = { border[start_idx], border[offset_to_index(start_idx,1)] };
433 single_circle_length += lengths[offset_to_index(i, -1)];
434 }
435 single_circle.emplace_back(border[i]);
436 single_circle_length += lengths[i];
437 } else {
438 if (circle && single_circle.size() >= 5) {
439 single_circle.emplace_back(border[i]);
440 single_circle_length += lengths[i];
441
442 bool accept_circle = true;
443 {
444
445 int j = offset_to_index(start_idx, 3);
446 while (j != i) {
447 if (! are_lengths_same(lengths[offset_to_index(j,-1)], lengths[j])) {
448 accept_circle = false;
449 break;
450 }
451 j = offset_to_index(j, 1);
452 }
453 }
454
455 if (accept_circle) {
457
458
459
460 accept_circle &= err < 0.05;
461
462
463 accept_circle &= single_circle_length / radius > 0.9*
M_PI/2.;
464
465 if (accept_circle) {
466
467 circles_idxs.emplace_back(start_idx, i);
469 }
470 }
471 }
472 circle = false;
473 }
474
475 first_iter = false;
476 i = offset_to_index(i, 1);
477 }
478
479
480 if (circles_idxs.empty()) {
481
482 for (int i=1; i<int(border.size()); ++i)
485 } else if (circles_idxs.size() > 1 || circles_idxs.front().first != circles_idxs.front().second) {
486
487 int i = circles_idxs.front().second;
488 int circle_idx = 1;
489 while (true) {
490 i = offset_to_index(i, 1);
492 if (circle_idx < int(circles_idxs.size()) && i == circles_idxs[circle_idx].first) {
493 i = circles_idxs[circle_idx].second;
494 ++circle_idx;
495 }
496 if (i == circles_idxs.front().first)
497 break;
498 }
499 }
500
501
502 assert(std::all_of(edges.begin(), edges.end(),
503 [](
const SurfaceFeature&
f) { return f.get_type() == SurfaceFeatureType::Edge; }));
504 for (int i=edges.size()-1; i>=0; --i) {
505 const auto& [first_start, first_end] = edges[i==0 ? edges.size()-1 : i-1].get_edge();
506 const auto& [second_start, second_end] = edges[i].get_edge();
507
509 &&
Slic3r::is_approx((first_end-first_start).normalized().
dot((second_end-second_start).normalized()), 1.)) {
510
512 edges.erase(edges.begin() + i);
513 }
514 }
515
516
517 assert(std::all_of(circles.begin(), circles.end(), [](
const SurfaceFeature&
f) {
518 return f.get_type() == SurfaceFeatureType::Circle;
519 }));
520 assert(std::all_of(edges.begin(), edges.end(), [](
const SurfaceFeature&
f) {
521 return f.get_type() == SurfaceFeatureType::Edge;
522 }));
523 plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(circles.begin()),
524 std::make_move_iterator(circles.end()));
525 plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(edges.begin()),
526 std::make_move_iterator(edges.end()));
527 }
528 }
529
530
531 Vec3d cog = Vec3d::Zero();
532 size_t counter = 0;
533 for (const std::vector<Vec3d>& b : plane.borders) {
534 for (size_t i = 0; i < b.size(); ++i) {
535 cog += b[i];
536 ++counter;
537 }
538 }
539 cog /= double(counter);
541 plane.normal, cog, std::optional<Vec3d>(), plane_idx + 0.0001));
542
543 plane.borders.clear();
544 plane.borders.shrink_to_fit();
545
546 plane.features_extracted = true;
547}
#define M_PI
Definition ExtrusionSimulator.cpp:31
Definition Measure.cpp:107
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:64
@ Plane
Definition Measure.hpp:28
@ Circle
Definition Measure.hpp:27
@ Edge
Definition Measure.hpp:26
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:124
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:320
Point normal(Point pt, double scale)
Definition TreeSupport.cpp:112
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:154