Bezier曲线快速相交计算(含代码)

article/2025/11/9 17:45:21

Bezier曲线快速相交计算

  • 背景介绍
  • 算法思路
  • 解释和分析
  • 示例
  • 参考资料

背景介绍

很多时候,需要计算曲线段与曲线段是否有交点。常规的思路是直接联立方程求解。不过,直接求方程的解这种思路通常在计算上开销较大。

针对任意曲线,曲线的方程阶次可能较高,无论是求导还是求根都比较困难。当曲线无交点时,并不能快速判断并停止计算。因此,本文介绍一种快速计算贝塞尔(Bezier)曲线的方法。这个方法的中心思想是化曲为直,分段判断。通过快速排除条件,可以节省计算时间。

算法思路

具体针对两条曲线(2D平面)进行说明:
1)采用AABB模型(Aixe Align Bounding Box)构建每条曲线的包围盒,对构建好的包围盒进行干涉判断,若空间干涉,进行下一步,否者退出本次判断;
2)对干涉空间内的曲线进行二分,即分成2段,2条曲线则分成四段。针对两两进行检测,执行步骤 1) ;
3)退出条件:曲线线段小于某一阈值或到达其他检测精度。
以上就是全部的思路,针对具体工程问题可以针对优化,进行加速计算。

解释和分析

不相交的曲线,在形成包围盒进行相交测试中可能会由于包围盒的范围太大而出现干涉,因此需要进一步二分,减少空间大小以排除或者确定。相交的曲线在该段内形成的包围盒一定会干涉,因此只需要收缩包围盒大小(也即曲线段范围缩小),就能找到交点(当然是一个近似结果,但一般能满足工程需要)。

干涉判断
为什么要用AABB模型而不是OBB(Oriented Bounding Box)?
当然从实际角度考虑,曲线是有方向和走向的,使用OBB模型更符合实际。但是OBB的计算比较复杂,需要计算切线方向,涉及到求导等。另外OBB的干涉检测也比较复杂,需要用到分离轴SAT或者GJK算法进行判断,这无疑加大了计算量,每一步的OBB干涉判断耗时太大了。当然,不在乎实时性的可以采用该方法,进一步也可以采用基于OBB的紧包围盒(都不在乎计算量了,直接精确求解它不香嘛)。

AABB包围盒如何计算,如何判断干涉?
如果曲线的x,y从起点出发到终点,x及y的变化呈现递增or递减的情况,则可以简单处理。此时AABB可以由该曲线的两个点确定(起点和终点,其中一个是最大点,一个是最小点)。

不同的AABB框
左边这个包围盒就只需要起点(70,250)和终点(220,60)就能确定了。右边这个则需要计算单调性改变处的坐标,并与起点和终点比较,最终构成AABB。具体确定单调性的方法,可以采用计算曲线导数(贝塞尔曲线的一阶导数为低一阶贝塞尔曲线),根据它确定根。
AABB的干涉判断比较简单了,x,y最大最小值直接判断就行了,可以参考其他教程。
以下两张图是搜索过程展示(资源来自于链接)

计算过程
终点确定

示例

此代码片段来自于python-bezier包

>>> import bezier
>>> import numpy as np
>>> nodes1 = np.asfortranarray([
...     [0.0, 0.5, 1.0],
...     [0.0, 1.0, 0.0],
... ])
>>> curve1 = bezier.Curve(nodes1, degree=2)

>>> nodes2 = np.asfortranarray([
...     [0.0, 0.25,  0.5, 0.75, 1.0],
...     [0.0, 2.0 , -2.0, 2.0 , 0.0],
... ])
>>> curve2 = bezier.Curve.from_nodes(nodes2)
>>> intersections = curve1.intersect(curve2)
>>> intersections
array([[0.31101776, 0.68898224, 0. , 1. ],[0.31101776, 0.68898224, 0. , 1. ]])
>>> s_vals = np.asfortranarray(intersections[0, :])
>>> points = curve1.evaluate_multi(s_vals)
>>> points
array([[0.31101776, 0.68898224, 0. , 1. ],[0.42857143, 0.42857143, 0. , 0. ]])

下图四个交点的位置,t1=0.31101776, 0.68898224, 0. , 1,对应t2=0.42857143, 0.42857143, 0. , 0.
检测结果
此方法的优点在于不需要计算导数及根,可以快速排除离得较远的曲线段。

参考资料

贝塞尔曲线的介绍:https://pomax.github.io/bezierinfo/
python代码:https://github.com/dhermes/bezier

欢迎留言交流,如果觉得有帮助,点个赞呗。


http://chatgpt.dhexx.cn/article/tPmkgDBd.shtml

相关文章

js绘制贝塞尔曲线(Bézier-Curve)

