nurb_split.c

Go to the documentation of this file.
00001 /*                    N U R B _ S P L I 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_split.c
00025  *      Subdivide a nurb surface by inserting a multiple knot of
00026  *      of the surface order in a given direction and return the
00027  *      resulting surfaces.
00028  *
00029  * Author-
00030  *      Paul Randal Stay
00031  *
00032  * Source
00033  *      SECAD/VLD Computing Consortium, Bldg 394
00034  *      The US Army Ballistic Research Laboratory
00035  *      Aberdeen Proving Ground, Maryland 21005
00036  */
00037 /*@}*/
00038 
00039 #include "common.h"
00040 
00041 
00042 
00043 #include <stdio.h>
00044 #include "machine.h"
00045 #include "vmath.h"
00046 #include "nmg.h"
00047 #include "raytrace.h"
00048 #include "nurb.h"
00049 
00050 /* Algorithm
00051  *
00052  *      Given a parametric direction (u or v) look at the direction
00053  * knot vector and insert a multiple knot of parametric direction surface
00054  * order.  If internal knot values exist than pick the one closest to the
00055  * middle and add additional knots to split at that value, otherwise
00056  * add multiple knots at the mid point of the knot vector. Use the new
00057  * knot vector to pass to the oslo refinement process and split the surface.
00058  * Separate the surface and return the two resulting surface.
00059  *
00060  *  The original surface is undisturbed by this operation.
00061  */
00062 void
00063 rt_nurb_s_split(struct bu_list *split_hd, const struct face_g_snurb *srf, int dir, struct resource *res)
00064 {
00065         struct knot_vector new_kv;
00066         fastf_t value;
00067         struct oslo_mat * oslo;
00068         int i;
00069         int k_index = 0;
00070         struct face_g_snurb * srf1, * srf2;
00071 
00072         NMG_CK_SNURB(srf);
00073 
00074         if ( dir == RT_NURB_SPLIT_ROW )
00075         {
00076                 value = srf->u.knots[(srf->u.k_size -1)/2];
00077 
00078                 for( i = 0; i < srf->u.k_size; i++)
00079                         if( value == srf->u.knots[i] )
00080                         {
00081                                 k_index = i;
00082                                 break;
00083                         }
00084                 if ( k_index == 0)
00085                 {
00086                         value = ( value +
00087                                 srf->u.knots[ srf->u.k_size -1])
00088                                 /2.0;
00089                         k_index = srf->order[0];
00090                 }
00091 
00092                 rt_nurb_kvmult( &new_kv, &srf->u, srf->order[0], value, res);
00093 
00094                 oslo = ( struct oslo_mat *)
00095                         rt_nurb_calc_oslo( srf->order[RT_NURB_SPLIT_ROW], &srf->u, &new_kv, res);
00096 
00097                 GET_SNURB( srf1 );
00098                 srf1->order[0]  = srf->order[0];
00099                 srf1->order[1]  = srf->order[1];
00100                 srf1->dir = RT_NURB_SPLIT_ROW;
00101                 rt_nurb_kvextract(&srf1->u, &new_kv, 0, k_index + srf1->order[0], res);
00102                 rt_nurb_kvcopy(&srf1->v, &srf->v, res);
00103 
00104                 srf1->pt_type = srf->pt_type;
00105                 srf1->s_size[0] = srf1->v.k_size -
00106                         srf1->order[1];
00107                 srf1->s_size[1] = srf1->u.k_size -
00108                         srf1->order[0];
00109 
00110                 srf1->ctl_points = (fastf_t *)
00111                         bu_malloc( sizeof(fastf_t) * srf1->s_size[0] *
00112                                 srf1->s_size[1] *
00113                                 RT_NURB_EXTRACT_COORDS( srf1->pt_type),
00114                                 "rt_nurb_s_split: srf1 row mesh control points");
00115 
00116                 GET_SNURB( srf2 );
00117                 srf2->order[0]  = srf->order[0];
00118                 srf2->order[1]  = srf->order[1];
00119                 srf2->dir = RT_NURB_SPLIT_ROW;
00120                 rt_nurb_kvextract(&srf2->u, &new_kv, k_index, new_kv.k_size, res);
00121                 rt_nurb_kvcopy(&srf2->v, &srf->v, res);
00122 
00123                 srf2->pt_type = srf->pt_type;
00124                 srf2->s_size[0] = srf2->v.k_size -
00125                         srf2->order[1];
00126                 srf2->s_size[1] = srf2->u.k_size -
00127                         srf2->order[0];
00128 
00129                 srf2->ctl_points = (fastf_t *)
00130                         bu_malloc( sizeof(fastf_t) * srf2->s_size[0] *
00131                                 srf2->s_size[1] *
00132                                 RT_NURB_EXTRACT_COORDS( srf2->pt_type),
00133                                 "rt_nurb_s_split: srf2 row mesh control points");
00134 
00135                 for( i = 0; i < srf->s_size[0]; i++)
00136                 {
00137                         fastf_t * old_mesh_ptr;
00138                         fastf_t * new_mesh_ptr;
00139 
00140                         old_mesh_ptr = &srf->ctl_points[
00141                                 i * srf->s_size[1] *
00142                                 RT_NURB_EXTRACT_COORDS( srf->pt_type)];
00143                         new_mesh_ptr = &srf1->ctl_points[
00144                                 i * srf1->s_size[1] *
00145                                 RT_NURB_EXTRACT_COORDS( srf1->pt_type)];
00146                         rt_nurb_map_oslo( oslo, old_mesh_ptr, new_mesh_ptr,
00147                                 RT_NURB_EXTRACT_COORDS( srf->pt_type ),
00148                                 RT_NURB_EXTRACT_COORDS( srf1->pt_type ),
00149                                 0, k_index, srf1->pt_type);
00150                         new_mesh_ptr = &srf2->ctl_points[
00151                                 i * srf2->s_size[1] *
00152                                 RT_NURB_EXTRACT_COORDS( srf2->pt_type)];
00153                         rt_nurb_map_oslo( oslo, old_mesh_ptr, new_mesh_ptr,
00154                                 RT_NURB_EXTRACT_COORDS( srf->pt_type ),
00155                                 RT_NURB_EXTRACT_COORDS( srf2->pt_type ),
00156                                 k_index, new_kv.k_size - srf2->order[0],
00157                                 srf2->pt_type);
00158                 }
00159         }
00160         else
00161         {
00162                 value = srf->v.knots[(srf->v.k_size -1)/2];
00163 
00164                 for( i = 0; i < srf->v.k_size; i++)
00165                         if( value == srf->v.knots[i] )
00166                         {
00167                                 k_index = i;
00168                                 break;
00169                         }
00170                 if ( k_index == 0)
00171                 {
00172                         value = ( value +
00173                                 srf->v.knots[ srf->v.k_size -1])
00174                                 /2.0;
00175                         k_index = srf->order[1];
00176                 }
00177 
00178                 rt_nurb_kvmult(&new_kv, &srf->v, srf->order[RT_NURB_SPLIT_COL], value, res);
00179 
00180                 oslo = ( struct oslo_mat *)
00181                         rt_nurb_calc_oslo( srf->order[RT_NURB_SPLIT_COL], &srf->v, &new_kv, res);
00182 
00183                 GET_SNURB( srf1 );
00184                 srf1->order[0]  = srf->order[0];
00185                 srf1->order[1]  = srf->order[1];
00186                 srf1->dir = RT_NURB_SPLIT_COL;
00187                 rt_nurb_kvextract(&srf1->v, &new_kv, 0, k_index + srf1->order[RT_NURB_SPLIT_COL], res);
00188                 rt_nurb_kvcopy(&srf1->u, &srf->u, res);
00189 
00190                 srf1->pt_type = srf->pt_type;
00191                 srf1->s_size[0] = srf1->v.k_size -
00192                         srf1->order[1];
00193                 srf1->s_size[1] = srf1->u.k_size -
00194                         srf1->order[0];
00195 
00196                 srf1->ctl_points = (fastf_t *)
00197                         bu_malloc( sizeof(fastf_t) * srf1->s_size[0] *
00198                                 srf1->s_size[1] *
00199                                 RT_NURB_EXTRACT_COORDS( srf1->pt_type),
00200                                 "rt_nurb_s_split: srf1 col mesh control points");
00201 
00202                 GET_SNURB( srf2 );
00203                 srf2->order[0]  = srf->order[0];
00204                 srf2->order[1]  = srf->order[1];
00205                 srf2->dir = RT_NURB_SPLIT_COL;
00206                 rt_nurb_kvextract(&srf2->v, &new_kv, k_index, new_kv.k_size, res);
00207                 rt_nurb_kvcopy(&srf2->u, &srf->u, res);
00208 
00209                 srf2->pt_type = srf->pt_type;
00210                 srf2->s_size[0] = srf2->v.k_size -
00211                         srf2->order[1];
00212                 srf2->s_size[1] = srf2->u.k_size -
00213                         srf2->order[0];
00214 
00215                 srf2->ctl_points = (fastf_t *)
00216                         bu_malloc( sizeof(fastf_t) * srf2->s_size[0] *
00217                                 srf2->s_size[1] *
00218                                 RT_NURB_EXTRACT_COORDS( srf2->pt_type),
00219                                 "rt_nurb_s_split: srf2 col mesh control points");
00220 
00221                 for( i = 0; i < srf->s_size[1]; i++)
00222                 {
00223                         fastf_t * old_mesh_ptr;
00224                         fastf_t * new_mesh_ptr;
00225 
00226                         old_mesh_ptr = &srf->ctl_points[
00227                                 i * RT_NURB_EXTRACT_COORDS( srf->pt_type)];
00228                         new_mesh_ptr = &srf1->ctl_points[
00229                                 i * RT_NURB_EXTRACT_COORDS( srf1->pt_type)];
00230                         rt_nurb_map_oslo( oslo, old_mesh_ptr, new_mesh_ptr,
00231                                 srf->s_size[1] *
00232                                 RT_NURB_EXTRACT_COORDS( srf->pt_type ),
00233                                 srf1->s_size[1] *
00234                                 RT_NURB_EXTRACT_COORDS( srf1->pt_type ),
00235                                 0, k_index, srf1->pt_type);
00236                         new_mesh_ptr = &srf2->ctl_points[
00237                                 i * RT_NURB_EXTRACT_COORDS( srf2->pt_type)];
00238                         rt_nurb_map_oslo( oslo, old_mesh_ptr, new_mesh_ptr,
00239                                 srf->s_size[1] *
00240                                 RT_NURB_EXTRACT_COORDS( srf->pt_type ),
00241                                 srf2->s_size[1] *
00242                                 RT_NURB_EXTRACT_COORDS( srf2->pt_type ),
00243                                 k_index, new_kv.k_size - srf2->order[1],
00244                                 srf2->pt_type);
00245                 }
00246         }
00247 
00248         /* Arrangement will be:  head, srf1, srf2 */
00249         BU_LIST_APPEND( split_hd, &srf2->l );
00250         BU_LIST_APPEND( split_hd, &srf1->l );
00251 
00252         rt_nurb_free_oslo(oslo, res);
00253         bu_free( (char *)new_kv.knots, "rt_nurb_s_split: new kv knots");
00254 
00255 }
00256 
00257 /*
00258  *                      R T _ N U R B _ C _ S P L I T
00259  *
00260  * Split a NURB curve by inserting a multiple knot and return
00261  * the result of the two curves.
00262  *
00263  * Algorithm
00264  *
00265  * Insert a multiple knot of the curve
00266  * order.  If internal knot values exist than pick the one closest to the
00267  * middle and add additional knots to split at that value, otherwise
00268  * add multiple knots at the mid point of the knot vector. Use the new
00269  * knot vector to pass to the oslo refinement process and split the curve.
00270  * Separate the curve and return the two resulting curves.
00271  *
00272  *  The original curve is undisturbed by this operation.
00273  */
00274 void
00275 rt_nurb_c_split(struct bu_list *split_hd, const struct edge_g_cnurb *crv)
00276 {
00277         struct knot_vector new_kv;
00278         fastf_t value;
00279         struct oslo_mat * oslo;
00280         int i;
00281         int k_index = 0;
00282         struct edge_g_cnurb * crv1, * crv2;
00283         int coords;
00284 
00285         NMG_CK_CNURB(crv);
00286 
00287         coords = RT_NURB_EXTRACT_COORDS( crv->pt_type ),
00288 
00289         value = crv->k.knots[(crv->k.k_size -1)/2];
00290 
00291         for( i = 0; i < crv->k.k_size; i++)
00292                 if( value == crv->k.knots[i] )
00293                 {
00294                         k_index = i;
00295                         break;
00296                 }
00297         if ( k_index == 0)
00298         {
00299                 value = ( value +
00300                         crv->k.knots[ crv->k.k_size -1])
00301                         /2.0;
00302                 k_index = crv->order;
00303         }
00304 
00305         rt_nurb_kvmult(&new_kv, &crv->k, crv->order, value, (struct resource *)NULL);
00306 
00307         oslo = ( struct oslo_mat *)
00308                 rt_nurb_calc_oslo( crv->order, &crv->k, &new_kv, (struct resource *)NULL);
00309 
00310         GET_CNURB( crv1 );
00311         crv1->order  = crv->order;
00312         rt_nurb_kvextract(&crv1->k, &new_kv, 0, k_index + crv->order, (struct resource *)NULL);
00313         crv1->pt_type = crv->pt_type;
00314         crv1->c_size = crv1->k.k_size - crv1->order;
00315         crv1->ctl_points = (fastf_t *)
00316                 bu_malloc( sizeof(fastf_t) * crv1->c_size *
00317                         RT_NURB_EXTRACT_COORDS( crv1->pt_type),
00318                         "rt_nurb_c_split: crv1 control points");
00319 
00320         GET_CNURB( crv2 );
00321         crv2->order  = crv->order;
00322         rt_nurb_kvextract(&crv2->k, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
00323         crv2->pt_type = crv->pt_type;
00324         crv2->c_size = crv2->k.k_size - crv2->order;
00325         crv2->ctl_points = (fastf_t *)
00326                 bu_malloc( sizeof(fastf_t) * crv2->c_size *
00327                         RT_NURB_EXTRACT_COORDS( crv2->pt_type),
00328                         "rt_nurb_s_split: crv2 mesh control points");
00329 
00330         rt_nurb_map_oslo( oslo, crv->ctl_points, crv1->ctl_points,
00331                 coords, coords, 0, k_index, crv->pt_type );
00332 
00333         rt_nurb_map_oslo( oslo, crv->ctl_points, crv2->ctl_points,
00334                 coords, coords, k_index, new_kv.k_size - crv2->order,
00335                 crv2->pt_type );
00336 
00337         rt_nurb_free_oslo( oslo, (struct resource *)NULL );
00338 
00339         bu_free( (char *) new_kv.knots, "rt_nurb_c_split; new_kv.knots" );
00340 
00341         /* Arrangement will be:  head, crv1, crv2 */
00342         BU_LIST_APPEND( split_hd, &crv2->l );
00343         BU_LIST_APPEND( split_hd, &crv1->l );
00344 }
00345 
00346 /*
00347  * Local Variables:
00348  * mode: C
00349  * tab-width: 8
00350  * c-basic-offset: 4
00351  * indent-tabs-mode: t
00352  * End:
00353  * ex: shiftwidth=4 tabstop=8
00354  */

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