在分段二次贝塞尔曲线上找到控制点

时间:2011-05-29 14:18:36

标签: bezier

我需要编写一个程序来生成并显示一个分段的二次贝塞尔曲线,该曲线插入每组数据点(我有一个txt文件包含数据点)。曲线应该具有连续的切线方向,每个数据点的切线方向是两个相邻弦方向的凸组合。

0.1 0, 
0 0,
0 5,
0.25 5,
0.25 0, 
5 0, 
5 5, 
10 5,
10 0, 
9.5 0

以上是我的数据点,有谁知道我可以用什么公式来计算控制点?

2 个答案:

答案 0 :(得分:0)

您需要使用三次贝塞尔曲线才能很好地处理多个斜率变化,例如数据集中出现的变化。对于二次贝塞尔曲线,数据点之间只有一个控制点,因此每个曲线段都在连接线段的一侧。

很难解释,所以这里是您的数据(黑点)和二次控制点(红色)和曲线(蓝色)的快速草图。 (假装曲线很平滑!)

enter image description here

查看Cubic Hermite curves以获得一般解决方案。

答案 1 :(得分:0)

从这里开始:http://blog.mackerron.com/2011/01/01/javascript-cubic-splines/

生成如下的插值曲线:

natural curve monotonic curve

您可以使用此咖啡脚本类(编译为javascript)

class MonotonicCubicSpline

# by George MacKerron, mackerron.com

# adapted from: 
# http://sourceforge.net/mailarchive/forum.php?thread_name=
# EC90C5C6-C982-4F49-8D46-A64F270C5247%40gmail.com&forum_name=matplotlib-users
# (easier to read at http://old.nabble.com/%22Piecewise-Cubic-Hermite-Interpolating-
# Polynomial%22-in-python-td25204843.html)

# with help from:
# F N Fritsch & R E Carlson (1980) 'Monotone Piecewise Cubic Interpolation', 
#   SIAM Journal of Numerical Analysis 17(2), 238 - 246.
# http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
# http://en.wikipedia.org/wiki/Cubic_Hermite_spline

constructor: (x, y) ->
  n = x.length
  delta = []; m = []; alpha = []; beta = []; dist = []; tau = []
  for i in [0...(n - 1)]
    delta[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i])
    m[i] = (delta[i - 1] + delta[i]) / 2 if i > 0
  m[0] = delta[0]
  m[n - 1] = delta[n - 2]
  to_fix = []
  for i in [0...(n - 1)]
    to_fix.push(i) if delta[i] == 0
  for i in to_fix
    m[i] = m[i + 1] = 0
  for i in [0...(n - 1)]
    alpha[i] = m[i] / delta[i]
    beta[i]  = m[i + 1] / delta[i] 
    dist[i]  = Math.pow(alpha[i], 2) + Math.pow(beta[i], 2)
    tau[i]   = 3 / Math.sqrt(dist[i])
  to_fix = []
  for i in [0...(n - 1)]
    to_fix.push(i) if dist[i] > 9
  for i in to_fix
    m[i]     = tau[i] * alpha[i] * delta[i]
    m[i + 1] = tau[i] * beta[i]  * delta[i]
  @x = x[0...n]  # copy
  @y = y[0...n]  # copy
  @m = m

interpolate: (x) ->
  for i in [(@x.length - 2)..0]
    break if @x[i] <= x
  h = @x[i + 1] - @x[i]
  t = (x - @x[i]) / h
  t2 = Math.pow(t, 2)
  t3 = Math.pow(t, 3)
  h00 =  2 * t3 - 3 * t2 + 1
  h10 =      t3 - 2 * t2 + t
  h01 = -2 * t3 + 3 * t2
  h11 =      t3  -    t2
  y = h00 * @y[i] + 
      h10 * h * @m[i] + 
      h01 * @y[i + 1] + 
      h11 * h * @m[i + 1]
  y