#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include <vector>
#include <iomanip>
#include <random>
struct Point {
double x, y;
};
class Arc {
public:
Arc(Point center, double radius) : center(center), radius(radius), startangle(0), endangle(2 * M_PI) {};
void SetArc(double startAngle, double endAanle) {
this->startangle = NormalizeAngle(startAngle);
this->endangle = NormalizeAngle(endangle);
}
bool FindInterSections(Point A, Point B, std::vector<Point>& intersections);
private:
Point center;
double radius;
double startangle;
double endangle;
double NormalizeAngle(double angle);
bool IsPointInArc(Point p);
};
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::FindInterSections(Point p1, Point p2, std::vector<Point>& intersections) {
double dx = p2.x - p1.x;
double dy = p2.y - p1.y;
double fx = p1.x - center.x;
double fy = p1.y - center.y;
double a = dx * dx + dy * dy;
double b = 2 * (fx * dx + fy * dy);
double c = (fx * fx + fy * fy) - radius * radius;
double det = b * b - 4 * a * c;
if (det < 0) {
return false;
}
double t1 = (-b - sqrt(det)) / (2 * a);
double t2 = (-b + sqrt(det)) / (2 * a);
if (t1 >= 0 && t1 <= 1) {
Point p = { p1.x + t1 * dx,p1.y + t1 * dy };
if (IsPointInArc(p)) intersections.push_back(p);
}
if (t2 >= 0 && t2 <= 1 && det > 0) {
Point p = { p1.x + t2 * dx,p1.y + t2 * dy };
if (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 = -100.0, max = 100.0;
for (int i = 0; i < num_tests; i++) {
Point line_start = { RandomDouble(min, max), RandomDouble(min, max) };
Point line_end = { RandomDouble(min, max), RandomDouble(min, max) };
Point center = { RandomDouble(min, max), RandomDouble(min, max) };
double radius = RandomDouble(1, 50);
double startangle = (RandomDouble(0, 360)) * M_PI / 180.0;
double endangle = startangle + (RandomDouble(0, 180)) * M_PI / 180.0;
Arc circle_arc(center, radius);
std::vector<Point> intersections;
std::cout << "Test " << i + 1 << ": \n";
std::cout << std::fixed << std::setprecision(2);
std::cout << "Line : (" << line_start.x << ", " << line_start.y << ") to (" << line_end.x << ", " << line_end.y << ")\n";
std::cout << "Arc cneter: (" << center.x << ", " << center.y << "),radius: " << radius << std::endl;
std::cout << "Arc start angle: " << startangle << ",endangle: " << endangle << std::endl;
if (circle_arc.FindInterSections(line_start, line_end, intersections)) {
std::cout << "The circleArc and the line segment intersect at:" << std::endl;
for (const Point& p : intersections) {
std::cout << std::fixed << std::setprecision(2);
std::cout << "(" << p.x << "," << p.y << ") ";
}
std::cout << std::endl;
std::cout << std::endl;
}
else {
std::cout << "The circleArc and the line segment do not intersect.\n" << std::endl;
}
}
}
int main()
{
GenerateTest();
return 0;
}
线段与圆弧交点
于 2024-07-31 15:26:32 首次发布