线段与圆弧交点


#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;
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

康康今天学习了么

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值