使用CGAL计算直线和圆的交点

发布时间 2023-10-17 17:03:18作者: 小弧光

 

#include <vector>
#include <iostream>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Ray_2.h>
#include <CGAL/Polygon_2.h>
#include <CGAL/intersections.h>

typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Vector_2 Vector_2;
typedef Kernel::Segment_2 Segment_2;

typedef Kernel::Circle_2 Circle_2;

typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Line_2 Line_2;

std::vector<Point_2> lineCircleIntersect(const Point_2 &p1, const Point_2 &p2, const Point_2 &circle_origin, double circle_radius)
{
    std::vector<Point_2> points_out;
    Line_2 line(p1, p2);
    std::cout << "直线: " << line << std::endl;

    auto result = CGAL::intersection(line, Line_2(circle_origin, circle_origin + (p2 - p1).perpendicular(CGAL::LEFT_TURN)));
    const Point_2 *point_intersect = boost::get<Point_2>(&*result); // Output the intersection point
    std::cout << "垂线和直线的交点: " << *point_intersect << std::endl;
    Segment_2 seg(p1, p2);
    auto seg_len = CGAL::approximate_sqrt(seg.squared_length());
    std::cout << "线段长度: " << seg_len << std::endl;

    Vector_2 unit_vector  = (p2 - p1) / seg_len;
    std::cout << "直线单位向量: " <<  unit_vector<< std::endl;

    auto distance = (*point_intersect - circle_origin).squared_length();
    std::cout << "圆心到直线的平方距离: " <<  distance<< std::endl;

    if (distance >  CGAL::square(circle_radius)) {
        std::cout << "没有交点" << std::endl;
        return points_out;
    }

    // bool is_on_line = line.has_on(circle_origin); // 圆心在直线上
    // if (is_on_line)
    // {
    //     std::cout << "圆心在直线上" << std::endl;

    //     points_out.push_back(circle_origin + unit_vector * circle_radius);
    //     points_out.push_back(circle_origin - unit_vector * circle_radius);
    //     return points_out;
    // }

    // 直线和圆相切
    if ((*point_intersect - circle_origin).squared_length() == CGAL::square(circle_radius))
    {
        std::cout << "相切,一个点" << std::endl;
        points_out.push_back(*point_intersect);

        return points_out;
    }
    else
    {
        std::cout << "两个点" << std::endl;
        auto len_on_line =  CGAL::square(circle_radius) - CGAL::square(distance);
        std::cout << "直线上的截线段长度平方:" << len_on_line<< std::endl;
        points_out.push_back(*point_intersect + unit_vector * CGAL::approximate_sqrt(len_on_line));
        points_out.push_back(*point_intersect - unit_vector * CGAL::approximate_sqrt( len_on_line));

        return points_out;
    }
}

int main()
{
    // Point_2 start_point(-1, -1);
    // Point_2 end_point(1, -1);
    // Point_2 circle_origin(0, 0);
    // double radius = 2;

    // Point_2 start_point(-1, 0);
    // Point_2 end_point(1, 0);
    // Point_2 circle_origin(0, 0);
    // double radius = 1;

    Point_2 start_point(-1, -1);
    Point_2 end_point(1, -1);
    Point_2 circle_origin(0, 0);
    double radius = 1;

    // Point_2 start_point(-1, -2);
    // Point_2 end_point(1, -2);
    // Point_2 circle_origin(0, 0);
    // double radius = 1;

    auto points = lineCircleIntersect(start_point, end_point, circle_origin, radius);
    std::cout << "points: "<< std::endl;
    for (auto p : points)
    {
        std::cout << p << std::endl;
    }

    return 0;
}

// clang++ main.cpp -lgmp -lmpfr