OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::ArcSegment Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Circle.hpp>

Inheritance diagram for Slic3r::ArcSegment:
Collaboration diagram for Slic3r::ArcSegment:

Public Member Functions

 ArcSegment ()
 ArcSegment (Point center, double radius, Point start, Point end, ArcDirection dir)
bool is_valid () const
bool clip_start (const Point &point)
bool clip_end (const Point &point)
bool reverse ()
bool split_at (const Point &point, ArcSegment &p1, ArcSegment &p2)
bool is_point_inside (const Point &point) const
Point get_closest_point (const Point &input)
double get_polar_radians (const Point &p1) const
bool is_over_deviation (const Points &points, const double tolerance)
bool get_deviation_sum_squared (const Points &points, const double tolerance, double &sum_deviation)

Static Public Member Functions

static bool try_create_arc (const Points &points, ArcSegment &target_arc, double approximate_length, double max_radius=DEFAULT_SCALED_MAX_RADIUS, double tolerance=DEFAULT_SCALED_RESOLUTION, double path_tolerance_percent=DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE)
static bool try_create_arc (const Points3 &points, ArcSegment &target_arc, double approximate_length, double max_radius=DEFAULT_SCALED_MAX_RADIUS, double tolerance=DEFAULT_SCALED_RESOLUTION, double path_tolerance_percent=DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE)
static bool are_points_within_slice (const ArcSegment &test_arc, const Points &points)
static bool are_points_within_slice (const ArcSegment &test_arc, const Points3 &points)
static bool ray_intersects_segment (const Point &rayOrigin, const Vec2d &rayDirection, const Line &segment)
static float calc_arc_radian (Vec3f start_pos, Vec3f end_pos, Vec3f center_pos, bool is_ccw)
static float calc_arc_radius (Vec3f start_pos, Vec3f center_pos)
static float calc_arc_length (Vec3f start_pos, Vec3f end_pos, Vec3f center_pos, bool is_ccw)
static bool try_create_circle (const Point &p1, const Point &p2, const Point &p3, const double max_radius, Circle &new_circle)
static bool try_create_circle (const Points &points, const double max_radius, const double tolerance, Circle &new_circle)
static bool try_create_circle (const Points3 &points, const double max_radius, const double tolerance, Circle &new_circle)
static Vec3f calc_tangential_vector (const Vec3f &pos, const Vec3f &center_pos, const bool is_ccw)
static bool get_closest_perpendicular_point (const Point &p1, const Point &p2, const Point &c, Point &out)
static bool is_equal (double x, double y, double tolerance=ZERO_TOLERANCE)
static bool greater_than (double x, double y, double tolerance=ZERO_TOLERANCE)
static bool greater_than_or_equal (double x, double y, double tolerance=ZERO_TOLERANCE)
static bool less_than (double x, double y, double tolerance=ZERO_TOLERANCE)
static bool less_than_or_equal (double x, double y, double tolerance=ZERO_TOLERANCE)

Public Attributes

bool is_arc = false
double length = 0
double angle_radians = 0
double polar_start_theta = 0
double polar_end_theta = 0
Point start_point { Point(0,0) }
Point end_point { Point(0,0) }
ArcDirection direction = ArcDirection::Arc_Dir_unknow
Point center
double radius

Private Member Functions

void update_angle_and_length ()

Static Private Member Functions

static bool try_create_arc (const Circle &c, const Point &start_point, const Point &mid_point, const Point &end_point, ArcSegment &target_arc, double approximate_length, double path_tolerance_percent=DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE)

Detailed Description

Constructor & Destructor Documentation

◆ ArcSegment() [1/2]

Slic3r::ArcSegment::ArcSegment ( )
inline
74: Circle() {}
Circle()
Definition Circle.hpp:16

References Slic3r::Circle::Circle().

Referenced by are_points_within_slice(), are_points_within_slice(), split_at(), try_create_arc(), try_create_arc(), and try_create_arc().

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

◆ ArcSegment() [2/2]

Slic3r::ArcSegment::ArcSegment ( Point center,
double radius,
Point start,
Point end,
ArcDirection dir )
inline
75 :
77 start_point(start),
78 end_point(end),
79 direction(dir) {
80 if (radius == 0.0 ||
82 end_point == center ||
84 is_arc = false;
85 return;
86 }
88 is_arc = true;
89 }
Point start_point
Definition Circle.hpp:96
Point end_point
Definition Circle.hpp:97
ArcDirection direction
Definition Circle.hpp:98
void update_angle_and_length()
Definition Circle.cpp:267
bool is_arc
Definition Circle.hpp:91
double radius
Definition Circle.hpp:25
Point center
Definition Circle.hpp:24

References Slic3r::Circle::Circle(), Slic3r::Circle::center, direction, end_point, is_arc, Slic3r::Circle::radius, start_point, and update_angle_and_length().

Here is the call graph for this function:

Member Function Documentation

◆ are_points_within_slice() [1/2]

