changeset 9403:2108d03d50de octave-forge

Fixed bug in 1D, added 3D case, added derivatives
author rafavzqz
date Mon, 06 Feb 2012 13:48:17 +0000
parents 45f81afe5b34
children 29f6872a57d0
files extra/nurbs/src/tbasisfun.cc
diffstat 1 files changed, 101 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/extra/nurbs/src/tbasisfun.cc	Sun Feb 05 16:07:55 2012 +0000
+++ b/extra/nurbs/src/tbasisfun.cc	Mon Feb 06 13:48:17 2012 +0000
@@ -1,4 +1,5 @@
 /* Copyright (C) 2009 Carlo de Falco
+   Copyright (C) 2012 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
@@ -23,7 +24,7 @@
   //std::cout << "u=" << u << " " << "p=" << p << " \n" << "U=" << U;
   
   double N = 0.0;
-  if ((u < U.min ()) || ( u > U.max ()))
+  if ((u <= U.min ()) || ( u > U.max ()))
     return (N);
   else if (p == 0)
     return (1.0);
@@ -41,14 +42,40 @@
   return (N);
 }
 
+
+double onebasisfunder__ (double u, octave_idx_type p, RowVector U)
+{
+
+  //std::cout << "u=" << u << " " << "p=" << p << " \n" << "U=" << U;
+  
+  double N = 0.0;
+  if ((u <= U.min ()) || ( u > U.max ()))
+    return (N);
+  else if (p == 0)
+    return (0.0);
+  else {
+ 
+  double ld = U(U.length () - 2) - U(0);
+  if (ld != 0)
+    N += p * onebasisfun__ (u, p-1, U.extract (0, U.length () - 2))/ ld; 
+    
+  double dd = U(U.length () - 1) - U(1);
+  if (dd != 0)
+    N -= p * onebasisfun__ (u, p-1, U.extract (1, U.length () - 1))/ dd;
+    
+  return (N);
+  }
+}
+
    
-DEFUN_DLD(tbasisfun, args, nargout,"\
-TBASISFUN: Compute a B- or T-Spline basis function from its local knot vector.\n\
+DEFUN_DLD(tbasisfunder, args, nargout,"\
+TBASISFUN: Compute a B- or T-Spline basis function, and its derivatives, from its local knot vector.\n\
 \n\
  usage:\n\
 \n\
- N = tbasisfun (u, p, U)\n\
- N = tbasisfun ([u; v], [p q], {U, V})\n\
+ [N, Nder] = tbasisfun (u, p, U)\n\
+ [N, Nder] = tbasisfun ([u; v], [p q], {U, V})\n\
+ [N, Nder] = tbasisfun ([u; v; w], [p q r], {U, V, W})\n\
  \n\
  INPUT:\n\
   u or [u; v] : points in parameter space where the basis function is to be\n\
@@ -56,16 +83,18 @@
   \n\
   U or {U, V} : local knot vector\n\
 \n\
- p or [p q] : polynomial order of the basis function\n\
+  p or [p q] : polynomial order of the basis function\n\
 \n\
  OUTPUT:\n\
-  N : basis function evaluated at the given parametric points\n")
+  N : basis function evaluated at the given parametric points\n\
+  Nder : gradient of the basis function evaluated at the given points\n")
 
 {
   
   octave_value_list retval;
   Matrix u = args(0).matrix_value ();
 
+  RowVector N(u.cols ());
   if (! args(2).is_cell ())
     {
 
@@ -73,37 +102,79 @@
       RowVector U = args(2).row_vector_value (true, true);
       assert (U.numel () == p+2);
       
-      RowVector N(u.cols ());
       for (octave_idx_type ii=0; ii<u.numel (); ii++)
 	N(ii) = onebasisfun__ (u(ii), p, U);
 
+      if (nargout == 2) {
+        RowVector Nder(u.cols ());
+        for (octave_idx_type ii=0; ii<u.numel (); ii++)
+          Nder(ii) = onebasisfunder__ (u(ii), p, U);
+        retval(1) = Nder;
+      }
+
     }  else {
-
     RowVector p = args(1).row_vector_value ();
-    Cell C = args(2).cell_value ();
-    RowVector U = C(0).row_vector_value (true, true);
-    RowVector V = C(1).row_vector_value (true, true);
+
+    if (p.length() == 2) {
+      Cell C = args(2).cell_value ();
+      RowVector U = C(0).row_vector_value (true, true);
+      RowVector V = C(1).row_vector_value (true, true);
     
+      for (octave_idx_type ii=0; ii<u.cols (); ii++)
+        {
+          N(ii) = onebasisfun__ (u(0, ii), octave_idx_type(p(0)), U) *
+            onebasisfun__ (u(1, ii), octave_idx_type(p(1)), V);
+	//std::cout << "N=" << N(ii) << "\n\n\n";
+        }
+
+      if (nargout == 2) {
+        Matrix Nder (2, u.cols());
+        for (octave_idx_type ii=0; ii<u.cols (); ii++)
+          {
+            Nder(0,ii) = onebasisfunder__ (u(0, ii), octave_idx_type(p(0)), U) *
+              onebasisfun__ (u(1, ii), octave_idx_type(p(1)), V);
+            Nder(1,ii) = onebasisfun__ (u(0, ii), octave_idx_type(p(0)), U) *
+              onebasisfunder__ (u(1, ii), octave_idx_type(p(1)), V);
+	//std::cout << "N=" << N(ii) << "\n\n\n";
+          }
+        retval(1) = Nder;
+        }
 
-    RowVector N(u.cols ());
-    for (octave_idx_type ii=0; ii<u.cols (); ii++)
-      {
-	N(ii) = onebasisfun__ (u(0, ii), octave_idx_type(p(0)), U) *
-	  onebasisfun__ (u(1, ii), octave_idx_type(p(1)), V);
+    } else if (p.length() == 3) {
+      Cell C = args(2).cell_value ();
+      RowVector U = C(0).row_vector_value (true, true);
+      RowVector V = C(1).row_vector_value (true, true);
+      RowVector W = C(2).row_vector_value (true, true);
+    
+      for (octave_idx_type ii=0; ii<u.cols (); ii++)
+        {
+          N(ii) = onebasisfun__ (u(0, ii), octave_idx_type(p(0)), U) *
+            onebasisfun__ (u(1, ii), octave_idx_type(p(1)), V) *
+            onebasisfun__ (u(2, ii), octave_idx_type(p(2)), W);
 	//std::cout << "N=" << N(ii) << "\n\n\n";
-      }
-    retval(0) = octave_value (N);
+        }
+
+      if (nargout == 2) {
+        Matrix Nder (3, u.cols());
+        double Nu, Nv, Nw;
+        for (octave_idx_type ii=0; ii<u.cols (); ii++)
+          {
+            Nu = onebasisfun__ (u(0, ii), octave_idx_type(p(0)), U);
+            Nv = onebasisfun__ (u(1, ii), octave_idx_type(p(1)), V);
+            Nw = onebasisfun__ (u(2, ii), octave_idx_type(p(2)), W);
+            Nder(0,ii) = onebasisfunder__ (u(0, ii), octave_idx_type(p(0)), U) *
+              Nv * Nw;
+            Nder(1,ii) = onebasisfunder__ (u(1, ii), octave_idx_type(p(1)), V) *
+              Nu * Nw;
+            Nder(2,ii) = onebasisfunder__ (u(2, ii), octave_idx_type(p(2)), W) *
+              Nu * Nv;
+	//std::cout << "N=" << N(ii) << "\n\n\n";
+          }
+        retval(1) = Nder;
+        }
+
+    }
   }
+  retval(0) = octave_value (N);
   return retval;
 }
-
-
-/*
-%!demo
-%! U = {[0 0 1/2 1 1], [0 0 0 1 1]};
-%! p = [3, 3];
-%! [X, Y] = meshgrid (linspace(0, 1, 30));
-%! u = [X(:), Y(:)]';
-%! N = tbasisfun (u, p, U);
-%! surf (X, Y, reshape (N, size(X)))
-*/