nurb_bezier.c

Go to the documentation of this file.
00001 /*                   N U R B _ B E Z I E R . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1991-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_bezier.c
00025  * Convert a NURB surface or curve into Bezier form, with no internal knots.
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 
00044 #include "machine.h"
00045 #include "vmath.h"
00046 #include "nmg.h"
00047 #include "raytrace.h"
00048 #include "nurb.h"
00049 
00050 /*
00051  *                      R T _ N U R B _ B E Z I E R
00052  *
00053  *  Given a single snurb, if it is in Bezier form,
00054  *  duplicate the snurb, and enqueue it on the bezier_hd list.
00055  *  If the original snurb is NOT in Bezier form,
00056  *  subdivide it a set of snurbs which are,
00057  *  each of which are enqueued on the bezier_hd list.
00058  *
00059  *  In either case, the original surface remains untouched.
00060  *
00061  *  Returns -
00062  *      0       Surface splitting was done.
00063  *      1       Original surface was Bezier, only a copy was done.
00064  */
00065 int
00066 rt_nurb_bezier(struct bu_list *bezier_hd, const struct face_g_snurb *orig_surf, struct resource *res)
00067 {
00068         struct face_g_snurb     *s;
00069         int             dir;
00070         struct bu_list  todo;
00071 
00072         NMG_CK_SNURB(orig_surf);
00073 
00074         if( (dir = rt_bez_check( orig_surf )) == -1)  {
00075                 s = rt_nurb_scopy( orig_surf, res );
00076                 BU_LIST_APPEND( bezier_hd, &s->l );
00077                 return 1;       /* Was already Bezier, nothing done */
00078         }
00079 
00080         BU_LIST_INIT( &todo );
00081         rt_nurb_s_split( &todo, orig_surf, dir, res );
00082 
00083         while( BU_LIST_WHILE( s, face_g_snurb, &todo ) )  {
00084                 if( (dir = rt_bez_check(s)) == -1)  {
00085                         /* This snurb is now a Bezier */
00086                         BU_LIST_DEQUEUE( &s->l );
00087                         BU_LIST_APPEND( bezier_hd, &s->l );
00088                 } else {
00089                         /* Split, and keep going */
00090                         BU_LIST_DEQUEUE( &s->l );
00091                         rt_nurb_s_split( &todo, s, dir, res );
00092                         rt_nurb_free_snurb(s, res);
00093                 }
00094         }
00095         return 0;               /* Bezier snurbs on bezier_hd list */
00096 }
00097 
00098 int
00099 rt_bez_check(const struct face_g_snurb *srf)
00100 {
00101         NMG_CK_SNURB(srf);
00102 
00103         if( srf->u.k_size > (2.0 * srf->order[0]))
00104                 return 0;
00105         if( srf->v.k_size > (2.0 * srf->order[1]))
00106                 return 1;
00107 
00108         return -1;
00109 }
00110 
00111 /*              N U R B _ C R V _ I S _ B E Z I E R
00112  *
00113  * Check if a NURB curve is in Bezier form.
00114  *
00115  * returns:
00116  *      1 - curve is Bezier
00117  *      0 - curve is not Bezier
00118  */
00119 
00120 int
00121 nurb_crv_is_bezier(const struct edge_g_cnurb *crv)
00122 {
00123         int i;
00124         fastf_t knot_min, knot_max;
00125         int bezier=1;
00126 
00127         knot_min = crv->k.knots[0];
00128         knot_max = crv->k.knots[crv->k.k_size-1];
00129 
00130         for( i=1 ; i<crv->k.k_size-1 ; i++ )
00131         {
00132                 if( crv->k.knots[i] != knot_min && crv->k.knots[i] != knot_max )
00133                 {
00134                         bezier = 0;
00135                         break;
00136                 }
00137         }
00138 
00139         return( bezier );
00140 }
00141 
00142 /*      N U R B _ C _ T O _ B E Z I E R
00143  *
00144  * Split NURB curve into list of Bezier curves.
00145  *
00146  * If curve is already Bezier, return NULL
00147  */
00148 
00149 void
00150 nurb_c_to_bezier(struct bu_list *clist, struct edge_g_cnurb *crv)
00151 {
00152         fastf_t knot_min, knot_max;
00153         int i;
00154         struct edge_g_cnurb *crv1, *crv_copy;
00155         int done;
00156 
00157         /* make a copy of original curve */
00158         crv_copy = rt_nurb_crv_copy( crv );
00159 
00160         /* split curve at each knot value */
00161         done = 0;
00162         while( !done )
00163         {
00164                 fastf_t split;
00165 
00166                 knot_min = crv_copy->k.knots[0];
00167                 knot_max = crv_copy->k.knots[crv_copy->k.k_size-1];
00168 
00169                 split = MAX_FASTF;
00170                 for( i=1 ; i<crv_copy->k.k_size-1 ; i++ )
00171                 {
00172                         if( crv_copy->k.knots[i] != knot_min && crv_copy->k.knots[i] != knot_max )
00173                         {
00174                                 split = crv_copy->k.knots[i];
00175                                 break;
00176                         }
00177                 }
00178 
00179                 if( split == MAX_FASTF )
00180                 {
00181                         done = 1;
00182                         BU_LIST_APPEND( clist, &crv_copy->l );
00183                         break;
00184                 }
00185 
00186                 crv1 = rt_nurb_c_xsplit( crv_copy, split );
00187 
00188                 rt_nurb_free_cnurb( crv_copy );
00189                 crv_copy = BU_LIST_PNEXT( edge_g_cnurb, &crv1->l );
00190                 BU_LIST_DEQUEUE( &crv_copy->l );
00191 
00192                 BU_LIST_APPEND( clist, &crv1->l );
00193         }
00194 }
00195 
00196 /*
00197  * Local Variables:
00198  * mode: C
00199  * tab-width: 8
00200  * c-basic-offset: 4
00201  * indent-tabs-mode: t
00202  * End:
00203  * ex: shiftwidth=4 tabstop=8
00204  */

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