AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
// SPDX-License-Identifier: BSD-3-Clause
// Arc.cpp
// Copyright 2011, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.
#include "Arc.h"
#include "Curve.h"
void CArc::SetDirWithPoint(const Point& p)
{
double angs = atan2(m_s.y - m_c.y, m_s.x - m_c.x);
double ange = atan2(m_e.y - m_c.y, m_e.x - m_c.x);
double angp = atan2(p.y - m_c.y, p.x - m_c.x);
if (ange < angs) {
ange += 6.2831853071795864;
}
if (angp < angs - 0.0000000000001) {
angp += 6.2831853071795864;
}
if (angp > ange + 0.0000000000001) {
m_dir = false;
}
else {
m_dir = true;
}
}
double CArc::IncludedAngle() const
{
double angs = atan2(m_s.y - m_c.y, m_s.x - m_c.x);
double ange = atan2(m_e.y - m_c.y, m_e.x - m_c.x);
if (m_dir) {
// make sure ange > angs
if (ange < angs) {
ange += 6.2831853071795864;
}
}
else {
// make sure angs > ange
if (angs < ange) {
angs += 6.2831853071795864;
}
}
return fabs(ange - angs);
}
bool CArc::AlmostALine() const
{
Point mid_point = MidParam(0.5);
if (Line(m_s, m_e - m_s).Dist(mid_point) <= Point::tolerance) {
return true;
}
const double max_arc_radius = 1.0 / Point::tolerance;
double radius = m_c.dist(m_s);
if (radius > max_arc_radius) {
return true; // We don't want to produce an arc whose radius is too large.
}
return false;
}
Point CArc::MidParam(double param) const
{
/// returns a point which is 0-1 along arc
if (fabs(param) < 0.00000000000001) {
return m_s;
}
if (fabs(param - 1.0) < 0.00000000000001) {
return m_e;
}
Point p;
Point v = m_s - m_c;
v.Rotate(param * IncludedAngle());
p = v + m_c;
return p;
}
// segments - number of segments per full revolution!
// d_angle - determines the direction and the amount of the arc to draw
void CArc::GetSegments(void (*callbackfunc)(const double* p), double pixels_per_mm) const
{
if (m_s == m_e) {
return;
}
Point Va = m_s - m_c;
Point Vb = m_e - m_c;
double start_angle = atan2(Va.y, Va.x);
double end_angle = atan2(Vb.y, Vb.x);
if (m_dir) {
if (start_angle > end_angle) {
end_angle += 6.28318530717958;
}
}
else {
if (start_angle < end_angle) {
end_angle -= 6.28318530717958;
}
}
double radius = m_c.dist(m_s);
double d_angle = end_angle - start_angle;
int segments = (int)(fabs(pixels_per_mm * radius * d_angle / 6.28318530717958 + 1));
double theta = d_angle / (double)segments;
while (theta > 1.0) {
segments *= 2;
theta = d_angle / (double)segments;
}
double tangential_factor = tan(theta);
double radial_factor = 1 - cos(theta);
double x = radius * cos(start_angle);
double y = radius * sin(start_angle);
double pp[3] = {0.0, 0.0, 0.0};
for (int i = 0; i < segments + 1; i++) {
Point p = m_c + Point(x, y);
pp[0] = p.x;
pp[1] = p.y;
(*callbackfunc)(pp);
double tx = -y;
double ty = x;
x += tx * tangential_factor;
y += ty * tangential_factor;
double rx = -x;
double ry = -y;
x += rx * radial_factor;
y += ry * radial_factor;
}
}