]> Creatis software - CreaPhase.git/blobdiff - octave_packages/nurbs-1.3.6/basisfunder.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / nurbs-1.3.6 / basisfunder.m
diff --git a/octave_packages/nurbs-1.3.6/basisfunder.m b/octave_packages/nurbs-1.3.6/basisfunder.m
new file mode 100644 (file)
index 0000000..c6f0a89
--- /dev/null
@@ -0,0 +1,151 @@
+function dersv = basisfunder (ii, pl, uu, u_knotl, nders)
+
+% BASISFUNDER:  B-Spline Basis function derivatives.
+%
+% Calling Sequence:
+% 
+%   ders = basisfunder (ii, pl, uu, k, nd)
+%
+%    INPUT:
+%   
+%      ii  - knot span index (see findspan)
+%      pl  - degree of curve
+%      uu  - parametric points
+%      k   - knot vector
+%      nd  - number of derivatives to compute
+%
+%    OUTPUT:
+%   
+%      ders - ders(n, i, :) (i-1)-th derivative at n-th point
+%   
+%    Adapted from Algorithm A2.3 from 'The NURBS BOOK' pg72.
+%
+%    Copyright (C) 2009,2011 Rafael Vazquez
+%
+%    This program is free software: you can redistribute it and/or modify
+%    it under the terms of the GNU General Public License as published by
+%    the Free Software Foundation, either version 2 of the License, or
+%    (at your option) any later version.
+
+%    This program is distributed in the hope that it will be useful,
+%    but WITHOUT ANY WARRANTY; without even the implied warranty of
+%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%    GNU General Public License for more details.
+%
+%    You should have received a copy of the GNU General Public License
+%    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+  dersv = zeros(numel(uu), nders+1, pl+1);
+
+  for jj = 1:numel(uu)
+
+    i = ii(jj)+1; %% convert to base-1 numbering of knot spans
+    u = uu(jj);
+
+    ders = zeros(nders+1,pl+1);
+    ndu = zeros(pl+1,pl+1);
+    left = zeros(pl+1);
+    right = zeros(pl+1);
+    a = zeros(2,pl+1);
+    ndu(1,1) = 1;
+    for j = 1:pl
+      left(j+1) = u - u_knotl(i+1-j);
+      right(j+1) = u_knotl(i+j) - u;
+      saved = 0;
+      for r = 0:j-1
+        ndu(j+1,r+1) = right(r+2) + left(j-r+1);
+        temp = ndu(r+1,j)/ndu(j+1,r+1);
+        ndu(r+1,j+1) = saved + right(r+2)*temp;
+        saved = left(j-r+1)*temp;
+      end
+      ndu(j+1,j+1) = saved;
+    end   
+    for j = 0:pl
+      ders(1,j+1) = ndu(j+1,pl+1);
+    end
+    for r = 0:pl
+      s1 = 0;
+      s2 = 1;
+      a(1,1) = 1;
+      for k = 1:nders %compute kth derivative
+        d = 0;
+        rk = r-k;
+        pk = pl-k;
+        if (r >= k)
+          a(s2+1,1) = a(s1+1,1)/ndu(pk+2,rk+1);
+          d = a(s2+1,1)*ndu(rk+1,pk+1);
+        end
+        if (rk >= -1)
+          j1 = 1;
+        else 
+          j1 = -rk;
+        end
+        if ((r-1) <= pk)
+          j2 = k-1;
+        else 
+          j2 = pl-r;
+        end
+        for j = j1:j2
+          a(s2+1,j+1) = (a(s1+1,j+1) - a(s1+1,j))/ndu(pk+2,rk+j+1);
+          d = d + a(s2+1,j+1)*ndu(rk+j+1,pk+1);
+        end
+        if (r <= pk)
+          a(s2+1,k+1) = -a(s1+1,k)/ndu(pk+2,r+1);
+          d = d + a(s2+1,k+1)*ndu(r+1,pk+1);
+        end
+        ders(k+1,r+1) = d;
+        j = s1;
+        s1 = s2;
+        s2 = j;
+      end
+    end
+    r = pl;
+    for k = 1:nders
+      for j = 0:pl
+        ders(k+1,j+1) = ders(k+1,j+1)*r;
+      end
+      r = r*(pl-k);
+    end
+
+    dersv(jj, :, :) = ders;
+    
+  end
+
+end
+
+%!test
+%! k    = [0 0 0 0 1 1 1 1];
+%! p    = 3;
+%! u    = rand (1);
+%! i    = findspan (numel(k)-p-2, p, u, k);
+%! ders = basisfunder (i, p, u, k, 1);
+%! sumders = sum (squeeze(ders), 2);
+%! assert (sumders(1), 1, 1e-15);
+%! assert (sumders(2:end), 0, 1e-15);
+
+%!test
+%! k    = [0 0 0 0 1/3 2/3 1 1 1 1];
+%! p    = 3;
+%! u    = rand (1);
+%! i    = findspan (numel(k)-p-2, p, u, k);
+%! ders = basisfunder (i, p, u, k, 7); 
+%! sumders = sum (squeeze(ders), 2);
+%! assert (sumders(1), 1, 1e-15);
+%! assert (sumders(2:end), zeros(rows(squeeze(ders))-1, 1), 1e-13);
+
+%!test
+%! k    = [0 0 0 0 1/3 2/3 1 1 1 1];
+%! p    = 3;
+%! u    = rand (100, 1);
+%! i    = findspan (numel(k)-p-2, p, u, k);
+%! ders = basisfunder (i, p, u, k, 7);
+%! for ii=1:10
+%!   sumders = sum (squeeze(ders(ii,:,:)), 2);
+%!   assert (sumders(1), 1, 1e-15);
+%!   assert (sumders(2:end), zeros(rows(squeeze(ders(ii,:,:)))-1, 1), 1e-13);
+%! end
+%! assert (ders(:, (p+2):end, :), zeros(numel(u), 8-p-1, p+1), 1e-13)
+%! assert (all(all(ders(:, 1, :) <= 1)), true)
+
+
+