Inkscape自动平滑节点的算法

问题描述 投票:0回答:1

我是通过插值(很多)点来生成平滑曲线的,我希望有局部支持(即只有少数点决定局部的平滑曲线),所以我不想使用经典的插值花键。我希望有局部的支持(即只有几个点决定局部的平滑曲线),所以我不想使用经典的插值花键。对我来说,贝塞尔曲线是一个自然的解决方案,而Inkscape的自动平滑节点(http:/tavmjong.free.frINKSCAPEMANUALhtmlPaths-Edit.html#Paths-Node-AutoSmooth。)可以很好地实现我想要的东西。但是我在源码中找不到实现的方法,也找不到底层算法的参考。

这里有谁知道这个算法或者熟悉Inkscape的源代码,所以他们能给我指出正确的方向吗?

为了便于理解,我正在计算一个平滑路径。我正在为钢笔绘图仪计算一个平滑的路径,但我不能等待所有的支持点。

bezier inkscape cubic-bezier
1个回答
1
投票

按照下面@fang的评论。使用 Catmull-Rom Interpolating Spline 可能比较好,它既能插值又有局部控制的特性。查看更多

关于拼接插值的立方贝塞尔曲线(更像自然立方花键),请看下面的原答案。

以下是 javascript-样的伪代码,计算一系列(最多)立方贝塞尔曲线,这些曲线组合在一起就会变成 实现一条平滑的曲线通过给定点. bezier 在下面的代码中,假设是一个通过给定控制点计算(多项式形式)立方贝塞尔的函数(这是已知的算法)。注2:在下面的代码中,假设函数是通过给定的控制点计算(多项式形式)一个立方贝塞尔函数(已经知道算法)。 下面的算法是针对一维曲线的,但很容易调整为二维曲线(即计算x和y坐标)。

function bezierThrough( knots )
{
    var i, points, segments;
    computePoints = function computePoints( knots ) {
        var i, p1, p2, a, b, c, r, m, n = knots.length-1;
        p1 = new Array(n);
        p2 = new Array(n);

        /*rhs vector*/
        a = new Array(n);
        b = new Array(n);
        c = new Array(n);
        r = new Array(n);

        /*left most segment*/
        a[0] = 0;
        b[0] = 2;
        c[0] = 1;
        r[0] = knots[0] + 2*knots[1];

        /*internal segments*/
        for(i=1; i<n-1; i++)
        {
            a[i] = 1;
            b[i] = 4;
            c[i] = 1;
            r[i] = 4*knots[i] + 2*knots[i+1];
        }

        /*right segment*/
        a[n-1] = 2;
        b[n-1] = 7;
        c[n-1] = 0;
        r[n-1] = 8*knots[n-1] + knots[n];

        /*solves Ax=b with the Thomas algorithm (from Wikipedia)*/
        for(i=1; i<n; i++)
        {
            m = a[i] / b[i-1];
            b[i] = b[i] - m*c[i - 1];
            r[i] = r[i] - m*r[i-1];
        }

        p1[n-1] = r[n-1] / b[n-1];
        for(i=n-2; i>=0; --i)
            p1[i] = (r[i]-c[i]*p1[i+1]) / b[i];

        /*we have p1, now compute p2*/
        for (i=0;i<n-1;i++)
            p2[i] = 2*knots[i+1] - p1[i+1];
        p2[n-1] = (knots[n]+p1[n-1])/2;

        return [p1, p2];
    };
    if ( 1 === knots.length )
    {
        segments = [knots[0]];
    }
    else if ( 2 === knots.length )
    {
        segments = [bezier([knots[0], knots[1]])];
    }
    else
    {
        segments = [];
        points = computePoints(knots);
        for(i=0; i<knots.length-1; i++)
            segments.push(bezier([knots[i], points[0][i], points[1][i], knots[i+1]]));
    }
    return segments;
}

又见 相关职位

改编自 此处

© www.soinside.com 2019 - 2024. All rights reserved.