圆弧与圆弧交点


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

}



  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

康康今天学习了么

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

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

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

打赏作者

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

抵扣说明:

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

余额充值