关于Bezier曲线实施的问题?

时间:2010-08-18 19:30:30

标签: math geometry

我已经阅读了一些贝塞尔曲线的教程,例如这个http://www.codeproject.com/KB/recipes/BezirCurves.aspx

创建贝塞尔曲线的基本思想是使用一些控制点并决定需要创建多少个新点。然后插入这些新点。

以下是问题:

假设我有1000分,我想多插补2000分。我想要使​​用的控制点数量为5.参数t的范围为[0,1]。

Givens点P0,P1,P2,P3,P4,P5,P6,...... P1000。 我可以使用P0-P4来产生新的点,接下来是什么? 使用P5-P9产生新点???我可以立即看到P4和P5之间的突然转换。

我该如何解决这个问题?

谢谢

/////////////////////////////////////////////// ////// 你好Stargazer712,

我理解你的意见,直到达到实施方法。

假设我们有以下几点:

A1->A2->A3->A4->A5->A6->A7->A8 initial points

你说我们需要在每对其他中间点添加一个新点。

我的问题是新观点的顺序是什么?

让我们使用这个注释(A1 + A3)/ 2 == A12

现在生成的新点是

A13 A24 A35 A46 A57 A68 (this is what you mean "every other pair"?

我应该在哪里将这些点插入原始列表?

我正在处理的轮廓是从二进制图像中提取的。生成的轮廓为锯齿形。在我应用这种平滑的方法后,它的形状不会改善太多。我认为主要原因是邻居彼此靠近并使插值不那么有用。

谢谢

/////////////////////////////////////////////// /////

1 个答案:

答案 0 :(得分:11)

我认为你要做的是创建一个平滑曲线来插值点。为此,您需要了解以下关于贝塞尔曲线的信息:

假设我们有两条曲线,包括A1,A2,A3,A4和B1,B2,B3和B4点。

如果两条曲线在同一点上结束,并且第一条控制点的最后一个控制点与下一条控制点的第一个控制点共线,那么曲线将是平滑的。所以在我们的例子中,如果:

  • A4 == B1
  • A3,A4和B2是共线的(与A3,B1,B2共线相同)

然后曲线将是平滑的。

为了获取任意点列表并制作平滑曲线,我们需要强制这两个条件成立。

要做到这一点,我们假设我们从一组点开始:

Initial Points

要强制执行上述条件,请添加一些额外点。我们会在所有其他对的中点处添加一个新点,如下所示:

With meta points

我们现在可以在0-3,3-6,6-9等点之间绘制贝塞尔曲线,我们可以确定它会形成一条平滑的曲线:

Curve drawn

希望这有帮助!

编辑:这是一个简单的python程序,它完全实现了上面显示的内容(我的意思是确切地说)。您需要安装python和PIL:

from PIL import Image
import math

#
#   draws a single point on our image
#
def drawPoint( img, loc, size=5, color=(0,0,0) ):
    px = img.load()
    for x in range(size):
        for y in range(size):
            xloc = loc[0] + x - size/2
            yloc = loc[1] + y - size/2
            px[ xloc, yloc ] = color


#
#   draws a simple bezier curve with 4 points
#            
def drawCurve( img, points ):

    steps = 20
    for i in range(steps):

        t = i / float(steps)

        xloc = math.pow(1-t,3) * points[0][0] \
             + 3*t*math.pow(1-t,2) * points[1][0] \
             + 3*(1-t)*math.pow(t,2) * points[2][0] \
             + math.pow(t,3) * points[3][0]
        yloc = math.pow(1-t,3) * points[0][1] \
             + 3*t*math.pow(1-t,2) * points[1][1] \
             + 3*(1-t)*math.pow(t,2) * points[2][1] \
             + math.pow(t,3) * points[3][1]

        drawPoint( img, (xloc,yloc), size=2 )


#
#   draws a bezier curve with any number of points
#
def drawBezier( img, points ):

    for i in range(0,len(points),3):
        if( i+3 < len(points) ):
            drawCurve( img, points[i:i+4] )


#
#   draws a smooth bezier curve by adding points that
#   force smoothness
#
def drawSmoothBezier( img, points ):

    newpoints = []

    for i in range(len(points)):

        # add the next point (and draw it)
        newpoints.append(points[i])
        drawPoint( img, points[i], color=(255,0,0) )

        if( i%2 == 0 and i>0 and i+1<len(points) ):

            # calculate the midpoint
            xloc = (points[i][0] + points[i+1][0]) / 2.0
            yloc = (points[i][1] + points[i+1][1]) / 2.0

            # add the new point (and draw it)
            newpoints.append( (xloc, yloc) )
            drawPoint( img, (xloc, yloc), color=(0,255,0) )

    drawBezier( img, newpoints )



#   Create the image
myImage = Image.new("RGB",(627,271),(255,255,255))

#   Create the points
points = [  (54,172), 
            (121,60), 
            (220,204), 
            (284,56), 
            (376,159), 
            (444,40), 
            (515,228), 
            (595,72) ]

#   Draw the curve
drawSmoothBezier( myImage, points )

#   Save the image
myImage.save("myfile.png","PNG")

该线将遵循点的模式。如果你的结果是锯齿形的,那是因为这就是线条的样子。