【问题标题】:Given f(x) linear function, how to obtain a Quadratic Bezier control point给定 f(x) 线性函数,如何获得二次贝塞尔控制点
【发布时间】:2013-06-22 18:09:48
【问题描述】:

我一直在对该主题进行大量研究,并发现了一些有用的帖子,但我就是无法做到这一点。

我正在开发一个非常简单的结构分析应用程序。在这个应用程序中,我需要显示一个图表来显示梁的内应力。该图由以下公式得到:

y = (100 * X / 2) * (L - X)

其中L 是梁的已知长度(为简单起见,我们称其为 1)。而X 是介于 0 和 be 梁的长度之间的值。所以最终的公式是:

y = (100 * X / 2) * (1 - x) where  0 < X < 1.

假设我的起点和终点是P0 = (0,0)P2 = (1,0)。如何获取P2(控制点)??我一直在维基百科页面中搜索,但不确定如何从二次贝塞尔曲线公式中获取控制点:

B(t) = (1 - t)^2 * P0 + 2*(1 - t)*t * P1 + t^2 * P2

我确定这一定是一个很容易解决的问题……谁能帮帮我吗?

P.S.:我还发现了这个,How to find the mathematical function defining a bezier curve,它似乎解释了如何做与我想要实现的目标相反的事情。我只是不知道如何扭转它。

【问题讨论】:

  • 如果你还没有,你可能想看看 Math.SE math.stackexchange.com
  • 谢谢!我已经看过数学部分了。我只是不知道如何处理“t”值。我尝试做与我链接的问题相同的操作,但“t”仍然存在,所以我留下了一个无用的坐标。

标签: math language-agnostic uibezierpath bezier


【解决方案1】:

我们希望y 定义的二次曲线与二次贝塞尔曲线相匹配 由B(t)定义。

在许多必须匹配的点中,峰值出现在x = 0.5。当x = 0.5

y = (100 * x / 2) * (1 - x)

    100     1      25
y = ---- * ---  = ---- = 12.5
     4      2       2

所以,我们安排B(0.5) = (0.5, 12.5)

B(t) = (1-t)^2*(0,0) + 2*(1-t)*t*(Px, Py) + t^2*(1,0)
(0.5, 12.5) = B(0.5) = (0,0) + 2*(0.5)*(0.5)*(Px, Py) + (0.25)*(1,0)

0.5 = 0.5 * Px + 0.25
12.5 = 0.5 * Py

求解PxPy,我们得到

(Px, Py) = (0.5, 25)

这是我们找到正确点的视觉确认(在 Python 中):

# test.py
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 1, 100)
y = (100*x/2)*(1-x)
t = np.linspace(0, 1, 100)
P0 = np.array([0,0])
P1 = np.array([0.5,25])
P2 = np.array([1,0])
B = ((1-t)**2)[:,np.newaxis]*P0 + 2*((1-t)*t)[:,np.newaxis]*P1 + (t**2)[:,np.newaxis]*P2
plt.plot(x, y)
plt.plot(B[:,0], B[:,1])
plt.show()

运行python test.py,我们看到两条曲线重叠:


我怎么知道B(t)达到最大高度时选择t = 0.5作为参数值?

嗯,它主要是基于直觉,但这里有一种更正式的方式来证明它:

B(t) 达到其最大高度时,B'(t) 的 y 分量等于 0。所以,取B(t) 的导数,我们看到

0 = 2*(1-2t)*Py
t = 0.5 or Py = 0

如果 Py = 0,则 B(t) 是从 (0,0) 到 (1,0) 的水平线。拒绝这种退化的情况,我们看到B(t)t = 0.5 时达到其最大高度。

【讨论】:

  • 哇!非常感谢unutbu。这很容易......所以让我直截了当,阅读你的代码我得出结论,贝塞尔曲线的最大值出现在 t = 0.5 处。总是这样吗?
  • @t0t3m:这只是一个幸运的猜测。但我在上面添加了一个更正式的论点,为什么 t=0.5 是正确的选择。
  • 我用@Teeppeem 指出的变化编辑了控制点数学。我认为我做对了,但请随时检查。用于视觉确认的图表仍然是相同的。
【解决方案2】:

您的二次贝塞尔曲线公式在中期有错字。应该是:
B(t) = (1 - t)^2 * P0 + 2 * (1 - t) * t * P1 + t^2 * P2
这意味着您应该使用@unutbu 找到的P1=(1,50) 并将坐标一分为二得到P1=(.5,25)。 (如果您自己绘制参数方程,这无关紧要,但如果您想要 LaTeX 的 \qbezier(0,0)(.5,25)(1,0) 之类的东西,那么您将需要更正点。)

P1 控制点被定义为使P0P2 处的切线在P1 处相交。这意味着如果(P1)x=(P2)x,则图形在其右侧应该是垂直的(您不希望这样)。

响应您的评论,如果您有一个二次方y=f(x),那么它是关于其轴对称的(几乎是重言式)。所以最大值/最小值将出现在根(以及控制点)的平均值处。

【讨论】:

  • 我现在正要问这个问题。新的控制点 (0.5, 25) 比之前的 (1,50) 更有意义。我已经更正了公式。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 2011-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多