如何选择三维Bézier曲线的控制点距离来优化“圆度”?

时间:2015-05-24 14:46:18

标签: optimization 3d distance bezier

假设我想构建一个三维Bézier曲线,我已经有两个终点和两个控制点的方向(法向量)。如何选择两个控制点到各自终点的距离,以使曲线尽可能“圆润”?

形式化'精确圆润':我认为这意味着最大化曲线中任意两个线段之间的最小角度。例如,端点(10,0,0)(0,10,0)具有相应的法向量(0,1,0) (1,0,0)应产生90°圆弧。对于2D圆弧的具体情况,我发现了文章like this one。但是我没有找到任何更常见的案例。

too big too small just right

(请注意,这些图像只是为了说明'圆度'的概念。我的曲线不能保证是平面对齐的。我可以稍后替换图像以更好地说明这一点。)

这是一个美学问题,如果真正的解决方案未知或过于复杂,我会对合理的近似感到满意。我当前的近似过于简单:在两个控制点距离的两个端点之间选择一半距离。更熟悉数学的人可能会想出更好的东西。

(PS:这是open-source software,我很乐意在GitHub上表示赞赏。)

编辑:以下是一些其他图片来说明3D案例(jsfiddle):

bad good

编辑2:以下是ApiNATOMY不稳定版本的屏幕截图,让您了解我正在尝试做什么。我正在创建3D管来代表血管,连接解剖示意图的不同部分:

ApiNATOMY with 3D blood-vessels

(They won't let me put in a jsfiddle link if I don't include code...)

3 个答案:

答案 0 :(得分:1)

您基本上要求的是使样条曲线上的曲率尽可能恒定。

曲率恒定的曲线只是一个圆弧,因此尝试将这样的弧拟合到输入参数是有意义的。在2D中,这很容易:构造穿过起点并与所需方向矢量正交的线。对结束点做同样的事情。现在将这两条线相交:结果是圆的中心,它通过具有所需方向向量的两个点。

在您的示例中,此交点仅为(0,0),并且所需的圆弧位于单位圆上。

所以这会给你一个圆弧,你可以直接使用它,也可以使用你已经引用过的近似算法。

当两个方向向量共线时会发生故障,因此如果出现这种情况,你必须稍微捏一下它。如果他们指向对方,你可以简单地使用一条直线。

在3D中,相同的结构为您提供了两个穿过终点的平面。相交这些,你得到一条线;在这一行上,选择最小化到两点的平方距离之和的点。这为您提供了接触两个端点的球体的中心,现在您可以简单地在这三个点所跨越的平面中工作,并按照2D进行操作。

答案 1 :(得分:0)

对于特殊情况,您的两个端点和控制点的两个已知法向量碰巧使贝塞尔曲线成为平面矢量,那么基本上您正在寻找一个可以近似圆弧的三次贝塞尔曲线。对于这种特殊情况,您可以将控制点与其各自终点之间的距离(表示为L)设置为L =(4/3)* tan(A / 4)其中A是圆弧的角度。 / p>

对于一般3D情况,也许您可​​以应用相同的公式:

  • 计算两个法向量之间的角度。
  • 使用L =(4/3)* tan(A / 4)来确定控制点的位置。

答案 2 :(得分:0)

如果您的法线在平面中对齐

你在这里基本上做的是在3D中创建一个椭圆弧,其中“它在3D中”部分是完全不相关的,因为它只是一条2D曲线,旋转/平移坐在你的3D空间中。所以,让我们解决2D案例,然后RT完全取决于您。

在弧comes with limitations上的两个点之间创建“完美”三次贝塞尔曲线。你基本上不能创造超过四分之一圆的好看的弧。因此,有了这样的说法:你的起点和终点法线给你一个法线向量之间的二维角度,这是与开始和结束切线之间的角度相同(因为法线垂直于切线)。那么,让我们:

  1. 对齐我们的曲线,使得开始处的切线为0
  2. 将切线之间的角度插入Primer on Bezier curves中圆近似部分中给出的公式中。这基本上只是愚蠢“将c1x / c1y / c2x / c2y的公式实现为以角度为参数的函数,并将四个值作为c1(x,y)和c2(x,y)协调值吐出“
  3. 没有第3步,我们已经完成了。
  4. 在步骤2之后,您将控制点设置为2D,以在起点和终点之间创建最圆弧。现在您只需要在3D中缩放/旋转/翻译它,以便它与您需要开始和结束点的位置对齐。

    如果您的法线未在平面中对齐

    现在我们遇到了一个问题,尽管我们可以通过将维度完全视为单独的事物来处理问题。我们将创建三个:而不是创建单个2D曲线,一个是X / Y投影,一个是X / Z投影,另一个是Y / Z投影。对于所有这三个,我们将以与以前完全相同的方式抽象中的控制点然后我们简单地采用投射控制点(每个控制点三个),然后去“好吧,我们现在有X,Y和Z投影坐标。这意味着我们有(X,Y,Z)坐标”,并再次完成。