2010-08-18 105 views
9

我已经阅读了贝齐尔曲线的一些教程,例如这个http://www.codeproject.com/KB/recipes/BezirCurves.aspx关于Bezier曲线实现的问题?

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

这里有一个问题:

假设我有1000点,我想插2000点以上。我想要使​​用的控制点的数量是5.参数t在[0,1]的范围内。

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

我该如何解决这个问题?

谢谢

//////////////////////////////////////// ///////////// Hello 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"? 

我应该在哪里插入这些点到原来的名单?

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

谢谢

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

回答

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") 

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

+0

Hello Stargazer712, 我已根据您的意见发布了新问题。请参阅我的原始问题下的帖子。 谢谢 – q0987 2010-08-18 20:17:18

+0

@ q0987 - 绘制贝塞尔曲线的程序非常简单。我希望有一个例子可以解答您可能遇到的任何问题 – riwalk 2010-08-18 22:49:04

+0

非常感谢你的帮助。 您的编码风格看起来很完美:) – q0987 2010-08-19 03:27:47