Алгоритм кривых Безье - может быть, канонические сплайны? - PullRequest
2 голосов
/ 03 сентября 2010

У меня есть путь, который состоит из нескольких точек - то есть 0,0 0,50 50,50 70,20

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

Поэтому мне было интересно, как будет выглядеть алгоритм / метод кривых Безье, который я мог бы назвать, который автоматически изменяет острые углы на "узкие" кривые?

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

Изображение справа представляет то, что мне нужно, чтобы алгоритм работал. По сути, я добавляю дополнительную точку к каждой дуге, которая составляет соединение в точке, которая находится на расстоянии 10% от соединения, затем я удаляю точку соединения и настраиваю маркеры таким образом, чтобы они находились там, где была точка немного раздвинуты, это просто так, что вы можете видеть). Это то, что мне нужно сделать.

alt text

Ответы [ 2 ]

3 голосов
/ 03 сентября 2010

Э-э ... просто добавьте BezierSegment в коллекцию PathSegmentCollection.

1 голос
/ 03 сентября 2010

Так что вам нужно идентифицировать 2 дополнительные точки на «угловую» точку.«Угловой» точкой является любая внутренняя точка на пути.

Вот начало:

public List<Point> AddControlPoints(List<Point> path)
{
    // arbitrary minimum length to use to make a corner
    double segmentLengthThreshold = 10.0;
    double cornerDistance = 2.0;

    if (path.Count < 3) return path.ToList(); // arbitrarily a copy

    var newPath = new List<Point>();
    newPath.Add(path[0]);
    for (int ii = 1; ii < path.Count - 1; ii += 2)
    {
        // walk each "corner" point and do line interpolation for the point
        double m = (path[ii].Y - path[ii-1].Y) / (path[ii].X - path[ii-1].X);
        double b = (path[ii].Y - m * path[ii].X);

        // above we setup the equation to move along the line
        // find the new X value and move along it
        double xi = path[ii].X - cornerDistance/m;
        newPath.Add(new Point(xi, m * xi + b));
        newPath.Add(path[ii]);

        // repeat for the next side
        m = (path[ii+1].Y - path[ii].Y) / (path[ii+1].X - path[ii].X);
        b = (path[ii].Y - m * path[ii].X);

        xi = path[ii].X + cornerDistance/m;
        newPath.Add(new Point(xi, m * xi + b));

        // this will likely fail in many ways, 0 slopes etc
        // but throwing the equations some test values shows it makes
        // decent control points. If you'd like them to be length based
        // just find the distance of the two points and multiply by a
        // factor
    }

    return newPath;
}
...