#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include <vector>
#include <iomanip>
#include <random>
//using namespace std;
struct Point {
double x, y;
};
class Arc {
public:
Arc(Point center, double radius,double start,double end) : center(center), radius(radius), startangle(start), endangle(end) {}
void SetArc(double startAngle, double endAanle) {
this->startangle = NormalizeAngle(startAngle);
this->endangle = NormalizeAngle(endangle);
}
static bool FindArcIntersections(Arc& arc1, Arc& arc2, std::vector<Point>& intersections);
private:
Point center;
double radius;
double startangle;
double endangle;
double NormalizeAngle(double angle);
bool IsPointInArc(Point p);
static bool CirclesArcIntersect(Point C1, double r1, Point C2, double r2, std::vector<Point>& intersections);
};
double Arc::NormalizeAngle(double angle) {
while (angle < 0) angle += 2 * M_PI;
while (angle >= 2 * M_PI) angle -= 2 * M_PI;
return angle;
}
bool Arc::IsPointInArc(Point p) {
double angle = atan2(p.y - center.y, p.x - center.x);
angle = NormalizeAngle(angle);
if (startangle <= endangle) {
return angle >= startangle && angle <= endangle;
}
else {
return angle >= startangle || angle <= endangle;
}
}
bool Arc::CirclesArcIntersect(Point C1, double r1, Point C2, double r2, std::vector<Point>& intersections) {
double dx = C2.x - C1.x;
double dy = C2.y - C1.y;
double distance = sqrt(dx * dx + dy * dy);
// do not intersects
if (distance > r1 + r2 || distance < fabs(r1 - r2)) {
return false;
}
double a = (r1 * r1 - r2 * r2 + distance * distance);
double h = sqrt(r1 * r1 - a * a);
//midpoint
double m_x = C1.x + a * (dx / distance);
double m_y = C1.y + a * (dy / distance);
//insection coordinates p q
double p_x = m_x + h * (dy / distance);
double p_y = m_y - h * (dx / distance);
double q_x = m_x - h * (dy / distance);
double q_y = m_y + h * (dx / distance);
intersections.push_back({ p_x,p_y });
if (distance != r1 + r2) {
intersections.push_back({ q_x,q_y });
}
return true;
}
bool Arc::FindArcIntersections(Arc& arc1, Arc& arc2, std::vector<Point>& intersections) {
std::vector<Point> circleintersections;
if (!CirclesArcIntersect(arc1.center, arc1.radius, arc2.center, arc2.radius, circleintersections)) {
return false;
}
for (const Point& p : circleintersections) {
if (arc1.IsPointInArc(p) && arc2.IsPointInArc(p)) {
intersections.push_back(p);
}
}
return !intersections.empty();
}
static double RandomDouble(double min, double max) {
static std::mt19937 generator(static_cast<unsigned int>(std::time(nullptr)));
std::uniform_real_distribution<double> distribution(min, max);
return distribution(generator);
}
static void GenerateTest() {
int num_tests = 1000;
double min = -1.0, max = 1.0;
for (int i = 0; i < num_tests; i++) {
Point center1 = { RandomDouble(min, max), RandomDouble(min, max) };
Point center2 = { RandomDouble(min, max), RandomDouble(min, max) };
double radius1 = RandomDouble(1, 5);
double radius2 = RandomDouble(1, 5);
double startangle1 = (RandomDouble(0, 360)) * M_PI / 180.0;
double endangle1 = (RandomDouble(0, 180)) * M_PI / 180.0;
double startangle2 = (RandomDouble(0, 360)) * M_PI / 180.0;
double endangle2 = (RandomDouble(0, 180)) * M_PI / 180.0;
Arc arc1(center1, radius1, startangle1, endangle1);
Arc arc2(center2, radius2, startangle2, endangle2);
std::vector<Point> arcintersections;
std::cout << "Test " << i + 1 << ": \n";
std::cout << std::fixed << std::setprecision(2);
std::cout << "Arc1 cneter: (" << center1.x << ", " << center1.y << "),radius: " << radius1 << std::endl;
std::cout << "Arc1 start angle: " << startangle1 << ",endangle: " << endangle1 << std::endl;
std::cout << "Arc2 cneter: (" << center2.x << ", " << center2.y << "),radius: " << radius2 << std::endl;
std::cout << "Arc2 start angle: " << startangle2 << ",endangle: " << endangle2 << std::endl;
if (Arc::FindArcIntersections(arc1, arc2, arcintersections)) {
for (const Point& p : arcintersections) {
std::cout << "arc1 and arc2 inersect at:(" << p.x << ", " << p.y << ")" << std::endl;
}
std::cout << std::endl;
}
else {
std::cout << "arc1 and arc2 do not intersect.\n" << std::endl;
}
}
}
int main()
{
GenerateTest();
return 0;
}
圆弧与圆弧交点
最新推荐文章于 2024-08-20 16:47:30 发布