bool Slic3r::ArcSegment::are_points_within_slice ( const ArcSegment & test_arc,
const Points & points )
static
414{
415 //BBS: Check all the points and see if they fit inside of the angles
416 double previous_polar = test_arc.polar_start_theta;
417 bool will_cross_zero = false;
418 bool crossed_zero = false;
419 const int point_count = points.size();
420
421 Vec2d start_norm(((double)test_arc.start_point.x() - (double)test_arc.center.x()) / test_arc.radius,
422 ((double)test_arc.start_point.y() - (double)test_arc.center.y()) / test_arc.radius);
423 Vec2d end_norm(((double)test_arc.end_point.x() - (double)test_arc.center.x()) / test_arc.radius,
424 ((double)test_arc.end_point.y() - (double)test_arc.center.y()) / test_arc.radius);
425
426 if (test_arc.direction == ArcDirection::Arc_Dir_CCW)
427 will_cross_zero = test_arc.polar_start_theta > test_arc.polar_end_theta;
428 else
429 will_cross_zero = test_arc.polar_start_theta < test_arc.polar_end_theta;
430
431 //BBS: check if point 1 to point 2 cross zero
432 double polar_test;
433 for (int index = point_count - 2; index < point_count; index++)
434 {
435 if (index < point_count - 1)
436 polar_test = test_arc.get_polar_radians(points[index]);
437 else
438 polar_test = test_arc.polar_end_theta;
439
440 //BBS: First ensure the test point is within the arc
441 if (test_arc.direction == ArcDirection::Arc_Dir_CCW)
442 {
443 //BBS: Only check to see if we are within the arc if this isn't the endpoint
444 if (index < point_count - 1) {
445 if (will_cross_zero) {
446 if (!(polar_test > test_arc.polar_start_theta || polar_test < test_arc.polar_end_theta))
447 return false;
448 } else if (!(test_arc.polar_start_theta < polar_test && polar_test < test_arc.polar_end_theta))
449 return false;
450 }
451 //BBS: check the angles are increasing
452 if (previous_polar > polar_test) {
453 if (!will_cross_zero)
454 return false;
455
456 //BBS: Allow the angle to cross zero once
457 if (crossed_zero)
458 return false;
459 crossed_zero = true;
460 }
461 } else {
462 if (index < point_count - 1) {
463 if (will_cross_zero) {
464 if (!(polar_test < test_arc.polar_start_theta || polar_test > test_arc.polar_end_theta))
465 return false;
466 } else if (!(test_arc.polar_start_theta > polar_test && polar_test > test_arc.polar_end_theta))
467 return false;
468 }
469 //BBS: Now make sure the angles are decreasing
470 if (previous_polar < polar_test)
471 {
472 if (!will_cross_zero)
473 return false;
474 //BBS: Allow the angle to cross zero once
475 if (crossed_zero)
476 return false;
477 crossed_zero = true;
478 }
479 }
480
481 // BBS: check if the segment intersects either of the vector from the center of the circle to the endpoints of the arc
482 Line segmemt(points[index - 1], points[index]);
483 if ((index != 1 && ray_intersects_segment(test_arc.center, start_norm, segmemt)) ||
484 (index != point_count - 1 && ray_intersects_segment(test_arc.center, end_norm, segmemt)))
485 return false;
486 previous_polar = polar_test;
487 }
488 //BBS: Ensure that all arcs that cross zero
489 if (will_cross_zero != crossed_zero)
490 return false;
491 return true;
492}
static bool ray_intersects_segment(const Point &rayOrigin, const Vec2d &rayDirection, const Line &segment)
Definition Circle.cpp:576
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
@ Arc_Dir_CCW
Definition Circle.hpp:63

References ArcSegment(), Slic3r::Arc_Dir_CCW, Slic3r::Circle::center, direction, end_point, Slic3r::Circle::get_polar_radians(), polar_end_theta, polar_start_theta, Slic3r::Circle::radius, ray_intersects_segment(), and start_point.

Referenced by try_create_arc(), and try_create_arc().

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

◆ are_points_within_slice() [2/2]

