rt_dspline.c

Go to the documentation of this file.
00001 /*                    R T _ D S P L I N E . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2004-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup librt */
00023 /*@{*/
00024 /** @file rt_dspline.c
00025  * Simple data (double) spline package.
00026  *
00027  *  rt_dspline_matrix(m, type, tension, bias)   create basis matrix
00028  *  rt_dspline4(m, a, b, c, d, alpha)           interpolate 1 value
00029  *  rt_dspline4v(m, a, b, c, d, depth alpha)    interpolate vectors
00030  *  rt_dspline(r, m, knots, n, depth, alpha)    interpolate n knots over 0..1
00031  *
00032  *  Example:
00033  *      mat_t   m;
00034  *      double  d;
00035  *      vect_t  v;
00036  *      vect_t  kn = {  {0., 0., 0.},
00037  *                      {0., 1., 0.},
00038  *                      {.5, 1., 0.},
00039  *                      {1., 1., 0.},
00040  *                      {1., 0., 0.} };
00041  *
00042  *      rt_dspline_matrix(m, "Beta", 0.5, 1.0);
00043  *
00044  *      d = rt_dspline4(m, .0, .0, 1.0, 1.0, 0.25);
00045  *
00046  *      for (p = 0.0 ; p <= 1.0 ; p += 0.0625 ) {
00047  *              rt_dspline(v, m, kn, 5, 3, p);
00048  *              bu_log("%g (%g %g %g)\n", p, V3ARGS(v));
00049  *      }
00050  *
00051  *  Author -
00052  *      Lee A. Butler
00053  *
00054  *  Source -
00055  *      The U. S. Army Research Laboratory
00056  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00057  *
00058  */
00059 /*@}*/
00060 
00061 #ifndef lint
00062 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/rt_dspline.c,v 14.11 2006/09/16 02:04:26 lbutler Exp $ (ARL)";
00063 #endif
00064 
00065 #include "common.h"
00066 
00067 #include <stdlib.h>
00068 #include <stdio.h>
00069 #include <string.h>
00070 #include <math.h>
00071 
00072 #include "machine.h"
00073 #include "vmath.h"
00074 #include "bu.h"
00075 #include "raytrace.h"
00076 
00077 
00078 static void
00079 GetBeta(fastf_t *m, const double bias, const double tension)
00080 {
00081         register int i;
00082         double d, b2, b3;
00083         register double tmp;
00084 
00085         b2 = bias * bias;
00086         b3 = bias * b2;
00087 
00088         tmp = 2.0 * b3;
00089         m[12] = tmp;
00090         m[ 0] = -tmp;
00091 
00092         tmp = tension+b2+bias;
00093         m[ 1] = 2.0 * (tmp + b3);
00094         m[ 2] = -2.0 * (tmp + 1.0);
00095 
00096         tmp = tension + 2.0 * b2;
00097         m[ 5] = -3.0 * (tmp + 2.0 * b3);
00098         m[ 6] =  3.0 * tmp;
00099 
00100         tmp = 6.0 * b3;
00101         m[ 4] = tmp;
00102         m[ 8] = -tmp;
00103 
00104         m[ 9] = 6.0 * (b3 - bias);
00105         m[10] = 6.0 * bias;
00106 
00107         tmp = tension + 4.0 * (b2 + bias);
00108         m[13] = tmp;
00109         d = 1.0 / ( tmp + 2.0 * b3 + 2.0);
00110 
00111         m[ 3] = m[14] = 2.0;
00112         m[ 7] = m[11] = m[15] = 0.0;
00113 
00114         for (i=0 ; i < 16; i++) m[i] *= d;
00115 }
00116 
00117 static void
00118 GetCardinal(fastf_t *m, const double tension)
00119 {
00120         m[ 1] = 2.0 - tension;
00121         m[ 2] = tension - 2.0;
00122         m[ 4] = 2.0 * tension;
00123         m[ 5] = tension - 3.0;
00124         m[ 6] = 3.0 - 2.0 * tension;
00125         m[13] = 1.0;
00126         m[ 3] = m[10] = tension;
00127         m[ 0] = m[7] = m[ 8] = -tension;
00128         m[ 9] = m[11] = m[12] = m[14] = m[15] = 0.0;
00129 }
00130 
00131 /*      R T _ D S P L I N E _ M A T R I X
00132  *
00133  *      Initialize a spline matrix for a particular spline type.
00134  *
00135  */
00136 void
00137 rt_dspline_matrix(fastf_t *m, const char *type, const double tension, const double bias)
00138 
00139                                 /* "Cardinal", "Catmull", "Beta" */
00140                                 /* Cardinal tension of .5 is Catmull spline */
00141                                 /* only for B spline */
00142 {
00143         if (!strncmp(type, "Cardinal", 8))      GetCardinal(m, tension);
00144         else if (!strncmp(type, "Catmull", 7))  GetCardinal(m, 0.5);
00145         else if (!strncmp(type, "Beta", 4))     GetBeta(m, bias, tension);
00146         else {
00147                 bu_log( "Error: %s:%d spline type \"%s\" Unknown\n",
00148                         __FILE__, __LINE__, type);
00149                 abort();
00150         }
00151 }
00152 
00153 /*      R T _ D S P L I N E 4
00154  *
00155  *      m               spline matrix (see rt_dspline4_matrix)
00156  *      a, b, c, d      knot values
00157  *      alpha:  0..1    interpolation point
00158  *
00159  *      Evaluate a 1-dimensional spline at a point "alpha" on knot values
00160  *      a, b, c, d.
00161  */
00162 double
00163 rt_dspline4(fastf_t *m, double a, double b, double c, double d, double alpha)
00164                         /* spline matrix */
00165                         /* control pts */
00166                         /* point to interpolate at */
00167 {
00168         double p0, p1, p2, p3;
00169 
00170         p0 = m[ 0]*a + m[ 1]*b + m[ 2]*c + m[ 3]*d;
00171         p1 = m[ 4]*a + m[ 5]*b + m[ 6]*c + m[ 7]*d;
00172         p2 = m[ 8]*a + m[ 9]*b + m[10]*c + m[11]*d;
00173         p3 = m[12]*a + m[13]*b + m[14]*c + m[15]*d;
00174 
00175         return  p3 +  alpha*(p2 + alpha*(p1 + alpha*p0) );
00176 }
00177 
00178 /*      R T _ D S P L I N E 4 V
00179  *
00180  *      pt              vector to recieve the interpolation result
00181  *      m               spline matrix (see rt_dspline4_matrix)
00182  *      a, b, c, d      knot values
00183  *      alpha:  0..1    interpolation point
00184  *
00185  *  Evaluate a spline at a point "alpha" between knot pts b & c
00186  *  The knots and result are all vectors with "depth" values (length).
00187  *
00188  */
00189 void
00190 rt_dspline4v(double *pt, const fastf_t *m, const double *a, const double *b, const double *c, const double *d, const int depth, const double alpha)
00191                 /* result */
00192                         /* spline matrix obtained with spline_matrix() */
00193                         /* knots */
00194 
00195 
00196 
00197                         /* number of values per knot */
00198                         /* 0 <= alpha <= 1 */
00199 {
00200         int i;
00201         double p0, p1, p2, p3;
00202 
00203         for (i=0 ; i < depth ; i++) {
00204                 p0 = m[ 0]*a[i] + m[ 1]*b[i] + m[ 2]*c[i] + m[ 3]*d[i];
00205                 p1 = m[ 4]*a[i] + m[ 5]*b[i] + m[ 6]*c[i] + m[ 7]*d[i];
00206                 p2 = m[ 8]*a[i] + m[ 9]*b[i] + m[10]*c[i] + m[11]*d[i];
00207                 p3 = m[12]*a[i] + m[13]*b[i] + m[14]*c[i] + m[15]*d[i];
00208 
00209                 pt[i] = p3 +  alpha*(p2 + alpha*(p1 + alpha*p0) );
00210         }
00211 }
00212 
00213 
00214 /*      R T _ D S P L I N E _ N
00215  *
00216  *      Interpolate n knot vectors over the range 0..1
00217  *
00218  *      "knots" is an array of "n" knot vectors.  Each vector consists of
00219  *      "depth" values.  They define an "n" dimensional surface which is
00220  *      evaluated at the single point "alpha".  The evaluated point is
00221  *      returned in "r"
00222  *
00223  *      Example use:
00224  *              double result[MAX_DEPTH], knots[MAX_DEPTH*MAX_KNOTS];
00225  *              mat_t   m;
00226  *              int     knot_count, depth;
00227  *
00228  *              knots = bu_malloc(sizeof(double) * knot_length * knot_count);
00229  *              result = bu_malloc(sizeof(double) * knot_length);
00230  *
00231  *              rt_dspline4_matrix(m, "Catmull", (double *)NULL, 0.0);
00232  *
00233  *              for (i=0 ; i < knot_count ; i++)
00234  *                      get a knot(knots, i, knot_length);
00235  *
00236  *              rt_dspline_n(result, m, knots, knot_count, knot_length, alpha);
00237  *
00238  */
00239 void
00240 rt_dspline_n(double *r, const fastf_t *m, const double *knots, const int nknots, const int depth, const double alpha)
00241                         /* result */
00242                         /* spline matrix */
00243                         /* knot values */
00244                         /* number of knots */
00245                         /* number of values per knot */
00246                         /* point on surface (0..1) to evaluate */
00247 {
00248         double *a, *b, *c, *d, x;
00249         int nspans = nknots - 3;
00250         int span;
00251 
00252         /* validate args */
00253         if (nspans < 1 || depth < 1 || alpha < 0.0 || alpha > 1.0 ||
00254             !r || !knots)
00255             bu_bomb("invalid args given to rt_dspline_r");
00256 
00257 
00258         /* compute which knots (span) we're going to interpolate */
00259 
00260 
00261         x = alpha * nspans;
00262         span = (int)x;
00263         if (span >= nspans) span = nspans - 1;
00264         x -= span;
00265 
00266         /* compute point (alpha 0..1) within this span */
00267 
00268         a = (double *)&knots[span*depth];
00269         b = a+depth;
00270         c = b+depth;
00271         d = c+depth;
00272 
00273         rt_dspline4v(r, m, a, b, c, d, depth, x);
00274 
00275 }
00276 
00277 /*
00278  * Local Variables:
00279  * mode: C
00280  * tab-width: 8
00281  * c-basic-offset: 4
00282  * indent-tabs-mode: t
00283  * End:
00284  * ex: shiftwidth=4 tabstop=8
00285  */

Generated on Mon Sep 18 01:24:56 2006 for BRL-CAD by  doxygen 1.4.6