Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 计算三次贝塞尔曲线的控制点_Java_Bezier - Fatal编程技术网

Java 计算三次贝塞尔曲线的控制点

Java 计算三次贝塞尔曲线的控制点,java,bezier,Java,Bezier,我正在写一个在Android平板电脑上显示音乐的应用程序 我遇到了需要画领带和污点的时刻——将两个音符连接在一起的曲线 为此,我想使用立方贝塞尔-但不知道如何确定两个控制点的位置 很明显,我知道起点(A)和终点(B)点(2D),以及我想要曲线经过的线A-B的距离。我这样说是因为曲线不一定在水平面上 有谁能帮我确定所需的控制点,以便生成的曲线将通过一个给定点-即距平面的距离和沿A-B平面的偏移 请注意,我不是一个数学专家,我会喜欢编程类型的公式,而不是数学公式。。。求你了 以下是一个具体的例子:

我正在写一个在Android平板电脑上显示音乐的应用程序

我遇到了需要画领带和污点的时刻——将两个音符连接在一起的曲线

为此,我想使用立方贝塞尔-但不知道如何确定两个控制点的位置

很明显,我知道起点(A)和终点(B)点(2D),以及我想要曲线经过的线A-B的距离。我这样说是因为曲线不一定在水平面上

有谁能帮我确定所需的控制点,以便生成的曲线将通过一个给定点-即距平面的距离和沿A-B平面的偏移

请注意,我不是一个数学专家,我会喜欢编程类型的公式,而不是数学公式。。。求你了

以下是一个具体的例子:

我知道每条直线的起点和终点,以及我希望曲线通过的点


然而,在谷歌搜索了过去两天之后,我一直无法找到正确的公式来确定复制这些曲线所需的两个控制点位置。

不幸的是,如果不依靠数学,就无法做到这一点,因为从你的图像中,我们需要绘制的曲线类型取决于它所附着的东西。分析给定图像表明,这两条曲线不具有“构造”特性:

红线是起点/终点基线,它们的最大平移适合曲线,蓝线是从起点到第一个控制点,第二个控制点到终点的方向,绿线大致表示曲线的数学中点(t=0.5),黑线表示曲线的最大垂直延伸

为了形成这些曲线,我们将在一条标准曲线上发布线性代数,看看它能给我们带来什么

右边的曲线实际上相对容易构造,因为它是一条非常对称的曲线,我们可以通过缩放标准的半圆贝塞尔曲线来制作:

{ (0,0), (0,0.552), (1,0.552), (1,0) }
这将使曲线笔直地“向外”,因此让我们扭曲它,使曲线以微小角度开始和结束:

{ (0,0), (0.2,0.552), (0.8,0.552), (1,0) }
这是一条单位直线,高度为半圆,向上,所以我们需要把它缩小到四分之一高度,可能在y坐标前加上一些负号

{ (0,0), (0.2, +/- 0.138), (0.8, +/- 0.138), (1,0) }
并根据起点p1和终点p4对其进行缩放以匹配所需的线长度

D = distance(p1, p4)
{ (0,0), (0.2 * D, 0.138 * D), (0.8 * D, 0.138 * D), (D,0) }
然后旋转坐标,使其位于正确的角度线上,使用直线和水平线之间的角度,并将该角度粘贴在旋转矩阵中:

phi = atan2(p4.y - p1.y, p4.x - p1.x)

{
  (0, 0),
  (0.2 * D * cos(phi) - 0.138 * D * sin(phi), 0.2 * D * sin(phi) + 0.138 * D * cos(phi)),
  (D * cos(phi) - 0.138 * D * sin(phi), D * sin(phi) + 0.138 * D * sin(phi)),
  (D * cos(phi), D * sin(phi)
}
这看起来像“mathy”,但不是。cos(phi)和sin(phi),如果你已经有了phi,只是两个数字,这里没有数学,只是愚蠢的算术

最后一步是平移所有坐标,使其位于页面上的正确位置:

{
  (p1.x + 0, p1.y + 0),
  (p1.x + 0.2 * D * cos(phi) - 0.138 * D * sin(phi), p1.y + 0.2 * D * sin(phi) + 0.138 * D * cos(phi)),
  (p1.x + D * cos(phi) - 0.138 * D * sin(phi), p1.y + D * sin(phi) + 0.138 * D * sin(phi)),
  (p1.x + D * cos(phi), p1.y + D * sin(phi)
}
完成了。你的第二条曲线很容易画

左侧的曲线需要稍微多做一些工作,但只需要稍微多做一点。我们——也许是非直觉地——以同样的方式开始,形成与之前完全相同的曲线类型,在旋转之前停止。我们可以观察到,如果我们将图像中的曲线平放在水平面上,它实际上是一个规则缩放的半圆,但向右剪切。我们就这么做吧:

轮换前:

{ (0,0), (0.2 * D, 0.138 * D), (0.8 * D, 0.138 * D), (D,0) }
水平剪切

float sx = <strength of the shear>
{ (0,0), (0.2 * D + 0.138 * D * sx, 0.138 * D), (0.8 * D + 0.138 * D * sx, 0.138 * D), (D,0) }
最后的翻译步骤也是一样的。同样地,大多数情况下只是插入数字,不过这次您必须使用剪切值来查看哪一个看起来最好

自由参数

我们可以通过改变初始半圆的比例来控制曲线的“弯曲”程度。系数0.25相对较紧,系数0.33相对起泡。我们还可以控制像左领带这样的曲线的剪切有多快。1的切变是微妙的,1.75的切变是剧烈的突变

为什么这样做

贝塞尔曲线,尽管名字中有“曲线”一词,但它是线性插值的线性插值。。。一行行。对构建曲线的坐标应用线性变换可以保留曲线的属性,因此,我们不必尝试处理完整的曲线,而只需处理四个坐标,并相信曲线看起来是正确的

我们取一条曲线的四个坐标,我们知道它的坐标,然后应用我们需要的所有变换来得到我们想要的曲线:

(x,y) . scale . (shearx?) . rotation, + (tx,ty)
即:

|x| . | D 0 | . | 1 shearx | . |cos(phi) -sin(phi)| + |tx|
|y|   | 0 D |   | 0    1   |   |sin(phi)  cos(phi)|   |ty|
矩阵运算可以被压缩成一个矩阵(这就是为什么计算机在2D/3D方面如此擅长——都是矩阵,所以非常复杂的运算仍然只是一个应用于一百万坐标的矩阵)

事实上,如果我们将坐标视为3d坐标,z值始终为1,我们甚至可以将平移作为矩阵运算。但这与你的问题不再相关了

jsidle


可以在中找到一个分步实现左tie的提琴,但这并没有将所有操作折叠为一个操作。你需要自己去做。

不幸的是,不依靠数学是无法做到这一点的,因为从你的图像中,我们需要绘制的曲线类型取决于它所附着的东西。分析给定图像表明,这两条曲线不具有“构造”特性:

红线是起点/终点基线,它们的最大平移适合曲线,蓝线是从起点到第一个控制点,第二个控制点到终点的方向,绿线大致表示曲线的数学中点(t=0.5),黑线表示曲线的最大垂直延伸

为了形成这些曲线,我们将释放Linea
|x| . | D 0 | . | 1 shearx | . |cos(phi) -sin(phi)| + |tx|
|y|   | 0 D |   | 0    1   |   |sin(phi)  cos(phi)|   |ty|