贝塞尔曲线算法 - 也许是规范样条曲线?

发布于 2024-09-18 05:52:09 字数 424 浏览 8 评论 0原文

我有一条由多个点组成的路径 - 即 0,0 0,50 50,50 70,20

如果我只是在屏幕上画这条线,它看起来相当粗糙,因为它在连接处设置了一个锐角每个点。

因此,我想知道贝塞尔曲线算法/方法会是什么样子,我可以称之为自动将锐角更改为“紧”曲线?

我不希望曲线太大或通常影响主路径的下降,只需软化连接即可。如果您看一下下面的内容,这是我整理的一个快速示例。左边的线是我现在拥有的,中间的线是我想要的。

右图代表了我认为我需要算法完成的任务。本质上,我向每个弧添加一个附加点,该点在距离连接 10% 的点处构成连接,然后删除连接点并调整手柄,使它们位于该点所在的位置(不是在图中)稍微分开,这只是为了让您可以看到)。这就是我需要能够做到的。

替代文本

I've got a path that is made up of multiple points - i.e. 0,0 0,50 50,50 70,20

If I just draw this line on the screen it looks quite harsh as it puts a sharp angle at the joining of each point.

Hence I was wondering what the bezier curves algorithm/method would look like which I could call that automatically change the sharp angles to "tight" curves?

I wouldn't want the curve to be too big or generally effect the fall of main path, just soften the join out. If you have a look at the below here is a quick sample I have put together. The line on the left is what I have now, the one in the middle is the line I want.

The image on the right represents what I think I need the algorithm to do. Essentially, I add an additional point to each arc that makes up the join at a point which 10% away from the join, then I remove the join point and adjust the handles so that they are where the point was (not in the diagram they are slightly apart, this is just so that you can see). This is what I need to be able to do.

alt text

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听风吹 2024-09-25 05:52:09

呃...只需添加一个 BezierSegment 到您的 PathSegmentCollection。

Er.... just add a BezierSegment to your PathSegmentCollection.

伴我心暖 2024-09-25 05:52:09

因此,您需要为每个“角”点确定 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;
}

So you need to identify 2 additional points per "corner" point. A "corner" point being any interior point along the path.

Here is a start:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文