changeset 8215:613633634c8e octave-forge

New version to compute the second derivatives
author rafavzqz
date Fri, 22 Jul 2011 15:17:10 +0000
parents 8c1ab65f1d79
children cf6fa5ab41d4
files extra/nurbs/inst/nrbderiv.m extra/nurbs/inst/nrbdeval.m
diffstat 2 files changed, 153 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/extra/nurbs/inst/nrbderiv.m	Fri Jul 22 13:22:03 2011 +0000
+++ b/extra/nurbs/inst/nrbderiv.m	Fri Jul 22 15:17:10 2011 +0000
@@ -1,11 +1,12 @@
-function dnurbs = nrbderiv(nurbs)
+function varargout = nrbderiv (nurbs)
 % 
-% NRBDERIV: Construct the first derivative representation of a
+% NRBDERIV2: Construct the first and second derivative representation of a
 %           NURBS curve, surface or volume.
 % 
 % Calling Sequence:
 % 
-%   ders = nrbderiv(nrb);
+%   ders = nrbderiv (nrb);
+%   [ders, ders2] = nrbderiv (nrb);
 % 
 % INPUT:
 % 
@@ -13,34 +14,28 @@
 %
 % OUTPUT:
 % 
-%   ders	: A data structure that represents the first
-% 		  derivatives of a NURBS curve, surface or volume.
+%   ders:  A data structure that represents the first
+% 		    derivatives of a NURBS curve, surface or volume.
+%   ders2: A data structure that represents the second
+% 		    derivatives of a NURBS curve, surface or volume.
 % 
 % Description:
 % 
 %   The derivatives of a B-Spline are themselves a B-Spline of lower degree,
 %   giving an efficient means of evaluating multiple derivatives. However,
 %   although the same approach can be applied to NURBS, the situation for
-%   NURBS is a more complex. I have at present restricted the derivatives
-%   to just the first. I don't claim that this implentation is
-%   the best approach, but it will have to do for now. The function returns
-%   a data struture that for a NURBS curve contains the first derivatives of
-%   the B-Spline representation. Remember that a NURBS curve is represent by
-%   a univariate B-Spline using the homogeneous coordinates.
-%   The derivative data structure can be evaluated later with the function
-%   nrbdeval.
-% 
-% Examples:
-% 
-%   See the function nrbdeval for an example.
+%   NURBS is more complex. We have followed in this function the same idea
+%   that was already used for the first derivative in the function nrbderiv.
+%   The second derivative data structure can be evaluated later with the
+%   function nrbdeval2.
 % 
 % See also:
 % 
 %       nrbdeval
 %
 % Copyright (C) 2000 Mark Spink
-% Copyright (C) 2010 Rafael Vazquez
 % Copyright (C) 2010 Carlo de Falco
+% Copyright (C) 2010, 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
@@ -55,18 +50,24 @@
 %    You should have received a copy of the GNU General Public License
 %    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if ~isstruct(nurbs)
+if (~isstruct(nurbs))
   error('NURBS representation is not structure!');
 end
 
-if ~strcmp(nurbs.form,'B-NURBS')
+if (~strcmp(nurbs.form,'B-NURBS'))
   error('Not a recognised NURBS representation');
 end
 
+% We raise the degree to avoid errors in the computation of the second derivative
+if (nargout == 2)
+  degelev  = max ([2 2] - (nurbs.order-1), 0);
+  nurbs    = nrbdegelev (nurbs, degelev);
+end
+
 degree = nurbs.order - 1;
 
-if iscell(nurbs.knots)
-  if size(nurbs.knots,2) == 3
+if (iscell(nurbs.knots))
+  if (size(nurbs.knots,2) == 3)
   % NURBS structure represents a volume
     num1 = nurbs.number(1);
     num2 = nurbs.number(2);
@@ -74,56 +75,98 @@
 
   % taking derivatives along the u direction
     dknots = nurbs.knots;
