nurb_interp.c

Go to the documentation of this file.
00001 /*                   N U R B _ I N T E R P . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1994-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 nurb */
00023 /*@{*/
00024 /** @file nurb_interp.c
00025  * Interpolatopn routines for fitting NURB curves and
00026  * and surfaces to existing data.
00027  *
00028  *
00029  * Author:  Paul R. Stay
00030  *
00031  *  Source -
00032  *      The U. S. Army Research Laboratory
00033  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00034  */
00035 /*@}*/
00036 
00037 #ifndef lint
00038 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/nurb_interp.c,v 14.12 2006/09/16 02:04:25 lbutler Exp $ (ARL)";
00039 #endif
00040 
00041 #include "common.h"
00042 
00043 
00044 
00045 #include <stdio.h>
00046 #include <string.h>
00047 
00048 #include "machine.h"
00049 #include "vmath.h"
00050 #include "raytrace.h"
00051 #include "nurb.h"
00052 
00053 
00054 void
00055 rt_nurb_nodes(fastf_t *nodes, const struct knot_vector *knots, int order)
00056 {
00057         int i, j;
00058         fastf_t sum;
00059 
00060         for( i = 0; i < knots->k_size -order; i++)
00061         {
00062 
00063                 sum = 0.0;
00064 
00065                 for( j = 1; j <= order -1; j++)
00066                 {
00067                         sum += knots->knots[i+j];
00068                 }
00069                 nodes[i] = sum/(order -1);
00070         }
00071 }
00072 
00073 void
00074 rt_nurb_interp_mat(fastf_t *imat, struct knot_vector *knots, fastf_t *nodes, int order, int dim)
00075 {
00076         int i,j;
00077         int ptr;
00078 
00079         ptr = 0;
00080 
00081         for( i = 0; i < dim; i++)
00082         for( j = 0; j < dim; j++)
00083         {
00084                 imat[ptr] = rt_nurb_basis_eval( knots, j, order, nodes[i]);
00085                 ptr++;
00086         }
00087 
00088         imat[ptr-1] = 1.0;
00089 }
00090 
00091 
00092 /*
00093  *                      R T _ N U R B _ C I N T E R P
00094  *
00095  * main routine for interpolation of curves
00096  */
00097 void
00098 rt_nurb_cinterp(struct edge_g_cnurb *crv, int order, const fastf_t *data, int n)
00099 {
00100         fastf_t * interp_mat;
00101         fastf_t * nodes;
00102         fastf_t *local_data;
00103 
00104         /* Create Data memory and fill in curve structs */
00105 
00106         interp_mat = (fastf_t *) bu_malloc( n * n * sizeof(fastf_t),
00107                 "rt_nurb_interp: interp_mat");
00108 
00109         nodes = (fastf_t *) bu_malloc( n * sizeof(fastf_t),"rt_nurb_interp:nodes");
00110         local_data = (fastf_t *)bu_malloc( n * 3 * sizeof(fastf_t), "rt_nurb_interp() local_data[]");
00111 
00112         crv->ctl_points = (fastf_t *) bu_malloc( n * 3 * sizeof(fastf_t),
00113                 "solution");
00114 
00115         crv->order = order;
00116         crv->c_size = n;
00117         crv->pt_type = RT_NURB_MAKE_PT_TYPE( 3, RT_NURB_PT_XYZ, 0);
00118 
00119         /* First set up Curve data structs */
00120         /* For now we will assume that all paramerizations are uniform */
00121 
00122         rt_nurb_kvknot( &crv->k, order, 0.0, 1.0, (n - order), (struct resource *)NULL);
00123 
00124         /* Calculate Nodes at which the data points will be
00125          * evaluated in the curve
00126          */
00127 
00128         rt_nurb_nodes( nodes, &crv->k, order);
00129 
00130         /* use the node values to create the interpolation matrix
00131          * which is a diagonal matrix
00132          */
00133 
00134         rt_nurb_interp_mat( interp_mat, &crv->k, nodes, order, n);
00135 
00136         /* Solve the system of equations to get the control points
00137          * Because rt_nurb_solve needs to modify the data as it works,
00138          * and it wouldn't be polite to trash our caller's data,
00139          * make a local copy.
00140          * This creates the final ctl_points[] array.
00141          */
00142         bcopy( (char *)data, (char *)local_data, n * 3 * sizeof(fastf_t) );
00143         rt_nurb_solve( interp_mat, local_data, crv->ctl_points, n, 3);
00144 
00145         /* Free up node and interp_mat storage */
00146 
00147         bu_free( (char *) interp_mat, "rt_nurb_cinterp: interp_mat");
00148         bu_free( (char *) nodes, "rt_nurb_cinterp: nodes");
00149         bu_free( (char *) local_data, "rt_nurb_cinterp() local_data[]");
00150 
00151         /* All done, The resulting crv now interpolates the data */
00152 }
00153 
00154 /*
00155  *                      R T _ N U R B _ S I N T E R P
00156  *
00157  *  Interpolate the 2-D grid of data values and fit a B-spline surface to it.
00158  *
00159  *  This is done in two steps:
00160  *      1)  Fit a curve to the data in each row.
00161  *      2)  Fit a curve to the control points from step 1 in each column.
00162  *  The result is a mesh of control points which defines the surface.
00163  *
00164  *  Input data is assumed to be a 3-tuple of (X,Y,Z) where Z is the
00165  *  independent variable being interpolated to make the surface.
00166  */
00167 void
00168 rt_nurb_sinterp(struct face_g_snurb *srf, int order, const fastf_t *data, int ymax, int xmax)
00169 
00170 
00171                                 /* data[x,y] */
00172                                 /* nrow = max Y */
00173                                 /* ncol = max X */
00174 {
00175         int     x;
00176         int     y;
00177         struct edge_g_cnurb     *crv;   /* array of cnurbs */
00178         fastf_t         *tmp;
00179         fastf_t         *cpt;   /* surface control point pointer */
00180 
00181         /* Build the resultant surface structure */
00182         srf->order[0] = srf->order[1] = order;
00183         srf->dir = 0;
00184         srf->s_size[0] = xmax;
00185         srf->s_size[1] = ymax;
00186         srf->l.magic = RT_SNURB_MAGIC;
00187         srf->pt_type = RT_NURB_MAKE_PT_TYPE(3,RT_NURB_PT_XYZ,RT_NURB_PT_NONRAT);
00188 
00189         /* the U knot vector replates to the points in a row
00190          * therefore you want to determin how many cols there are
00191          * similar for the V knot vector
00192          */
00193 
00194         rt_nurb_kvknot(&srf->u, order, 0.0, 1.0, ymax - order, (struct resource *)NULL);
00195         rt_nurb_kvknot(&srf->v, order, 0.0, 1.0, xmax - order, (struct resource *)NULL);
00196 
00197         srf->ctl_points = (fastf_t *) bu_malloc(
00198                 sizeof(fastf_t) * xmax * ymax * 3,
00199                 "rt_nurb_sinterp() surface ctl_points[]");
00200         cpt = &srf->ctl_points[0];
00201 
00202 /* _col is X, _row is Y */
00203 #define NVAL(_col,_row) data[((_row)*xmax+(_col))*3]
00204 
00205         crv = (struct edge_g_cnurb *)bu_calloc( sizeof(struct edge_g_cnurb), ymax,
00206                 "rt_nurb_sinterp() crv[]");
00207 
00208         /* Interpolate the data across the rows, fitting a curve to each. */
00209         for( y = 0; y < ymax; y++)  {
00210                 crv[y].l.magic = RT_CNURB_MAGIC;
00211                 /* Build curve from from (0,y) to (xmax-1, y) */
00212                 rt_nurb_cinterp( &crv[y], order, &NVAL(0,y), xmax );
00213         }
00214 #undef NVAL
00215 
00216         tmp = (fastf_t *)bu_malloc( sizeof(fastf_t)*3 * ymax,
00217                 "rt_nurb_sinterp() tmp[]");
00218         for( x = 0; x < xmax; x++)  {
00219                 struct edge_g_cnurb     ncrv;
00220 
00221                 /* copy the curve ctl points into col major format */
00222                 for( y = 0; y < ymax; y++)  {
00223                         VMOVE( &tmp[y*3], &crv[y].ctl_points[x*3] );
00224                 }
00225 
00226                 /* Interpolate the curve interpolates, giving rows of a surface */
00227                 ncrv.l.magic = RT_CNURB_MAGIC;
00228                 rt_nurb_cinterp( &ncrv, order, tmp, ymax);
00229 
00230                 /* Move new curve interpolations into snurb ctl_points[] */
00231                 for( y = 0; y < ymax*3; y++)  {
00232                         *cpt++ = ncrv.ctl_points[y];
00233                 }
00234                 rt_nurb_clean_cnurb( &ncrv );
00235         }
00236         for( y = 0; y < ymax; y++)  {
00237                 rt_nurb_clean_cnurb( &crv[y] );
00238         }
00239         bu_free( (char *)crv, "crv[]");
00240         bu_free( (char *)tmp, "tmp[]");
00241 }
00242 
00243 /*
00244  * Local Variables:
00245  * mode: C
00246  * tab-width: 8
00247  * c-basic-offset: 4
00248  * indent-tabs-mode: t
00249  * End:
00250  * ex: shiftwidth=4 tabstop=8
00251  */

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