bool Slic3r::ArcSegment::are_points_within_slice ( const ArcSegment & test_arc,
const Points3 & points )
static
495{
496 //BBS: Check all the points and see if they fit inside of the angles
497 double previous_polar = test_arc.polar_start_theta;
498 bool will_cross_zero = false;
499 bool crossed_zero = false;
500 const int point_count = points.size();
501
502 Vec2d start_norm(((double)test_arc.start_point.x() - (double)test_arc.center.x()) / test_arc.radius,
503 ((double)test_arc.start_point.y() - (double)test_arc.center.y()) / test_arc.radius);
504 Vec2d end_norm(((double)test_arc.end_point.x() - (double)test_arc.center.x()) / test_arc.radius,
505 ((double)test_arc.end_point.y() - (double)test_arc.center.y()) / test_arc.radius);
506
507 if (test_arc.direction == ArcDirection::Arc_Dir_CCW)
508 will_cross_zero = test_arc.polar_start_theta > test_arc.polar_end_theta;
509 else
510 will_cross_zero = test_arc.polar_start_theta < test_arc.polar_end_theta;
511
512 //BBS: check if point 1 to point 2 cross zero
513 double polar_test;
514 for (int index = point_count - 2; index < point_count; index++)
515 {
516 if (index < point_count - 1)
517 polar_test = test_arc.get_polar_radians(points[index].to_point());
518 else
519 polar_test = test_arc.polar_end_theta;
520
521 //BBS: First ensure the test point is within the arc
522 if (test_arc.direction == ArcDirection::Arc_Dir_CCW)
523 {
524 //BBS: Only check to see if we are within the arc if this isn't the endpoint
525 if (index < point_count - 1) {
526 if (will_cross_zero) {
527 if (!(polar_test > test_arc.polar_start_theta || polar_test < test_arc.polar_end_theta))
528 return false;
529 } else if (!(test_arc.polar_start_theta < polar_test && polar_test < test_arc.polar_end_theta))
530 return false;
531 }
532 //BBS: check the angles are increasing
533 if (previous_polar > polar_test) {
534 if (!will_cross_zero)
535 return false;
536
537 //BBS: Allow the angle to cross zero once
538 if (crossed_zero)
539 return false;
540 crossed_zero = true;
541 }
542 } else {
543 if (index < point_count - 1) {
544 if (will_cross_zero) {
545 if (!(polar_test < test_arc.polar_start_theta || polar_test > test_arc.polar_end_theta))
546 return false;
547 } else if (!(test_arc.polar_start_theta > polar_test && polar_test > test_arc.polar_end_theta))
548 return false;
549 }
550 //BBS: Now make sure the angles are decreasing
551 if (previous_polar < polar_test)
552 {
553 if (!will_cross_zero)
554 return false;
555 //BBS: Allow the angle to cross zero once
556 if (crossed_zero)
557 return false;
558 crossed_zero = true;
559 }
560 }
561
562 // BBS: check if the segment intersects either of the vector from the center of the circle to the endpoints of the arc
563 Line segmemt(points[index - 1].to_point(), points[index].to_point());
564 if ((index != 1 && ray_intersects_segment(test_arc.center, start_norm, segmemt)) ||
565 (index != point_count - 1 && ray_intersects_segment(test_arc.center, end_norm, segmemt)))
566 return false;
567 previous_polar = polar_test;
568 }
569 //BBS: Ensure that all arcs that cross zero
570 if (will_cross_zero != crossed_zero)
571 return false;
572 return true;
573}
Point to_point(const stbtt__point &point)
Definition Emboss.cpp:911

References ArcSegment(), Slic3r::Arc_Dir_CCW, Slic3r::Circle::center, direction, end_point, Slic3r::Circle::get_polar_radians(), polar_end_theta, polar_start_theta, Slic3r::Circle::radius, ray_intersects_segment(), and start_point.

Here is the call graph for this function:

◆ calc_arc_length()

float Slic3r::ArcSegment::calc_arc_length ( Vec3f start_pos,
Vec3f end_pos,
Vec3f center_pos,
bool is_ccw )
static
629{
630 return calc_arc_radius(start_pos, center_pos) * calc_arc_radian(start_pos, end_pos, center_pos, is_ccw);
631}
static float calc_arc_radian(Vec3f start_pos, Vec3f end_pos, Vec3f center_pos, bool is_ccw)
Definition Circle.cpp:596
static float calc_arc_radius(Vec3f start_pos, Vec3f center_pos)
Definition Circle.cpp:620
static bool is_ccw(const Polygon &poly)
Definition Geometry.hpp:66

References calc_arc_radian(), calc_arc_radius(), and Slic3r::Geometry::is_ccw().

Referenced by Slic3r::CoolingBuffer::parse_layer_gcode().

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

◆ calc_arc_radian()