-    dcoefs = permute(nurbs.coefs,[1 3 4 2]);
-    dcoefs = reshape(dcoefs,4*num2*num3,num1);
-    [dcoefs,dknots{1}] = bspderiv(degree(1),dcoefs,nurbs.knots{1});
-    dcoefs = permute(reshape(dcoefs,[4 num2 num3 size(dcoefs,2)]),[1 4 2 3]);
-    dnurbs{1} = nrbmak(dcoefs, dknots);
+    dcoefs = permute (nurbs.coefs,[1 3 4 2]);
+    dcoefs = reshape (dcoefs,4*num2*num3,num1);
+    [dcoefs,dknots{1}] = bspderiv (degree(1),dcoefs,nurbs.knots{1});
+    dcoefs = permute (reshape (dcoefs,[4 num2 num3 size(dcoefs,2)]),[1 4 2 3]);
+    dnurbs{1} = nrbmak (dcoefs, dknots);
 
   % taking derivatives along the v direction
     dknots = nurbs.knots;
-    dcoefs = permute(nurbs.coefs,[1 2 4 3]);
-    dcoefs = reshape(dcoefs,4*num1*num3,num2);
-    [dcoefs,dknots{2}] = bspderiv(degree(2),dcoefs,nurbs.knots{2});
-    dcoefs = permute(reshape(dcoefs,[4 num1 num3 size(dcoefs,2)]),[1 2 4 3]);
-    dnurbs{2} = nrbmak(dcoefs, dknots);
+    dcoefs = permute (nurbs.coefs,[1 2 4 3]);
+    dcoefs = reshape (dcoefs,4*num1*num3,num2);
+    [dcoefs,dknots{2}] = bspderiv (degree(2),dcoefs,nurbs.knots{2});
+    dcoefs = permute (reshape (dcoefs,[4 num1 num3 size(dcoefs,2)]),[1 2 4 3]);
+    dnurbs{2} = nrbmak (dcoefs, dknots);
 
   % taking derivatives along the w direction
     dknots = nurbs.knots;
-    dcoefs = reshape(nurbs.coefs,4*num1*num2,num3);
-    [dcoefs,dknots{3}] = bspderiv(degree(3),dcoefs,nurbs.knots{3});
-    dcoefs = reshape(dcoefs,[4 num1 num2 size(dcoefs,2)]);
-    dnurbs{3} = nrbmak(dcoefs, dknots);
+    dcoefs = reshape (nurbs.coefs,4*num1*num2,num3);
+    [dcoefs,dknots{3}] = bspderiv (degree(3),dcoefs,nurbs.knots{3});
+    dcoefs = reshape (dcoefs,[4 num1 num2 size(dcoefs,2)]);
+    dnurbs{3} = nrbmak (dcoefs, dknots);
 
-  elseif size(nurbs.knots,2) == 2
-  % NURBS structure represents a surface
+    if (nargout == 2)
+      warning ('nrbderiv: the second derivative is not ready for volumes');
+      dnurbs2 = [];
+    end
+
+  elseif (size(nurbs.knots,2) == 2)
+% NURBS structure represents a surface
 
     num1 = nurbs.number(1);
     num2 = nurbs.number(2);
 
-  % taking derivatives along the u direction
+% taking first derivative along the u direction
     dknots = nurbs.knots;
-    dcoefs = permute(nurbs.coefs,[1 3 2]);
-    dcoefs = reshape(dcoefs,4*num2,num1);
-    [dcoefs,dknots{1}] = bspderiv(degree(1),dcoefs,nurbs.knots{1});
-    dcoefs = permute(reshape(dcoefs,[4 num2 size(dcoefs,2)]),[1 3 2]);
-    dnurbs{1} = nrbmak(dcoefs, dknots);
+    dcoefs = permute (nurbs.coefs,[1 3 2]);
+    dcoefs = reshape (dcoefs,4*num2,num1);
+    [dcoefs,dknots{1}] = bspderiv (degree(1),dcoefs,nurbs.knots{1});
+    dcoefs = permute (reshape (dcoefs,[4 num2 size(dcoefs,2)]),[1 3 2]);
+    dnurbs{1} = nrbmak (dcoefs, dknots);
+
+    if (nargout == 2)
+% taking second derivative along the u direction (duu)
+      dknots2 = dknots;
+      dcoefs2 = permute (dcoefs, [1 3 2]);
+      dcoefs2 = reshape (dcoefs2, 4*num2, []);
+      [dcoefs2, dknots2{1}] = bspderiv (degree(1)-1, dcoefs2, dknots{1});
+      dcoefs2 = permute (reshape (dcoefs2, 4, num2, []), [1 3 2]);
+      dnurbs2{1,1} = nrbmak (dcoefs2, dknots2); 
 
