BambuStudio/libslic3r/Circle.hpp

136 lines
4.7 KiB
C++

#ifndef slic3r_Circle_hpp_
#define slic3r_Circle_hpp_
#include "Point.hpp"
#include "Line.hpp"
namespace Slic3r {
constexpr double ZERO_TOLERANCE = 0.000005;
class Circle {
public:
Circle() {
center = Point(0,0);
radius = 0;
}
Circle(Point &p, double r) {
center = p;
radius = r;
}
Point center;
double radius;
Point get_closest_point(const Point& input) {
Vec2d v = (input - center).cast<double>().normalized();
return (center + (v * radius).cast<coord_t>());
}
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);
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);
//BBS: only support calculate on X-Y plane, Z is useless
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) {
double abs_difference = std::fabs(x - y);
return abs_difference < tolerance;
};
static bool greater_than(double x, double y, double tolerance = ZERO_TOLERANCE) {
return x > y && !Circle::is_equal(x, y, tolerance);
};
static bool greater_than_or_equal(double x, double y, double tolerance = ZERO_TOLERANCE) {
return x > y || Circle::is_equal(x, y, tolerance);
};
static bool less_than(double x, double y, double tolerance = ZERO_TOLERANCE) {
return x < y && !Circle::is_equal(x, y, tolerance);
};
static bool less_than_or_equal(double x, double y, double tolerance = ZERO_TOLERANCE){
return x < y || Circle::is_equal(x, y, tolerance);
};
};
enum class ArcDirection : unsigned char {
Arc_Dir_unknow,
Arc_Dir_CCW,
Arc_Dir_CW,
Count
};
#define DEFAULT_SCALED_MAX_RADIUS scale_(2000) // 2000mm
#define DEFAULT_SCALED_RESOLUTION scale_(0.05) // 0.05mm
#define DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE 0.05 // 5 percent
class ArcSegment: public Circle {
public:
ArcSegment(): Circle() {}
ArcSegment(Point center, double radius, Point start, Point end, ArcDirection dir) :
Circle(center, radius),
start_point(start),
end_point(end),
direction(dir) {
if (radius == 0.0 ||
start_point == center ||
end_point == center ||
start_point == end_point) {
is_arc = false;
return;
}
update_angle_and_length();
is_arc = true;
}
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;
bool is_valid() const { return is_arc; }
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;
private:
void update_angle_and_length();
public:
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 are_points_within_slice(const ArcSegment& test_arc, const Points &points);
// BBS: this function is used to detect whether a ray cross the segment
static bool ray_intersects_segment(const Point& rayOrigin, const Vec2d& rayDirection, const Line& segment);
// BBS: these three functions are used to calculate related arguments of arc in unscale_field.
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);
private:
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);
};
}
#endif