float Slic3r::ArcSegment::calc_arc_radian ( Vec3f start_pos,
Vec3f end_pos,
Vec3f center_pos,
bool is_ccw )
static
597{
598 Vec3f delta1 = center_pos - start_pos;
599 Vec3f delta2 = center_pos - end_pos;
600 // only consider arc in x-y plane, so clean z distance
601 delta1(2,0) = 0;
602 delta2(2,0) = 0;
603
604 float radian;
605 if ((delta1 - delta2).norm() < 1e-6) {
606 // start_pos is same with end_pos, we think it's a full circle
607 radian = 2 * M_PI;
608 } else {
609 double dot = delta1.dot(delta2);
610 double cross = (double)delta1(0, 0) * (double)delta2(1, 0) - (double)delta1(1, 0) * (double)delta2(0, 0);
611 radian = atan2(cross, dot);
612 if (is_ccw)
613 radian = (radian < 0) ? 2 * M_PI + radian : radian;
614 else
615 radian = (radian < 0) ? abs(radian) : 2 * M_PI - radian;
616 }
617 return radian;
618}
#define M_PI
Definition ExtrusionSimulator.cpp:31
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
T cross(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:168
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:154

References Slic3r::cross(), Slic3r::dot(), Slic3r::Geometry::is_ccw(), and M_PI.

Referenced by calc_arc_length().

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

◆ calc_arc_radius()

float Slic3r::ArcSegment::calc_arc_radius ( Vec3f start_pos,
Vec3f center_pos )
static
621{
622 Vec3f delta1 = center_pos - start_pos;
623 delta1(2,0) = 0;
624 return delta1.norm();
625}

Referenced by calc_arc_length().

Here is the caller graph for this function:

◆ calc_tangential_vector()

Vec3f Slic3r::Circle::calc_tangential_vector ( const Vec3f & pos,
const Vec3f & center_pos,
const bool is_ccw )
staticinherited
202{
203 Vec3f dir = center_pos - pos;
204 dir(2,0) = 0;
205 dir.normalize();
206 Vec3f res;
207 if (is_ccw)
208 res = { dir(1, 0), -dir(0, 0), 0.0f };
209 else
210 res = { -dir(1, 0), dir(0, 0), 0.0f };
211 return res;
212}
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16

References Slic3r::Geometry::is_ccw().

Here is the call graph for this function:

◆ clip_end()

bool Slic3r::ArcSegment::clip_end ( const Point & point)
235{
236 if (!is_valid() || point == center || !is_point_inside(point))
237 return false;
240 return true;
241}
bool is_valid() const
Definition Circle.hpp:100
bool is_point_inside(const Point &point) const
Definition Circle.cpp:253
Point get_closest_point(const Point &input)
Definition Circle.hpp:27

References Slic3r::Circle::center, end_point, Slic3r::Circle::get_closest_point(), is_point_inside(), is_valid(), and update_angle_and_length().

Here is the call graph for this function:

◆ clip_start()

bool Slic3r::ArcSegment::clip_start ( const Point & point)
226{
227 if (!is_valid() || point == center || !is_point_inside(point))
228 return false;
231 return true;
232}

References Slic3r::Circle::center, Slic3r::Circle::get_closest_point(), is_point_inside(), is_valid(), start_point, and update_angle_and_length().

Here is the call graph for this function:

◆ get_closest_perpendicular_point()

bool Slic3r::Circle::get_closest_perpendicular_point ( const Point & p1,
const Point & p2,
const Point & c,
Point & out )
staticinherited
145{
146 double x1 = p1.x();
147 double y1 = p1.y();
148 double x2 = p2.x();
149 double y2 = p2.y();
150 double x_dif = x2 - x1;
151 double y_dif = y2 - y1;
152 //BBS: [(Cx - Ax)(Bx - Ax) + (Cy - Ay)(By - Ay)] / [(Bx - Ax) ^ 2 + (By - Ay) ^ 2]
153 double num = (c[0] - x1) * x_dif + (c[1] - y1) * y_dif;
154 double denom = (x_dif * x_dif) + (y_dif * y_dif);
155 double t = num / denom;
156
157 //BBS: Considering this a failure if t == 0 or t==1 within tolerance. In that case we hit the endpoint, which is OK.
159 return false;
160
161 out[0] = x1 + t * (x2 - x1);
162 out[1] = y1 + t * (y2 - y1);
163 return true;
164}
static bool greater_than_or_equal(double x, double y, double tolerance=ZERO_TOLERANCE)
Definition Circle.hpp:49
static bool less_than_or_equal(double x, double y, double tolerance=ZERO_TOLERANCE)
Definition Circle.hpp:55

References greater_than_or_equal(), and less_than_or_equal().

Referenced by get_deviation_sum_squared(), and is_over_deviation().

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

◆ get_closest_point()

Point Slic3r::Circle::get_closest_point ( const Point & input)
inlineinherited
27 {
28 Vec2d v = (input - center).cast<double>().normalized();
29 return (center + (v * radius).cast<coord_t>());
30 }
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References Slic3r::cast(), center, and radius.

Referenced by Slic3r::ArcSegment::clip_end(), Slic3r::ArcSegment::clip_start(), and Slic3r::ArcSegment::split_at().

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

◆ get_deviation_sum_squared()

bool Slic3r::Circle::get_deviation_sum_squared ( const Points & points,
const double tolerance,
double & sum_deviation )
inherited
167{
168 total_deviation = 0;
169 Point temp;
170 double distance_from_center, deviation;
171 // BBS: skip the first and last points since they are on the circle
172 for (int index = 1; index < points.size() - 1; index++)
173 {
174 //BBS: make sure the length from the center of our circle to the test point is
175 // at or below our max distance.
176 temp = points[index] - center;
177 distance_from_center = sqrt((double)temp.x() * (double)temp.x() + (double)temp.y() * (double)temp.y());
178 deviation = std::fabs(distance_from_center - radius);
179 total_deviation += deviation * deviation;
180 if (deviation > tolerance)
181 return false;
182
183 }
184 Point closest_point;
185 //BBS: check the point perpendicular from the segment to the circle's center
186 for (int index = 0; index < points.size() - 1; index++)
187 {
188 if (get_closest_perpendicular_point(points[index], points[(size_t)index + 1], center, closest_point)) {
189 temp = closest_point - center;
190 distance_from_center = sqrt((double)temp.x() * (double)temp.x() + (double)temp.y() * (double)temp.y());
191 deviation = std::fabs(distance_from_center - radius);
192 total_deviation += deviation * deviation;
193 if (deviation > tolerance)
194 return false;
195 }
196 }
197 return true;
198}
static bool get_closest_perpendicular_point(const Point &p1, const Point &p2, const Point &c, Point &out)
Definition Circle.cpp:144
Kernel::Point_3 Point
Definition MeshRepair.cpp:81

References center, get_closest_perpendicular_point(), and radius.

Referenced by try_create_circle().

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

◆ get_polar_radians()

double Slic3r::Circle::get_polar_radians ( const Point & p1) const
inherited
109{
110 double polar_radians = atan2(p1.y() - center.y(), p1.x() - center.x());
111 if (polar_radians < 0)
112 polar_radians = (2.0 * PI) + polar_radians;
113 return polar_radians;
114}
static constexpr double PI
Definition libslic3r.h:81

References center, and PI.

Referenced by Slic3r::ArcSegment::are_points_within_slice(), Slic3r::ArcSegment::are_points_within_slice(), Slic3r::ArcSegment::is_point_inside(), Slic3r::ArcSegment::try_create_arc(), and Slic3r::ArcSegment::update_angle_and_length().

Here is the caller graph for this function:

◆ greater_than()

bool Slic3r::Circle::greater_than ( double x,
double y,
double tolerance = ZERO_TOLERANCE )
inlinestaticinherited
46 {
47 return x > y && !Circle::is_equal(x, y, tolerance);
48 };
static bool is_equal(double x, double y, double tolerance=ZERO_TOLERANCE)
Definition Circle.hpp:42

References is_equal(), and Slic3r::ZERO_TOLERANCE.

Here is the call graph for this function:

◆ greater_than_or_equal()

bool Slic3r::Circle::greater_than_or_equal ( double x,
double y,
double tolerance = ZERO_TOLERANCE )
inlinestaticinherited
49 {
50 return x > y || Circle::is_equal(x, y, tolerance);
51 };

References is_equal(), and Slic3r::ZERO_TOLERANCE.

Referenced by get_closest_perpendicular_point().

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

◆ is_equal()

bool Slic3r::Circle::is_equal ( double x,
double y,
double tolerance = ZERO_TOLERANCE )
inlinestaticinherited
42 {
43 double abs_difference = std::fabs(x - y);
44 return abs_difference < tolerance;
45 };

References Slic3r::ZERO_TOLERANCE.

Referenced by greater_than(), greater_than_or_equal(), less_than(), and less_than_or_equal().

Here is the caller graph for this function:

◆ is_over_deviation()

bool Slic3r::Circle::is_over_deviation ( const Points & points,
const double tolerance )
inherited
117{
118 Point closest_point;
119 Point temp;
120 double distance_from_center;
121 // BBS: skip the first and last points since they has fit perfectly.
122 for (size_t index = 0; index < points.size() - 1; index++)
123 {
124 if (index != 0)
125 {
126 //BBS: check fitting tolerance
127 temp = points[index] - center;
128 distance_from_center = sqrt((double)temp.x() * (double)temp.x() + (double)temp.y() * (double)temp.y());
129 if (std::fabs(distance_from_center - radius) > tolerance)
130 return true;
131 }
132
133 //BBS: Check the point perpendicular from the segment to the circle's center
134 if (get_closest_perpendicular_point(points[index], points[(size_t)index + 1], center, closest_point)) {
135 temp = closest_point - center;
136 distance_from_center = sqrt((double)temp.x() * (double)temp.x() + (double)temp.y() * (double)temp.y());
137 if (std::fabs(distance_from_center - radius) > tolerance)
138 return true;
139 }
140 }
141 return false;
142}

References center, get_closest_perpendicular_point(), and radius.

Referenced by try_create_circle().

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

◆ is_point_inside()

bool Slic3r::ArcSegment::is_point_inside ( const Point & point) const
254{
255 double polar_theta = get_polar_radians(point);
256 double radian_delta = polar_theta - polar_start_theta;
257 if (radian_delta > 0 && direction == ArcDirection::Arc_Dir_CW)
258 radian_delta = radian_delta - 2 * M_PI;
259 else if (radian_delta < 0 && direction == ArcDirection::Arc_Dir_CCW)
260 radian_delta = radian_delta + 2 * M_PI;
261
263 radian_delta > 0.0 && radian_delta < angle_radians :
264 radian_delta < 0.0 && radian_delta > angle_radians);
265}
double polar_start_theta
Definition Circle.hpp:94
double angle_radians
Definition Circle.hpp:93
double get_polar_radians(const Point &p1) const
Definition Circle.cpp:108
@ Arc_Dir_CW
Definition Circle.hpp:64