-  % taking derivatives along the v direction
+% taking second derivative along the v direction (duv and dvu)
+      dknots2 = dknots;
+      dcoefs2 = reshape (dcoefs, 4*(num1-1), num2);
+      [dcoefs2, dknots2{2}] = bspderiv (degree(2), dcoefs2, dknots{2});
+      dcoefs2 = reshape (dcoefs2, 4, num1-1, []);
+      dnurbs2{1,2} = nrbmak (dcoefs2, dknots2);
+      dnurbs2{2,1} = dnurbs2{1,2};
+    end
+
+% taking first derivative along the v direction
     dknots = nurbs.knots;
-    dcoefs = reshape(nurbs.coefs,4*num1,num2);
-    [dcoefs,dknots{2}] = bspderiv(degree(2),dcoefs,nurbs.knots{2});
-    dcoefs = reshape(dcoefs,[4 num1 size(dcoefs,2)]);
-    dnurbs{2} = nrbmak(dcoefs, dknots);
+    dcoefs = reshape (nurbs.coefs,4*num1,num2);
+    [dcoefs,dknots{2}] = bspderiv (degree(2),dcoefs,nurbs.knots{2});
+    dcoefs = reshape (dcoefs,[4 num1 size(dcoefs,2)]);
+    dnurbs{2} = nrbmak (dcoefs, dknots);
+
+    if (nargout == 2)
+% taking second derivative along the v direction (dvv)
+      dknots2 = dknots;
+      dcoefs2 = reshape (dcoefs, 4*num1, num2-1);
+      [dcoefs2, dknots2{2}] = bspderiv (degree(2)-1, dcoefs2, dknots{2});
+      dcoefs2 = reshape (dcoefs2, 4, num1, []);
+      dnurbs2{2,2} = nrbmak (dcoefs2, dknots2);
+    end
+
   end
 else
   % NURBS structure represents a curve
 
-  [dcoefs,dknots] = bspderiv(degree,nurbs.coefs,nurbs.knots);
-  dnurbs = nrbmak(dcoefs, dknots);
+  [dcoefs,dknots] = bspderiv (degree, nurbs.coefs, nurbs.knots);
+  dnurbs = nrbmak (dcoefs, dknots);
+  if (nargout == 2)
+    [dcoefs2,dknots2] = bspderiv (degree-1, dcoefs, dknots);
+    dnurbs2 = nrbmak (dcoefs2, dknots2);
+  end
 
 end
 
+varargout{1} = dnurbs;
+if (nargout == 2)
+  varargout{2} = dnurbs2;
+end
+
 end
 
 %!demo
--- a/extra/nurbs/inst/nrbdeval.m	Fri Jul 22 13:22:03 2011 +0000
+++ b/extra/nurbs/inst/nrbdeval.m	Fri Jul 22 15:17:10 2011 +0000
@@ -1,25 +1,21 @@
-function [pnt,jac] = nrbdeval(nurbs, dnurbs, tt)
+function varargout = nrbdeval (nurbs, dnurbs, varargin)
 
-% NRBDEVAL: Evaluation of the derivative NURBS curve, surface or volume.
+% NRBDEVAL: Evaluation of the derivative and second derivatives of NURBS curve, surface or volume.
 %
-%     [pnt, jac] = nrbdeval(crv, dcrv, tt)
-%     [pnt, jac] = nrbdeval(srf, dsrf, {tu tv})
-%     [pnt, jac] = nrbdeval(vol, dvol, {tu tv tw})
+%     [pnt, jac] = nrbdeval (crv, dcrv, tt)
+%     [pnt, jac] = nrbdeval (srf, dsrf, {tu tv})
+%     [pnt, jac] = nrbdeval (vol, dvol, {tu tv tw})
+%     [pnt, jac, hess] = nrbdeval (crv, dcrv, dcrv2, tt)
+%     [pnt, jac, hess] = nrbdeval (srf, dsrf, dsrf2, {tu tv})
+%     [pnt, jac, hess] = nrbdeval (vol, dvol, {tu tv tw})
 %
 % INPUTS:
 %
