Micha: B-Spline, letzter Funktionswert immer Null.

Hallo,

ich habe den Beitrag von Daniel Thoma gelesen und aus interesse mal ein wenig probiert. Als weitere Quelle habe ich noch diese gefunden und benutzt, wobei der Inhalt ähnlich ist.

Zu meinem Problem. Ich erzeuge den Knotenvektor wie bei der Osnabruecker Seite angegeben - wobei das keine Rolle spielt. Mein Problem ist, wenn der Funktionswert im letzten Intervall liegt und mit der Intervallgrenze zusammenfällt; in diesem Fall bekomme ich wohl ein "Null-Polynom" zurück, sodass die Kurve nicht durch den letzten Punkt geht, sondern durch den Ursprung (siehe Screenshot). Der letzte interpolierte Punkt (im Code unten das Array bSplinePoints) ist also 0,0.

B-Spline

Ist das korrekt, sodass die Kurve einfach zum letzten Wert interpoliert wird oder mach ich einen Fehler bzw. ist für den letzten Abschnitt eine Zusatzbedingung einzuführen? Ich hätte erwartet, da die Kurve auch im ersten Punkt beginnt, dass sie auch durch den letzten geht.

Der vollständigkeithalber noch mein Code (MatLab), da mglw. nur ein Laufindex falsch ist.

B-Spline Polynom
[code=Matlab]
function N = BSplinePolynom(i,p,T,t)
    if (p==1)
        if (T(i)<=t && t<T(i+1))
            N=1;
            return;
        else
            N=0;
            return;
        end
    end

N = 0;
    if (T(i+p-1) - T(i) ~= 0)
        N = (t-T(i)) / (T(i+p-1) - T(i)) * BSplinePolynom(i,p-1,T,t);
    end

if (T(i+p) - T(i+1) ~= 0)
        N = N + (T(i+p)-t) / (T(i+p) - T(i+1)) * BSplinePolynom(i+1,p-1,T,t);
    end
    return;
end
[/code]

Berechnung der Stützstellen
[code=Matlab]
function [bSplinePoints T] = BSpline(Points, k, T, interp)
    n = size(Points,1)-1;

% Bestimmt Knotenvektor, wenn keiner vorhanden
    if (nargin < 3 || isempty(T))
        T = zeros(n+k,1);
        for j=0:n+k
            if (j<k)
                T(j+1) = 0;
            elseif (k<= j && j <=n)
                T(j+1) = j-k+1;
            elseif (j>n)
                T(j+1) = n-k+2;
            end
        end
    end

if (nargin < 4)
        interp = 25;
    end

t = 0:1/interp:max(T);

bSplinePoints = zeros(length(t),2);
    for j=1:length(t)
        for i=1:n+1
            bSplinePoints(j,1) = bSplinePoints(j,1) + Points(i,1) * BSplinePolynom(i,k,T,t(j));
            bSplinePoints(j,2) = bSplinePoints(j,2) + Points(i,2) * BSplinePolynom(i,k,T,t(j));
        end
    end

return;
end
[/code]

Und das geplottete Beispiel:
[code=Matlab]
P = [
     1 10
     6  5
     10 7
    14  5
    19 10

];

k = 3;

bSplinePoints = BSpline(P, k);
[/code]

Vielen Dank für Eure Hilfe!

Mit freundlichem Gruß
Micha

  1. Hallo,

    ich denke, ich konnte das Problem lösen. Die Bestimmung der Polynome erfolgt ja immer im Intervall [a,b[. Die zweite Schranke ist daher nicht im Intervall selbst enthalten und wird beim nächsten Polynom mit erfasst [b,c[. Im letzten Intervall fehlt folglich der letzte Grenzwert, der, da es kein weiteres Polynom gibt, nicht berücksichtigt wird. Ich habe daher die Funktion BSplinePolynom modifiziert, dass diese nun prüft, ob es sich um die letzte Intervallsschranke handelt. Der Code sieht wie folgt aus:

    [code=Matlab]
    function N = BSplinePolynom(i,p,T,t,p0)
        if (nargin==4)
            p0 = p;
        end

    if (p==1)
            if (T(i)<=t && t<T(i+1)) || (t==T(i+1) && i+p0 == length(T))
                N=1;
                return;
            else
                N=0;
                return;
            end
        end

    N = 0;
        if (T(i+p-1) - T(i) ~= 0)
            N = (t-T(i)) / (T(i+p-1) - T(i)) * BSplinePolynom(i,p-1,T,t,p0);
        end

    if (T(i+p) - T(i+1) ~= 0)
            N = N + (T(i+p)-t) / (T(i+p) - T(i+1)) * BSplinePolynom(i+1,p-1,T,t,p0);
        end
        return;
    end [/code]

    Ich hoffe, es passt nun. ;-)

    Mit freundlichem Gruß
    Micha