References angle_radians, Slic3r::Arc_Dir_CCW, Slic3r::Arc_Dir_CW, direction, Slic3r::Circle::get_polar_radians(), M_PI, and polar_start_theta.

Referenced by clip_end(), clip_start(), and split_at().

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

◆ is_valid()

bool Slic3r::ArcSegment::is_valid ( ) const
inline
100{ return is_arc; }

References is_arc.

Referenced by clip_end(), clip_start(), reverse(), and split_at().

Here is the caller graph for this function:

◆ less_than()

bool Slic3r::Circle::less_than ( double x,
double y,
double tolerance = ZERO_TOLERANCE )
inlinestaticinherited
52 {
53 return x < y && !Circle::is_equal(x, y, tolerance);
54 };

References is_equal(), and Slic3r::ZERO_TOLERANCE.

Here is the call graph for this function:

◆ less_than_or_equal()

bool Slic3r::Circle::less_than_or_equal ( double x,
double y,
double tolerance = ZERO_TOLERANCE )
inlinestaticinherited
55 {
56 return x < y || Circle::is_equal(x, y, tolerance);
57 };

References is_equal(), and Slic3r::ZERO_TOLERANCE.

Referenced by get_closest_perpendicular_point().

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

◆ ray_intersects_segment()

bool Slic3r::ArcSegment::ray_intersects_segment ( const Point & rayOrigin,
const Vec2d & rayDirection,
const Line & segment )
static
577{
578 Vec2d v1 = Vec2d(rayOrigin.x() - segment.a.x(), rayOrigin.y() - segment.a.y());
579 Vec2d v2 = Vec2d(segment.b.x() - segment.a.x(), segment.b.y() - segment.a.y());
580 Vec2d v3 = Vec2d(-rayDirection(1), rayDirection(0));
581
582 double dot = v2(0) * v3(0) + v2(1) * v3(1);
583 if (std::fabs(dot) < SCALED_EPSILON)
584 return false;
585
586 double t1 = (v2(0) * v1(1) - v2(1) * v1(0)) / dot;
587 double t2 = (v1(0) * v3(0) + v1(1) * v3(1)) / dot;
588
589 if (t1 >= 0.0 && (t2 >= 0.0 && t2 <= 1.0))
590 return true;
591
592 return false;
593}
#define SCALED_EPSILON
Definition libslic3r.h:109
void segment(CGALMesh &src, std::vector< CGALMesh > &dst, double smoothing_alpha=0.5, int segment_number=5)
Definition MeshBoolean.cpp:480

