Вопрос о реализации Кривых Безье? - PullRequest
9 голосов
/ 18 августа 2010

Я прочитал несколько уроков по кривой Безье, таких как этот http://www.codeproject.com/KB/recipes/BezirCurves.aspx.

Основная идея создания кривой Безье состоит в том, чтобы использовать некоторые контрольные точки и принять решение о том, сколько новых точек необходимо создать. А затем интерполировать эти новые точки.

Вот вопрос:

Предположим, у меня есть 1000 баллов, и я хотел бы интерполировать еще 2000 баллов. Количество контрольных точек, которые я хочу использовать, равно 5. Параметр t находится в диапазоне [0, 1].

Дает баллы 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 Ответ

11 голосов
/ 18 августа 2010

Я думаю, что вы пытаетесь создать плавную кривую, интерполирующую точки. Для этого вам нужно понять следующее о кривых Безье:

Скажем, у нас есть две кривые с точками 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")

Линия будет следовать схеме точек. Если ваш результат зигзагообразный, то это потому, что именно так выглядели линии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...