nurb_diff.c

Go to the documentation of this file.
00001 /*                     N U R B _ D I F F . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1986-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_diff.c
00025  *      Differentiate a Non Uniform Rational B-Spline (NURB) Surface.
00026  *  Author -
00027  *      Paul Randal Stay
00028  *
00029  *  Source -
00030  *      SECAD/VLD Computing Consortium, Bldg 394
00031  *      The U.S. Army Ballistic Research Laboratory
00032  *      Aberdeen Proving Ground, Maryland 21005
00033  *
00034  */
00035 /*@}*/
00036 
00037 #include "common.h"
00038 
00039 
00040 
00041 #include <stdio.h>
00042 #include "machine.h"
00043 #include "vmath.h"
00044 #include "nmg.h"
00045 #include "raytrace.h"
00046 #include "nurb.h"
00047 
00048 /* Given a NURB surface and a direction, differentiate the surface
00049  * and return a new surface which is the derivative of the original
00050  * surface.
00051  *
00052  * The algorithm is found in the following reference:
00053  *      Carl De Boor, "A Practical Guide To Splines", page 139
00054  *
00055  * The algorithm deals mainly with the new control mesh, but the new knot
00056  * vector is a subset of the original. (subtract a knot from each of
00057  * the ends).
00058  *
00059  * Arguments to rt_nurb_s_diff() --
00060  *      srf - NURB surface
00061  *      dir - parametric direction of the split.
00062  */
00063 
00064 struct face_g_snurb *
00065 rt_nurb_s_diff(const struct face_g_snurb *srf, int dir)
00066 {
00067         struct face_g_snurb *nsrf;
00068         int     i;
00069 
00070         NMG_CK_SNURB(srf);
00071 
00072         if (dir == RT_NURB_SPLIT_ROW) {
00073                 nsrf = (struct face_g_snurb *)
00074                 rt_nurb_new_snurb( srf->order[0] - 1, srf->order[1],
00075                     srf->u.k_size - 2, srf->v.k_size,
00076                     srf->s_size[0], srf->s_size[1] - 1,
00077                     srf->pt_type, (struct resource *)NULL );
00078 
00079                 for ( i = 0; i < srf->s_size[0]; i++) {
00080                         fastf_t * old_points, *new_points;
00081 
00082                         old_points = srf->ctl_points +
00083                             i * RT_NURB_EXTRACT_COORDS(srf->pt_type)
00084                         *srf->s_size[1];
00085 
00086                         new_points = nsrf->ctl_points +
00087                             i * RT_NURB_EXTRACT_COORDS(nsrf->pt_type)
00088                         *nsrf->s_size[1];
00089 
00090                         rt_nurb_mesh_diff( srf->order[0],
00091                             old_points, new_points, srf->u.knots,
00092                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
00093                             RT_NURB_EXTRACT_COORDS(nsrf->pt_type),
00094                             srf->s_size[1], srf->pt_type);
00095                 }
00096 
00097                 for (i = 1; i < srf->u.k_size - 1; i++)
00098                         nsrf->u.knots[i - 1] = srf->u.knots[i];
00099 
00100                 for (i = 0; i < srf->v.k_size; i++)
00101                         nsrf->v.knots[i] = srf->v.knots[i];
00102         } else   {
00103                 nsrf = (struct face_g_snurb *) rt_nurb_new_snurb(
00104                     srf->order[0], srf->order[1] - 1,
00105                     srf->u.k_size, srf->v.k_size - 2,
00106                     srf->s_size[0] - 1, srf->s_size[1],
00107                     srf->pt_type, (struct resource *)NULL );
00108 
00109                 for ( i = 0; i < srf->s_size[1]; i++) {
00110                         fastf_t * old_points, *new_points;
00111 
00112                         old_points = srf->ctl_points +
00113                             i * RT_NURB_EXTRACT_COORDS(srf->pt_type);
00114 
00115                         new_points = nsrf->ctl_points +
00116                             i * RT_NURB_EXTRACT_COORDS(nsrf->pt_type);
00117 
00118                         rt_nurb_mesh_diff( srf->order[1],
00119                             old_points, new_points, srf->v.knots,
00120                             RT_NURB_EXTRACT_COORDS(srf->pt_type) *
00121                             srf->s_size[1],
00122                             RT_NURB_EXTRACT_COORDS(nsrf->pt_type) *
00123                             nsrf->s_size[1],
00124                             srf->s_size[0], srf->pt_type);
00125                 }
00126 
00127                 for (i = 0; i < srf->u.k_size; i++)
00128                         nsrf->u.knots[i] = srf->u.knots[i];
00129 
00130                 for (i = 1; i < srf->v.k_size - 1; i++)
00131                         nsrf->v.knots[i-1] = srf->v.knots[i];
00132         }
00133         return nsrf;
00134 }
00135 
00136 /* Do the same thing for a curve. */
00137 
00138 struct edge_g_cnurb *
00139 rt_nurb_c_diff(const struct edge_g_cnurb *crv)
00140 {
00141 
00142         struct edge_g_cnurb *ncrv;
00143         fastf_t * opts, *npts;
00144         int     i;
00145 
00146         NMG_CK_CNURB(crv);
00147 
00148         ncrv = (struct edge_g_cnurb *) rt_nurb_new_cnurb( crv->order - 1,
00149             crv->k.k_size - 2, crv->c_size - 1,
00150             crv->pt_type);
00151 
00152         opts = (fastf_t * ) crv->ctl_points;
00153         npts = (fastf_t * ) ncrv->ctl_points;
00154 
00155         rt_nurb_mesh_diff( crv->order, opts, npts, crv->k.knots,
00156             RT_NURB_EXTRACT_COORDS( crv->pt_type),
00157             RT_NURB_EXTRACT_COORDS( ncrv->pt_type),
00158             crv->c_size, crv->pt_type );
00159 
00160         for ( i = 1; i < crv->k.k_size - 1; i++)
00161                 ncrv->k.knots[ i - 1] = crv->k.knots[i];
00162 
00163         return ncrv;
00164 
00165 }
00166 
00167 void
00168 rt_nurb_mesh_diff(int order, const fastf_t *o_pts, fastf_t *n_pts, const fastf_t *knots, int o_stride, int n_stride, int o_size, int pt_type)
00169 {
00170         int     i, k;
00171         int     coords;
00172         fastf_t denom;
00173 
00174         coords = RT_NURB_EXTRACT_COORDS(pt_type);
00175 
00176         for ( i = 1; i < o_size; i++) {
00177                 denom = knots[ i + order - 1] - knots[i];
00178                 for (k = 0; k < coords; k++) {
00179                         if (denom == 0.0)
00180                                 n_pts[k] = 0.0;
00181                         else
00182                                 n_pts[k] = (order - 1) *
00183                                     (o_pts[k+o_stride] - o_pts[k]) /
00184                                     denom;
00185                 }
00186                 n_pts += n_stride;
00187                 o_pts += o_stride;
00188         }
00189 }
00190 
00191 
00192 /*
00193  * Local Variables:
00194  * mode: C
00195  * tab-width: 8
00196  * c-basic-offset: 4
00197  * indent-tabs-mode: t
00198  * End:
00199  * ex: shiftwidth=4 tabstop=8
00200  */

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