贝塞尔曲线(Bzier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们…

Bezier曲线与B-Spline曲线

微分几何基础 微分集合是用微分的方法来研究曲线的局部性质,如曲线的弯曲程度等。 一条可以用参数表示的三维曲线是一个有界点集,可以写成一个带参数的、连续的、单值的数学函数: { x x ( t ) y y ( t ) z z ( t ) 0 ⩽ t ⩽ 1 p p ( t…

初识贝塞尔(bezier)曲线

文章目录 资料援引贝塞尔曲线的用途一阶贝塞尔(bezier)曲线二阶贝塞尔(bezier)曲线三阶贝塞尔(bezier)曲线高阶贝塞尔(bezier)曲线三阶贝塞尔曲线求插值(Slerp&#xff0…

贝塞尔曲线(Bezier Curve)原理、公式推导及matlab代码实现

1. 定义 贝塞尔曲线(Bezier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋&#…

Bezier(贝塞尔曲线通用规律算法-DEMO)

之前也看过一些相关贝塞尔曲线的知识,但就是一直没有实践应用; 今天,听到有同事:程序、美术,在讨论相关的,人物的曲线路径行走的问题; 一些数学比较牛X的,说了用2阶,或…

bezier曲线原理(简单阐述)

原理和简单推导(以三阶为例): 设P0、P02、P2是一条抛物线上顺序三个不同的点。过P0和P2点的两切线交于P1点,在P02点的切线交P0P1和P2P1于P01和P11,则如下比例成立: 这是所谓抛物线的三切线定理。 当P0&…

Bezier贝塞尔曲线

1.简介 Bezier曲线在图形学和游戏中经常使用,一般用的比较多的是4个控制点的贝塞尔曲线,这里手写了一个仅供参考(注:理论上也可以写任意多个点(3个及以上)的贝塞尔,就是一个递归的过程&#xff…

java 贝塞尔曲线_在Java中绘制贝塞尔曲线

我需要创建一个简单的Java程序,通过任意数量的点逐个像素地绘制贝塞尔曲线.此刻,一切似乎都没问题,只是曲线总是在x 0 y 0坐标处结束. 截图1 截图2 我需要它在最后一点结束.我的大脑今天工作不太好,所以我正在寻求帮助. 这是我有的: private void drawScene(){ pr…

贝塞尔曲线(Bezier Curve)原理及公式推导

1. 定义 贝塞尔曲线(Bezier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋&#…

Bezier(贝塞尔)曲线小总结

在初学时,我发现Bezier曲线(中文名贝塞尔曲线,想要了解历史发展等的可以看此百度百科:贝塞尔曲线_百度百科)很难理解,故在此写了一篇自己的心得感悟。要理解它最重要的是理解Bernstein基函数。首先&#xf…

Bezier曲线原理—动态解释

Bezier曲线原理 贝塞尔曲线(Bzier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮…

正确的Bezier曲线的绘制

原文地址:http://blog.csdn.net/mylovestart/article/details/8434310 Bezier曲线是参数多项式曲线,它由一组控制多边形折线(控制多边形)的顶点唯一定义,在控制多边形的各顶点中,只有第一个和最后一个顶点在曲线上,其他的顶点则用以定义曲线的导数,阶次和形状 Bezier曲线的数…

根据Bezier曲线的定义公式实现Bezier曲线的绘制

Bezier曲线的定义公式 Pi是曲线上点的坐标(x,y,(z0)), Bi,n(t)伯恩斯坦公式,绘制Bezier曲线的第一种方法是根据这个公式来绘制。首先看看绘制的效果: (1)计算定义中多项式的值 首先要求伯恩斯…

Bezier曲线描述

Bezier曲线 1.Bezier曲线的定义 当用曲线段拟合曲线f(x)时,可以把曲线表示为许多小线段φi(x)之和,其中φi(x)称为基(混合)函数。 这些基(混合)函数是要用于计算和显示的。因此,经常选择多项式…

Bezier曲线的绘制

Bezier曲线是参数多项式曲线,它由一组控制多边形折线(控制多边形)的顶点唯一定义,在控制多边形的各顶点中,只有第一个和最后一个顶点在曲线上,其他的顶点则用以定义曲线的导数,阶次和形状 Bezier曲线的数学基础是能够在第一个和最后一个顶点之间进行插值的一个多项式混合函数,…

Bezier曲线的生成算法

Bezier曲线的生成方法 生成一条Bezier曲线实际上就是要求出曲线上的点。 1.根据定义直接生成Bezier曲线 定义: 其中 那么生成步骤为: ①首先给出 的递归计算式: ②:将表示成分量形式 由于的计算量大,算法效率不高…

bezier曲线解析与代码(c++)

前言: 作为rhino重度用户,我对于nurbs建模早有耳闻,但对于何为nurbs却不得其解。最近借上《计算机辅助设计》课程的机会,对此作了一些深入的学习,于是在此记录一下一些课程笔记和课后思考。了解nurbs,主要对…

Bezier曲线构造

Bezier曲线构造 曲线公式 曲 线 : C ( u ) ∑ i 0 n B n , i ( u ) P i 基 函 数 : B n , i n ! i ! ( n − i ) ! u i ( 1 − u ) n − i 曲线:C(u) \sum^n_{i0}B_{n,i}(u)P_i\\ 基函数:B_{n,i}\frac{n!}{i!(n-i)!}u^i(1-u)…

java版 贝塞尔曲线算法

public void test() {CvPoint controlPoint[] new CvPoint[4];controlPoint[0] new CvPoint(50, 60); //起点controlPoint[1] new CvPoint(130, 200); //控制点controlPoint[2] new CvPoint(300, 360); //控制点controlPoint[3] new CvPoint(400, 600); //终点int n cont…

Bezier曲线原理及实现代码(c++)

http://devres.zoomquiet.io/data/20110728232822/index.html Bezier曲线原理及实现代码(c) 一、原理: 贝塞尔曲线于1962年,由法国工程师皮埃尔贝塞尔(Pierre Bzier)所广泛发表,他运用贝塞尔曲线…