References Slic3r::dot(), and SCALED_EPSILON.

Referenced by are_points_within_slice(), and are_points_within_slice().

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

◆ reverse()

bool Slic3r::ArcSegment::reverse ( )
215{
216 if (!is_valid())
217 return false;
218 std::swap(start_point, end_point);
220 angle_radians *= -1.0;
222 return true;
223}
double polar_end_theta
Definition Circle.hpp:95
ArcDirection
Definition Circle.hpp:61

References angle_radians, Slic3r::Arc_Dir_CCW, Slic3r::Arc_Dir_CW, direction, end_point, is_valid(), polar_end_theta, polar_start_theta, and start_point.

Here is the call graph for this function:

◆ split_at()

bool Slic3r::ArcSegment::split_at ( const Point & point,
ArcSegment & p1,
ArcSegment & p2 )
244{
245 if (!is_valid() || point == center || !is_point_inside(point))
246 return false;
247 Point segment_point = get_closest_point(point);
248 p1 = ArcSegment(center, radius, this->start_point, segment_point, this->direction);
249 p2 = ArcSegment(center, radius, segment_point, this->end_point, this->direction);
250 return true;
251}
ArcSegment()
Definition Circle.hpp:74

References ArcSegment(), Slic3r::Circle::center, direction, end_point, Slic3r::Circle::get_closest_point(), is_point_inside(), is_valid(), Slic3r::Circle::radius, and start_point.

Here is the call graph for this function:

◆ try_create_arc() [1/3]

bool Slic3r::ArcSegment::try_create_arc ( const Circle & c,
const Point & start_point,
const Point & mid_point,
const Point & end_point,
ArcSegment & target_arc,
double approximate_length,
double path_tolerance_percent = DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE )
staticprivate
338{
339 double polar_start_theta = c.get_polar_radians(start_point);
340 double polar_mid_theta = c.get_polar_radians(mid_point);
341 double polar_end_theta = c.get_polar_radians(end_point);
342
343 double angle_radians = 0;
345 //BBS: calculate the direction of the arc
347 if (polar_start_theta < polar_mid_theta && polar_mid_theta < polar_end_theta) {
350 } else if ((0.0 <= polar_mid_theta && polar_mid_theta < polar_start_theta) ||
351 (polar_end_theta < polar_mid_theta && polar_mid_theta < (2.0 * PI))) {
354 }
355 } else if (polar_start_theta > polar_end_theta) {
356 if ((polar_start_theta < polar_mid_theta && polar_mid_theta < (2.0 * PI)) ||
357 (0.0 < polar_mid_theta && polar_mid_theta < polar_end_theta)) {
360 } else if (polar_end_theta < polar_mid_theta && polar_mid_theta < polar_start_theta) {
363 }
364 }
365
366 // BBS: this doesn't always work.. in rare situations, the angle may be backward
368 return false;
369
370 // BBS: Check the length against the original length.
371 // This can trigger simply due to the differing path lengths
372 // but also could indicate that the vector calculation above
373 // got wrong direction
374 double arc_length = c.radius * angle_radians;
375 double difference = (arc_length - approximate_length) / approximate_length;
376 if (std::fabs(difference) >= path_tolerance_percent)
377 {
378 // BBS: So it's possible that vector calculation above got wrong direction.
379 // This can happen if there is a crazy arrangement of points
380 // extremely close to eachother. They have to be close enough to
381 // break our other checks. However, we may be able to salvage this.
382 // see if an arc moving in the opposite direction had the correct length.
383
384 //BBS: Find the rest of the angle across the circle
385 double test_radians = std::fabs(angle_radians - 2 * PI);
386 // Calculate the length of that arc
387 double test_arc_length = c.radius * test_radians;
388 difference = (test_arc_length - approximate_length) / approximate_length;
389 if (std::fabs(difference) >= path_tolerance_percent)
390 return false;
391 //BBS: Set the new length and flip the direction (but not the angle)!
392 arc_length = test_arc_length;
394 }
395
397 angle_radians *= -1.0;
398
399 target_arc.is_arc = true;
400 target_arc.direction = direction;
401 target_arc.center = c.center;
402 target_arc.radius = c.radius;
403 target_arc.start_point = start_point;
404 target_arc.end_point = end_point;
405 target_arc.length = arc_length;
406 target_arc.angle_radians = angle_radians;
407 target_arc.polar_start_theta = polar_start_theta;
408 target_arc.polar_end_theta = polar_end_theta;
409
410 return true;
411}
#define EPSILON
Definition ColorUtils.cpp:64
@ Arc_Dir_unknow
Definition Circle.hpp:62

