【问题标题】:CGAL Intersection Circle and Vertical Lines (not segments)CGAL 相交圆和垂直线(不是线段)
【发布时间】:2016-07-29 11:52:11
【问题描述】:

在 CGAL 中,我需要计算一组线和一组圆之间的确切交点。从圆开始(可以有无理半径但有理 squared_radius)我应该计算通过每个圆的 x_extremal_points 的垂直线(不是线段而是线)并计算每个圆与每条线的交点。

我将 CircularKernel 和 Circle_2 用于圆圈,将 Line_2 用于线条。 这是我如何计算圆和线以及如何检查它们是否相交的示例。

int main()
{

    Point_2 a = Point_2(250.5, 98.5);
    Point_2 b = Point_2(156, 139);

    //Radius is half distance ab
    Circular_k::FT aRad = CGAL::squared_distance(a, b);

    Circle_2 circle_a = Circle_2(a, aRad/4);

    Circular_arc_point_2 a_left_point = CGAL::x_extremal_point(circle_a, false);
    Circular_arc_point_2 a_right_point = CGAL::x_extremal_point(circle_a, true);

    //for example use only left extremal point of circle a
    CGAL::Bbox_2 a_left_point_bb = a_left_point.bbox();

    Line_2 a_left_line = Line_2(Point_2(a_left_point_bb.xmin(), a_left_point_bb.ymin()),
                                Point_2(a_left_point_bb.xmin(), a_left_point_bb.ymax()));

    if ( do_intersect(a_left_line, circle_a) ) {
        std::cout << "intersect";
    }
    else {
        std::cout << " do not intersect ";
    }

    return 0;
}

这个流程引发了这个异常:

CGAL error: precondition violation!
 Expression : y != 0
 File       : c:\dev\cgal-4.7\include\cgal\gmp\gmpq_type.h
 Line       : 371
 Explanation:
 Refer to the bug-reporting instructions at http://www.cgal.org/bug_report.html

我不知道如何计算交点。 另外,有没有更好的方法来计算线条?我知道 x_extremal_point 函数,但它返回 Circular_arc_point 点,我无法在不使用边界框的情况下直接构造一条穿过它们的垂直线。

【问题讨论】:

  • 我猜你不能从一个点构造一条线这就是说:a_left_point_bb 是一个退化的盒子。你想做什么?通过a_left_point的垂直线?
  • 哦!那是一个退化的盒子:/!是的,我需要一条通过 a_left_point 的垂直线。然后我需要将它与集合中的所有圆相交(在示例中只有 circle_a)以获得所有相交点。 (一种扫描线算法)使用 Line_2(Point_2(a_left_point_bb.xmin(), a_left_point_bb.ymin()), Point_2(a_left_point_bb.xmin(), 0));有用。有没有更好的计算方法?如何获得交点?
  • 您可以改为直接使用Line_2(a_left_point, Point_2(a_left_point.x(), a_left_point.y() + 1)) 避免a_left_point 的y 为0 的情况

标签: c++ computational-geometry intersection cgal


【解决方案1】:

在您的代码中,您似乎在计算圆与通过圆极值点的垂直线的交点(我忘记了边界框)。那么,(双)交点本身就是极值点...... 在全球范围内,您在介绍中说您想要计算精确的交叉点。那么你当然不应该使用边界框,根据定义,边界框会引入一些近似值。

如果我正确理解了您的文字, * 测试你的垂直线与其他圆的交点,你不需要构造线,你只需要比较两个圆的极值点的横坐标,你可以用 CGAL 圆核来做。 * 用于计算具有非有理系数的垂直线(因为其方程的形式为 x= +-sqrt(r))与另一个圆的交点,那么 CGAL 圆形内核不会为您提供预煮解决方案.该内核会有所帮助,但您仍然必须手动计算一些东西。 如果您不想打扰,那么您也可以使用 Core::Expr 作为底层数字类型的标准 CGAL 内核。它可以做“任何事情”,但速度会慢一些。

【讨论】:

  • 我真正需要的是垂直线和每个圆之间的交叉间隔(在 y 坐标上)。垂直线是从圆的极值点(最左边和最右边)和每对圆之间的交点开始计算的。在这里,我公开了我的程序的第一步,即计算通过极值点的垂直线。如果使用边界框我失去了精度,我怎样才能得到一条穿过 Circular_arc_point_2 a_left_point 的垂直线?谢谢
  • 那条垂直线有方程 x = x_a_left_point。如果您需要 y 范围,那么正如我所说,您可以使用带有 Core::Expr 的(标准)CGAL 内核(例如 CGAL::Cartesian)计算所需的一切。
  • 和 x_a_left_point = x_a +- sqrt(r_a)。这允许您构造一条线,请参阅 CGAL 内核中的 Line_2。
【解决方案2】:

为了提高效率,你应该看看底层的一维问题:在 X 轴上投影线和圆,你有一组点和一组区间 [Xc-R, Xc+R]。

如果L个点是递增排序的,可以通过二分法定位一个时间区间Lg(L)的左边界,扫描点列表直到右边界。这会导致 O(Lg(L).C + I) 行为(C 圈间隔),其中 I 是报告的交叉点数。

我猜想通过使用活动列表的类似合并的过程,如果区间边界也被排序,你可以降低到 O(L + C + I)。

2D 的扩展是基本的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多