nurb_knot.c

Go to the documentation of this file.
00001 /*                     N U R B _ K N O T . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1990-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_knot.c
00025  * Various knot vector routines.
00026  *
00027  * Author -
00028  *     Paul R. Stay
00029  *
00030  * Source -
00031  *     SECAD/VLD Computing Consortium, Bldg 394
00032  *     The U.S. Army Ballistic Research Laboratory
00033  *     Aberdeen Proving Ground, Maryland 21005
00034  *
00035  */
00036 /*@}*/
00037 
00038 #include "common.h"
00039 
00040 
00041 
00042 #include <stdio.h>
00043 #include <math.h>
00044 #include "machine.h"
00045 #include "vmath.h"
00046 #include "raytrace.h"
00047 #include "nurb.h"
00048 
00049 /* rt_nurb_kvknot()
00050  * Generate a open knot vector with n=order knots at the beginning of
00051  * the sequence and n knots at the end of the sequence with a lower,
00052  * and an upper value and num knots in between
00053  */
00054 
00055 void
00056 rt_nurb_kvknot(register struct knot_vector *new_knots, int order, fastf_t lower, fastf_t upper, int num, struct resource *res)
00057 {
00058         register int    i;
00059         int     total;
00060         fastf_t knot_step;
00061 
00062         total = order * 2 + num;
00063 
00064         knot_step = (upper - lower) / ( num + 1 );
00065 
00066         new_knots->k_size = total;
00067 
00068         new_knots->knots = (fastf_t * ) bu_malloc ( sizeof( fastf_t) * total,
00069                     "rt_nurb_kvknot: new knots values");
00070 
00071         for ( i = 0; i < order; i++)
00072                 new_knots->knots[i] = lower;
00073 
00074         for ( i = order; i <= (num + order - 1); i++)
00075                 new_knots->knots[i] = new_knots->knots[i-1] + knot_step;
00076 
00077         for ( i = ( num + order ) ; i < total; i++)
00078                 new_knots->knots[i] = upper;
00079 }
00080 
00081 
00082 /* rt_nurb_kvmult()
00083  *      Construct a new knot vector which is the same as the passed in
00084  * knot vector except it has multiplicity of num of val. It checks to see if
00085  * val already is a multiple knot.
00086  */
00087 void
00088 rt_nurb_kvmult(struct knot_vector *new_kv, const struct knot_vector *kv, int num, register fastf_t val, struct resource *res)
00089 {
00090         int     n;
00091         register int    i;
00092         struct knot_vector check;
00093 
00094         n = rt_nurb_kvcheck( val, kv );
00095 
00096         check.k_size = num - n;
00097         if( check.k_size <= 0 )  {
00098                 bu_log("rt_nurb_kvmult(new_kv=x%x, kv=x%x, num=%d, val=%g)\n",
00099                         new_kv, kv, num, val);
00100                 rt_nurb_pr_kv(kv);
00101                 rt_bomb("rt_nurb_kvmult\n");
00102         }
00103 
00104         check.knots = (fastf_t * ) bu_malloc( sizeof(fastf_t) * check.k_size,
00105                     "rt_nurb_kvmult: check knots");
00106 
00107         for ( i = 0; i < num - n; i++)
00108                 check.knots[i] = val;
00109 
00110         rt_nurb_kvmerge( new_kv, &check, kv, res);
00111 
00112         /* free up old knot values */
00113         bu_free((char *)check.knots, "rt_nurb_kvmult:check knots");
00114 }
00115 
00116 
00117 /* rt_nurb_kvgen( )
00118  *      Generate a knot vector with num knots from lower value to
00119  *      the upper  value.
00120  */
00121 
00122 void
00123 rt_nurb_kvgen(register struct knot_vector *kv, fastf_t lower, fastf_t upper, int num, struct resource *res)
00124 {
00125         register int    i;
00126         register fastf_t inc;
00127 
00128         inc = (upper - lower) / ( num + 1 );
00129 
00130         kv->k_size = num;
00131 
00132         kv->knots = (fastf_t * ) bu_malloc ( sizeof( fastf_t) * num,
00133                     "rt_nurb_kvgen: kv knots");
00134 
00135         for ( i = 1; i <= num; i++)
00136                 kv->knots[i-1] = lower + i * inc;
00137 }
00138 
00139 
00140 /* rt_nurb_kvmerge()
00141  *      Merge two knot vectors together and return the new resulting
00142  *      knot vector.
00143  */
00144 
00145 void
00146 rt_nurb_kvmerge(struct knot_vector *new_knots, const struct knot_vector *kv1, const struct knot_vector *kv2, struct resource *res)
00147 {
00148         int     kv1_ptr = 0;
00149         int     kv2_ptr = 0;
00150         int     new_ptr;
00151 
00152         new_knots->k_size = kv1->k_size + kv2->k_size;
00153 
00154         new_knots->knots = (fastf_t * ) bu_malloc(
00155                     sizeof (fastf_t) * new_knots->k_size,
00156                     "rt_nurb_kvmerge: new knot values");
00157 
00158         for ( new_ptr = 0; new_ptr < new_knots->k_size; new_ptr++) {
00159                 if ( kv1_ptr >= kv1->k_size )
00160                         new_knots->knots[new_ptr] = kv2->knots[kv2_ptr++];
00161                 else if ( kv2_ptr >= kv2->k_size )
00162                         new_knots->knots[new_ptr] = kv1->knots[kv1_ptr++];
00163                 else if ( kv1->knots[kv1_ptr] < kv2->knots[kv2_ptr])
00164                         new_knots->knots[new_ptr] = kv1->knots[kv1_ptr++];
00165                 else
00166                         new_knots->knots[new_ptr] = kv2->knots[kv2_ptr++];
00167         }
00168 }
00169 
00170 
00171 /* rt_nurb_kvcheck()
00172  *      Checks to see if the knot (val) exists in the Knot Vector and
00173  *      returns its multiplicity.
00174  */
00175 
00176 int
00177 rt_nurb_kvcheck(fastf_t val, register const struct knot_vector *kv)
00178 {
00179         register int    kv_num = 0;
00180         register int    i;
00181 
00182         for ( i = 0; i < kv->k_size; i++) {
00183                 if ( val == kv->knots[i] )
00184                         kv_num++;
00185         }
00186 
00187         return kv_num;
00188 }
00189 
00190 
00191 /* rt_nurb_kvextract()
00192  *      Extract the portion of the knot vector from kv->knots[lower] to
00193  *      kv->knots[upper]
00194  */
00195 
00196 void
00197 rt_nurb_kvextract(struct knot_vector *new_kv, register const struct knot_vector *kv, int lower, int upper, struct resource *res)
00198 {
00199         register int    i;
00200         register fastf_t *ptr;
00201 
00202         new_kv->knots = (fastf_t * ) bu_malloc (
00203                     sizeof (fastf_t) * (upper - lower),
00204                     "spl_kvextract: nkw kv values" );
00205 
00206         new_kv->k_size = upper - lower;
00207         ptr = new_kv->knots;
00208 
00209         for ( i = lower; i < upper; i++)
00210                 *ptr++ = kv->knots[i];
00211 }
00212 
00213 
00214 /* rt_nurb_kvcopy()
00215  *      Generic copy the knot vector and pass a new one in.
00216  */
00217 
00218 void
00219 rt_nurb_kvcopy(struct knot_vector *new_kv, register const struct knot_vector *old_kv, struct resource *res)
00220 {
00221         register int    i;
00222 
00223         new_kv->k_size = old_kv->k_size;
00224 
00225         new_kv->knots = (fastf_t * ) bu_malloc( sizeof( fastf_t) *
00226                     new_kv->k_size, "spl_kvcopy: new knot values");
00227 
00228         for ( i = 0; i < new_kv->k_size; i++)
00229                 new_kv->knots[i] = old_kv->knots[i];
00230 }
00231 
00232 
00233 /* rt_nurb_kvnorm()
00234  *      Normalize the knot vector so its values are from zero to one.
00235  */
00236 
00237 /* XXX Need to check to see if the lower value is zero */
00238 void
00239 rt_nurb_kvnorm(register struct knot_vector *kv)
00240 {
00241         register fastf_t upper;
00242         register int    i;
00243 
00244         upper = kv->knots[kv->k_size - 1];
00245         if( NEAR_ZERO( upper, SMALL ) )
00246                 upper = 0;
00247         else
00248                 upper = 1 / upper;
00249 
00250         for ( i = 0; i < kv->k_size; i++)
00251                 kv->knots[i] *= upper;
00252 }
00253 
00254 
00255 /* knot_index()
00256  *      Calculates and returns the index of the value for the knot vector
00257  *
00258  * XXX It is hard to know what tolerance to use here for the comparisons.
00259  */
00260 
00261 int
00262 rt_nurb_knot_index(const struct knot_vector *kv, fastf_t k_value, int order)
00263 {
00264         int     i;
00265         fastf_t  knt;
00266         int     k_index;
00267 
00268         if ( k_value < ( knt = *(kv->knots + order - 1))) {
00269                 if (fabs( k_value - knt) < 0.0001) {
00270                         k_value = knt;
00271                 } else
00272                         return - 1;
00273         }
00274 
00275         if ( k_value > ( knt = *(kv->knots + kv->k_size - order + 1)) ) {
00276                 if (fabs( k_value - knt) < 0.0001) {
00277                         k_value = knt;
00278                 } else
00279                         return - 1;
00280         }
00281 
00282         if ( k_value == kv->knots[ kv->k_size - order + 1] )
00283                 k_index = kv->k_size - order - 1;
00284         else if ( k_value == kv->knots[ order - 1] )
00285                 k_index = order - 1;
00286         else
00287          {
00288                 k_index = 0;
00289                 for ( i = 0; i < kv->k_size - 1; i++)
00290                         if ( kv->knots[i] < k_value && k_value <= kv->knots[i+1] )
00291                                 k_index = i;
00292 
00293         }
00294 
00295         return k_index;
00296 }
00297 
00298 
00299 /* rt_nurb_gen_knot_vector()
00300  * Generate a open knot vector with n=order knots at the beginning of
00301  * the sequence and n knots at the end of the sequence.
00302  */
00303 
00304 void
00305 rt_nurb_gen_knot_vector(register struct knot_vector *new_knots, int order, fastf_t lower, fastf_t upper, struct resource *res)
00306 {
00307     register int i;
00308     int total;
00309 
00310     total = order * 2;
00311 
00312     new_knots->k_size = total;
00313 
00314     new_knots->knots = (fastf_t *) bu_malloc ( sizeof( fastf_t) * total,
00315                 "rt_nurb_gen_knot_vector: new knots values");
00316 
00317     for ( i = 0; i < order; i++)
00318         new_knots->knots[i] = lower;
00319 
00320     for ( i = order; i < total; i++)
00321         new_knots->knots[i] = upper;
00322 }
00323 
00324 /*
00325  * Local Variables:
00326  * mode: C
00327  * tab-width: 8
00328  * c-basic-offset: 4
00329  * indent-tabs-mode: t
00330  * End:
00331  * ex: shiftwidth=4 tabstop=8
00332  */

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