References ArcSegment(), Slic3r::Circle::Circle(), angle_radians, Slic3r::Arc_Dir_CCW, Slic3r::Arc_Dir_CW, Slic3r::Arc_Dir_unknow, Slic3r::Circle::center, direction, end_point, EPSILON, Slic3r::Circle::get_polar_radians(), is_arc, length, PI, polar_end_theta, polar_start_theta, Slic3r::Circle::radius, and start_point.

Here is the call graph for this function:

◆ try_create_arc() [2/3]

bool Slic3r::ArcSegment::try_create_arc ( const Points & points,
ArcSegment & target_arc,
double approximate_length,
double max_radius = DEFAULT_SCALED_MAX_RADIUS,
double tolerance = DEFAULT_SCALED_RESOLUTION,
double path_tolerance_percent = DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE )
static
287{
288 Circle test_circle = (Circle)target_arc;
289 if (!Circle::try_create_circle(points, max_radius, tolerance, test_circle))
290 return false;
291
292 int mid_point_index = ((points.size() - 2) / 2) + 1;
293 ArcSegment test_arc;
294 if (!ArcSegment::try_create_arc(test_circle, points[0], points[mid_point_index], points[points.size() - 1], test_arc, approximate_length, path_tolerance_percent))
295 return false;
296
297 if (ArcSegment::are_points_within_slice(test_arc, points))
298 {
299 target_arc = test_arc;
300 return true;
301 }
302 return false;
303}
static bool are_points_within_slice(const ArcSegment &test_arc, const Points &points)
Definition Circle.cpp:413
static bool try_create_arc(const Points &points, ArcSegment &target_arc, double approximate_length, double max_radius=DEFAULT_SCALED_MAX_RADIUS, double tolerance=DEFAULT_SCALED_RESOLUTION, double path_tolerance_percent=DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE)
Definition Circle.cpp:280
static bool try_create_circle(const Point &p1, const Point &p2, const Point &p3, const double max_radius, Circle &new_circle)
Definition Circle.cpp:20

References ArcSegment(), Slic3r::Circle::Circle(), are_points_within_slice(), try_create_arc(), and Slic3r::Circle::try_create_circle().

Referenced by Slic3r::ArcFitter::do_arc_fitting(), try_create_arc(), and try_create_arc().

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

◆ try_create_arc() [3/3]

bool Slic3r::ArcSegment::try_create_arc ( const Points3 & points,
ArcSegment & target_arc,
double approximate_length,
double max_radius = DEFAULT_SCALED_MAX_RADIUS,
double tolerance = DEFAULT_SCALED_RESOLUTION,
double path_tolerance_percent = DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE )
static
312{
313 Circle test_circle = (Circle)target_arc;
314 if (!Circle::try_create_circle(points, max_radius, tolerance, test_circle))
315 return false;
316
317 int mid_point_index = ((points.size() - 2) / 2) + 1;
318 ArcSegment test_arc;
319 if (!ArcSegment::try_create_arc(test_circle, points[0].to_point(), points[mid_point_index].to_point(), points[points.size() - 1].to_point(), test_arc, approximate_length, path_tolerance_percent))
320 return false;
321
322 if (ArcSegment::are_points_within_slice(test_arc, points))
323 {
324 target_arc = test_arc;
325 return true;
326 }
327 return false;
328}

References ArcSegment(), Slic3r::Circle::Circle(), are_points_within_slice(), try_create_arc(), and Slic3r::Circle::try_create_circle().

Here is the call graph for this function:

◆ try_create_circle() [1/3]