-%   crv    - original NURBS curve.
-%
-%   srf    - original NUBRS surface
-%
-%   vol    - original NUBRS volume
-%
-%   dcrv   - NURBS derivative representation of crv
-%
-%   dsrf   - NURBS derivative representation of surface
-%
-%   dvol   - NURBS derivative representation of volume
-%
+%   crv,   srf,   vol   - original NURBS curve, surface or volume.
+%   dcrv,  dsrf,  dvol  - NURBS derivative representation of crv, srf 
+%                          or vol (see nrbderiv2)
+%   dcrv2, dsrf2, dvol2 - NURBS second derivative representation of crv,
+%                          srf or vol (see nrbderiv2)
 %   tt     - parametric evaluation points
 %            If the nurbs is a surface or a volume then tt is a cell
 %            {tu, tv} or {tu, tv, tw} are the parametric coordinates
@@ -28,18 +24,11 @@
 %
 %   pnt  - evaluated points.
 %   jac  - evaluated first derivatives (Jacobian).
-%
-% Examples:
-% 
-%   // Determine the first derivatives a NURBS curve at 9 points for 0.0 to
-%   // 1.0
-%   tt = linspace(0.0, 1.0, 9);
-%   dcrv = nrbderiv(crv);
-%   [pnts,jac] = nrbdeval(crv, dcrv, tt);
+%   hess - evaluated second derivatives (Hessian).
 %
 % Copyright (C) 2000 Mark Spink 
-% Copyright (C) 2010 Rafael Vazquez
 % Copyright (C) 2010 Carlo de Falco
+% Copyright (C) 2010, 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
@@ -54,6 +43,15 @@
 %    You should have received a copy of the GNU General Public License
 %    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+if (nargin == 3)
+  tt = varargin{1};
+elseif (nargin == 4)
+  dnurbs2 = varargin{1};
+  tt = varargin{2};
+else 
+  error ('nrbrdeval: wrong number of input parameters')
+end
+
 if (~isstruct(nurbs))
   error('NURBS representation is not structure!');
 end
@@ -62,7 +60,7 @@
   error('Not a recognised NURBS representation');
 end
 
-[cp,cw] = nrbeval (nurbs, tt);
+[cp,cw] = nrbeval(nurbs, tt);
 
 if (iscell(nurbs.knots))
   if (size(nurbs.knots,2) == 3)
@@ -82,6 +80,11 @@
     tempw = cww(ones(3,1),:,:,:);
     jac{3} = (cwp-tempw.*pnt)./temp;
 
+    if (nargout == 3)
+      warning ('nrbdeval: the second derivative is not ready for volumes');
+      hess = [];
+    end
+
   elseif (size(nurbs.knots,2) == 2)
   % NURBS structure represents a surface
     temp = cw(ones(3,1),:,:);
@@ -95,6 +98,22 @@
     tempv = cvw(ones(3,1),:,:);
     jac{2} = (cvp-tempv.*pnt)./temp;
 
+% second derivatives
+    if (nargout == 3 && exist ('dnurbs2'))
+      [cuup, cuuw] = nrbeval (dnurbs2{1,1}, tt);
+      tempuu = cuuw(ones(3,1),:,:);
+      hess{1,1} = (cuup - (2*cup.*tempu + cp.*tempuu)./temp + 2*cp.*tempu.^2./temp.^2)./temp;
+
+      [cvvp, cvvw] = nrbeval (dnurbs2{2,2}, tt);
+      tempvv = cvvw(ones(3,1),:,:);
+      hess{2,2} = (cvvp - (2*cvp.*tempv + cp.*tempvv)./temp + 2*cp.*tempv.^2./temp.^2)./temp;
+
+      [cuvp, cuvw] = nrbeval (dnurbs2{1,2}, tt);
+      tempuv = cuvw(ones(3,1),:,:);
+      hess{1,2} = (cuvp - (cup.*tempv + cvp.*tempu + cp.*tempuv)./temp + 2*cp.*tempu.*tempv./temp.^2)./temp;
+      hess{2,1} = hess{1,2};
+    end
+
   end
 else
 
@@ -107,6 +126,19 @@
   temp1 = cuw(ones(3,1),:);
   jac = (cup-temp1.*pnt)./temp;
 
+  % second derivative
+  if (nargout == 3 && exist ('dnurbs2'))
+    [cuup,cuuw] = nrbeval (dnurbs2, tt);
+    temp2 = cuuw(ones(3,1),:);
+    hess = (cuup - (2*cup.*temp1 + cp.*temp2)./temp + 2*cp.*temp1.^2./temp.^2)./temp;
+  end
+
+end
+
+varargout{1} = pnt;
+varargout{2} = jac;
+if (nargout == 3)
+  varargout{3} = hess;
 end
 
 end