bool Slic3r::Circle::try_create_circle ( const Point & p1,
const Point & p2,
const Point & p3,
const double max_radius,
Circle & new_circle )
staticinherited
21{
22 double x1 = p1.x();
23 double y1 = p1.y();
24 double x2 = p2.x();
25 double y2 = p2.y();
26 double x3 = p3.x();
27 double y3 = p3.y();
28
29 //BBS: use area of triangle to judge whether three points are almostly on one line
30 //Because the point is scale_ once, so area should scale_ twice.
31 if (fabs((y1 - y2) * (x1 - x3) - (y1 - y3) * (x1 - x2)) <= scale_(scale_(Parallel_area_threshold)))
32 return false;
33
34 double a = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - x3 * y2;
35 //BBS: take out to figure out how we handle very small values
36 if (fabs(a) < SCALED_EPSILON)
37 return false;
38
39 double b = (x1 * x1 + y1 * y1) * (y3 - y2)
40 + (x2 * x2 + y2 * y2) * (y1 - y3)
41 + (x3 * x3 + y3 * y3) * (y2 - y1);
42
43 double c = (x1 * x1 + y1 * y1) * (x2 - x3)
44 + (x2 * x2 + y2 * y2) * (x3 - x1)
45 + (x3 * x3 + y3 * y3) * (x1 - x2);
46
47 double center_x = -b / (2.0 * a);
48 double center_y = -c / (2.0 * a);
49
50 double delta_x = center_x - x1;
51 double delta_y = center_y - y1;
52 double radius = sqrt(delta_x * delta_x + delta_y * delta_y);
53 if (radius > max_radius)
54 return false;
55
56 new_circle.center = Point(center_x, center_y);
57 new_circle.radius = radius;
58
59 return true;
60}
#define scale_(val)
Definition libslic3r.h:106
static const double Parallel_area_threshold
Definition Circle.cpp:18

References Circle(), center, Slic3r::Parallel_area_threshold, radius, scale_, and SCALED_EPSILON.

Referenced by Slic3r::ArcSegment::try_create_arc(), Slic3r::ArcSegment::try_create_arc(), try_create_circle(), and try_create_circle().

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

◆ try_create_circle() [2/3]

bool Slic3r::Circle::try_create_circle ( const Points & points,
const double max_radius,
const double tolerance,
Circle & new_circle )
staticinherited
63{
64 size_t count = points.size();
65 size_t middle_index = count / 2;
66 // BBS: the middle point will almost always produce the best arcs with high possibility.
67 if (count == 3) {
68 return (Circle::try_create_circle(points[0], points[middle_index], points[count - 1], max_radius, new_circle)
69 && !new_circle.is_over_deviation(points, tolerance));
70 } else {
71 Point middle_point = (count % 2 == 0) ? (points[middle_index] + points[middle_index - 1]) / 2 :
72 (points[middle_index - 1] + points[middle_index + 1]) / 2;
73 if (Circle::try_create_circle(points[0], middle_point, points[count - 1], max_radius, new_circle)
74 && !new_circle.is_over_deviation(points, tolerance))
75 return true;
76 }
77
78 // BBS: Find the circle with the least deviation, if one exists.
79 Circle test_circle;
80 double least_deviation;
81 bool found_circle = false;
82 double current_deviation;
83 for (int index = 1; index < count - 1; index++)
84 {
85 if (index == middle_index)
86 // BBS: We already checked this one, and it failed. don't need to do again
87 continue;
88
89 if (Circle::try_create_circle(points[0], points[index], points[count - 1], max_radius, test_circle) && test_circle.get_deviation_sum_squared(points, tolerance, current_deviation))
90 {
91 if (!found_circle || current_deviation < least_deviation)
92 {
93 found_circle = true;
94 least_deviation = current_deviation;
95 new_circle = test_circle;
96 }
97 }
98 }
99 return found_circle;
100}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246

References Circle(), count, get_deviation_sum_squared(), is_over_deviation(), and try_create_circle().

Here is the call graph for this function:

◆ try_create_circle() [3/3]

bool Slic3r::Circle::try_create_circle ( const Points3 & points,
const double max_radius,
const double tolerance,
Circle & new_circle )
staticinherited
103{
104 return Circle::try_create_circle(to_points(points), max_radius, tolerance, new_circle);
105}
Points to_points(const ExPolygons &src)
Definition ExPolygon.hpp:222

References Circle(), Slic3r::to_points(), and try_create_circle().

Here is the call graph for this function:

◆ update_angle_and_length()

void Slic3r::ArcSegment::update_angle_and_length ( )
private

References angle_radians, Slic3r::Arc_Dir_CCW, Slic3r::Arc_Dir_CW, direction, end_point, Slic3r::Circle::get_polar_radians(), is_arc, length, M_PI, polar_end_theta, polar_start_theta, Slic3r::Circle::radius, and start_point.

Referenced by ArcSegment(), clip_end(), and clip_start().

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

Member Data Documentation

◆ angle_radians

double Slic3r::ArcSegment::angle_radians = 0

◆ center

◆ direction

◆ end_point

◆ is_arc

◆ length

double Slic3r::ArcSegment::length = 0

◆ polar_end_theta

◆ polar_start_theta

◆ radius

◆ start_point


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Circle.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Circle.cpp