g_sketch.c

Go to the documentation of this file.
00001 /*                      G _ S K E T C H . 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 g_  */
00023 
00024 /*@{*/
00025 /** @file g_sketch.c
00026  *      Provide support for 2D sketches.
00027  *
00028  *  Source -
00029  *      SECAD/VLD Computing Consortium, Bldg 394
00030  *      The U. S. Army Ballistic Research Laboratory
00031  *      Aberdeen Proving Ground, Maryland  21005-5066
00032  *
00033  */
00034 /*@}*/
00035 
00036 #ifndef lint
00037 static const char RCSsketch[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_sketch.c,v 14.16 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00038 #endif
00039 
00040 #include "common.h"
00041 
00042 #include <stdlib.h>
00043 #include <stdio.h>
00044 #ifdef HAVE_STRING_H
00045 #  include <string.h>
00046 #else
00047 #  include <strings.h>
00048 #endif
00049 #include <math.h>
00050 #include <ctype.h>
00051 
00052 #include "tcl.h"
00053 #include "machine.h"
00054 #include "vmath.h"
00055 #include "db.h"
00056 #include "nmg.h"
00057 #include "raytrace.h"
00058 #include "nurb.h"
00059 #include "rtgeom.h"
00060 #include "./debug.h"
00061 
00062 
00063 fastf_t rt_cnurb_par_edge(const struct edge_g_cnurb *crv, fastf_t epsilon);
00064 extern void get_indices( genptr_t seg, int *start, int *end );  /* from g_extrude.c */
00065 
00066 int
00067 rt_check_curve(struct curve *crv, struct rt_sketch_internal *skt, int noisey)
00068 {
00069     int i, j;
00070     int ret=0;
00071 
00072     for( i=0 ; i<crv->seg_count ; i++ )
00073         {
00074             struct line_seg *lsg;
00075             struct carc_seg *csg;
00076             struct nurb_seg *nsg;
00077             struct bezier_seg *bsg;
00078             long *lng;
00079 
00080             lng = (long *)crv->segments[i];
00081 
00082             switch( *lng )
00083                 {
00084                     case CURVE_LSEG_MAGIC:
00085                         lsg = (struct line_seg *)lng;
00086                         if( lsg->start >= skt->vert_count ||
00087                             lsg->end >= skt->vert_count )
00088                             ret++;
00089                         break;
00090                     case CURVE_CARC_MAGIC:
00091                         csg = (struct carc_seg *)lng;
00092                         if( csg->start >= skt->vert_count ||
00093                             csg->end >= skt->vert_count )
00094                             ret++;
00095                         break;
00096                     case CURVE_NURB_MAGIC:
00097                         nsg = (struct nurb_seg *)lng;
00098                         for( j=0 ; j<nsg->c_size ; j++ )
00099                             {
00100                                 if( nsg->ctl_points[j] >= skt->vert_count )
00101                                     {
00102                                         ret++;
00103                                         break;
00104                                     }
00105                             }
00106                         break;
00107                     case CURVE_BEZIER_MAGIC:
00108                         bsg = (struct bezier_seg *)lng;
00109                         for( j=0 ; j<=bsg->degree ; j++ ) {
00110                             if( bsg->ctl_points[j] >= skt->vert_count ) {
00111                                 ret++;
00112                                 break;
00113                             }
00114                         }
00115                         break;
00116                     default:
00117                         ret++;
00118                         if( noisey )
00119                             bu_log( "Unrecognized segment type in sketch\n");
00120                         break;
00121                 }
00122         }
00123     if( ret && noisey )
00124         bu_log( "sketch references non-existent vertices!!!\n" );
00125     return( ret );
00126 }
00127 
00128 
00129 /**
00130  *                      R T _ S K E T C H _ P R E P
00131  *
00132  *  Given a pointer to a GED database record, and a transformation matrix,
00133  *  determine if this is a valid SKETCH, and if so, precompute various
00134  *  terms of the formula.
00135  *
00136  *  Returns -
00137  *      0       SKETCH is OK
00138  *      !0      Error in description
00139  *
00140  *  Implicit return -
00141  *      A struct sketch_specific is created, and it's address is stored in
00142  *      stp->st_specific for use by sketch_shot().
00143  */
00144 int
00145 rt_sketch_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00146 {
00147     stp->st_specific = (genptr_t)NULL;
00148     return( 0 );
00149 }
00150 
00151 
00152 /**
00153  *                      R T _ S K E T C H _ P R I N T
00154  */
00155 void
00156 rt_sketch_print(register const struct soltab *stp)
00157 {
00158 }
00159 
00160 /**
00161  *                      R T _ S K E T C H _ S H O T
00162  *
00163  *  Intersect a ray with a sketch.
00164  *  If an intersection occurs, a struct seg will be acquired
00165  *  and filled in.
00166  *
00167  *  Returns -
00168  *      0       MISS
00169  *      >0      HIT
00170  */
00171 int
00172 rt_sketch_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00173 {
00174     return(0);                  /* MISS */
00175 }
00176 
00177 #define RT_SKETCH_SEG_MISS(SEG) (SEG).seg_stp=RT_SOLTAB_NULL
00178 
00179 
00180 /**
00181  *                      R T _ S K E T C H _ V S H O T
00182  *
00183  *  Vectorized version.
00184  */
00185 void
00186 rt_sketch_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00187      /* An array of solid pointers */
00188      /* An array of ray pointers */
00189      /* array of segs (results returned) */
00190      /* Number of ray/object pairs */
00191 
00192 {
00193     rt_vstub( stp, rp, segp, n, ap );
00194 }
00195 
00196 
00197 /**
00198  *                      R T _ S K E T C H _ N O R M
00199  *
00200  *  Given ONE ray distance, return the normal and entry/exit point.
00201  */
00202 void
00203 rt_sketch_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00204 {
00205 
00206     VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
00207 }
00208 
00209 
00210 /**
00211  *                      R T _ S K E T C H _ C U R V E
00212  *
00213  *  Return the curvature of the sketch.
00214  */
00215 void
00216 rt_sketch_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00217 {
00218     cvp->crv_c1 = cvp->crv_c2 = 0;
00219 
00220     /* any tangent direction */
00221     bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
00222 }
00223 
00224 
00225 /**
00226  *                      R T _ S K E T C H _ U V
00227  *
00228  *  For a hit on the surface of an sketch, return the (u,v) coordinates
00229  *  of the hit point, 0 <= u,v <= 1.
00230  *  u = azimuth
00231  *  v = elevation
00232  */
00233 void
00234 rt_sketch_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00235 {
00236 }
00237 
00238 
00239 /**
00240  *              R T _ S K E T C H _ F R E E
00241  */
00242 void
00243 rt_sketch_free(register struct soltab *stp)
00244 {
00245 }
00246 
00247 
00248 /**
00249  *                      R T _ S K E T C H _ C L A S S
00250  */
00251 int
00252 rt_sketch_class(void)
00253 {
00254     return(0);
00255 }
00256 
00257 int
00258 seg_to_vlist(struct bu_list *vhead, const struct rt_tess_tol *ttol, fastf_t *V, fastf_t *u_vec, fastf_t *v_vec, struct rt_sketch_internal *sketch_ip, genptr_t seg)
00259 {
00260     int         ret=0;
00261     int         i;
00262     long                *lng;
00263     struct line_seg *lsg;
00264     struct carc_seg *csg;
00265     struct nurb_seg *nsg;
00266     struct bezier_seg *bsg;
00267     fastf_t delta;
00268     point_t center, start_pt;
00269     fastf_t pt[4];
00270     vect_t semi_a, semi_b;
00271     fastf_t radius;
00272     vect_t norm;
00273 
00274     lng = (long *)seg;
00275     switch( *lng )
00276         {
00277             case CURVE_LSEG_MAGIC:
00278                 lsg = (struct line_seg *)lng;
00279                 if( lsg->start >= sketch_ip->vert_count ||
00280                     lsg->end >= sketch_ip->vert_count )
00281                     {
00282                         ret++;
00283                         break;
00284                     }
00285                 VJOIN2( pt, V, sketch_ip->verts[lsg->start][0], u_vec, sketch_ip->verts[lsg->start][1], v_vec);
00286                 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE )
00287                     VJOIN2( pt, V, sketch_ip->verts[lsg->end][0], u_vec, sketch_ip->verts[lsg->end][1], v_vec);
00288                 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00289                 break;
00290             case CURVE_CARC_MAGIC:
00291                 {
00292                     point2d_t mid_pt, start2d, end2d, center2d, s2m, dir;
00293                     fastf_t s2m_len_sq, len_sq, tmp_len, cross_z;
00294                     fastf_t start_ang, end_ang, tot_ang, cosdel, sindel;
00295                     fastf_t oldu, oldv, newu, newv;
00296                     int nsegs;
00297 
00298                     csg = (struct carc_seg *)lng;
00299                     if( csg->start >= sketch_ip->vert_count ||
00300                         csg->end >= sketch_ip->vert_count )
00301                         {
00302                             ret++;
00303                             break;
00304                         }
00305 
00306                     delta = M_PI/4.0;
00307                     if( csg->radius <= 0.0 )
00308                         {
00309                             VJOIN2( center, V, sketch_ip->verts[csg->end][0], u_vec, sketch_ip->verts[csg->end][1], v_vec);
00310                             VJOIN2( pt, V, sketch_ip->verts[csg->start][0], u_vec, sketch_ip->verts[csg->start][1], v_vec);
00311                             VSUB2( semi_a, pt, center );
00312                             VCROSS( norm, u_vec, v_vec );
00313                             VCROSS( semi_b, norm, semi_a );
00314                             VUNITIZE( semi_b );
00315                             radius = MAGNITUDE( semi_a );
00316                             VSCALE( semi_b, semi_b, radius );
00317                         }
00318                     else if( csg->radius < SMALL_FASTF )
00319                         {
00320                             bu_log( "Radius too small in sketch!\n" );
00321                             break;
00322                         }
00323                     else
00324                         radius = csg->radius;
00325 
00326                     if( ttol->abs > 0.0 )
00327                         {
00328                             fastf_t tmp_delta, ratio;
00329 
00330                             ratio = ttol->abs / radius;
00331                             if( ratio < 1.0 )
00332                                 {
00333                                     tmp_delta = 2.0 * acos( 1.0 - ratio);
00334                                     if( tmp_delta < delta )
00335                                         delta = tmp_delta;
00336                                 }
00337                         }
00338                     if( ttol->rel > 0.0 && ttol->rel < 1.0 )
00339                         {
00340                             fastf_t tmp_delta;
00341 
00342                             tmp_delta = 2.0 * acos( 1.0 - ttol->rel );
00343                             if( tmp_delta < delta )
00344                                 delta = tmp_delta;
00345                         }
00346                     if( ttol->norm > 0.0 )
00347                         {
00348                             fastf_t norm;
00349 
00350                             norm = ttol->norm * M_PI / 180.0;
00351                             if( norm < delta )
00352                                 delta = norm;
00353                         }
00354                     if( csg->radius <= 0.0 )
00355                         {
00356                             /* this is a full circle */
00357                             nsegs = ceil( 2.0 * M_PI / delta );
00358                             delta = 2.0 * M_PI / (double)nsegs;
00359                             cosdel = cos( delta );
00360                             sindel = sin( delta );
00361                             oldu = 1.0;
00362                             oldv = 0.0;
00363                             VJOIN2( start_pt, center, oldu, semi_a, oldv, semi_b );
00364                             RT_ADD_VLIST( vhead, start_pt, BN_VLIST_LINE_MOVE );
00365                             for( i=1 ; i<nsegs ; i++ )
00366                                 {
00367                                     newu = oldu * cosdel - oldv * sindel;
00368                                     newv = oldu * sindel + oldv * cosdel;
00369                                     VJOIN2( pt, center, newu, semi_a, newv, semi_b );
00370                                     RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00371                                     oldu = newu;
00372                                     oldv = newv;
00373                                 }
00374                             RT_ADD_VLIST( vhead, start_pt, BN_VLIST_LINE_DRAW );
00375                             break;
00376                         }
00377 
00378                     /* this is an arc (not a full circle) */
00379                     V2MOVE( start2d, sketch_ip->verts[csg->start] );
00380                     V2MOVE( end2d, sketch_ip->verts[csg->end] );
00381                     mid_pt[0] = (start2d[0] + end2d[0]) * 0.5;
00382                     mid_pt[1] = (start2d[1] + end2d[1]) * 0.5;
00383                     V2SUB2( s2m, mid_pt, start2d )
00384                         dir[0] = -s2m[1];
00385                     dir[1] = s2m[0];
00386                     s2m_len_sq =  s2m[0]*s2m[0] + s2m[1]*s2m[1];
00387                     if( s2m_len_sq < SMALL_FASTF )
00388                         {
00389                             bu_log( "start and end points are too close together in circular arc of sketch\n" );
00390                             break;
00391                         }
00392                     len_sq = radius*radius - s2m_len_sq;
00393                     if( len_sq < 0.0 )
00394                         {
00395                             bu_log( "Impossible radius for specified start and end points in circular arc\n");
00396                             break;
00397                         }
00398                     tmp_len = sqrt( dir[0]*dir[0] + dir[1]*dir[1] );
00399                     dir[0] = dir[0] / tmp_len;
00400                     dir[1] = dir[1] / tmp_len;
00401                     tmp_len = sqrt( len_sq );
00402                     V2JOIN1( center2d, mid_pt, tmp_len, dir )
00403 
00404                         /* check center location */
00405                         cross_z = ( end2d[X] - start2d[X] )*( center2d[Y] - start2d[Y] ) -
00406                         ( end2d[Y] - start2d[Y] )*( center2d[X] - start2d[X] );
00407                     if( !(cross_z > 0.0 && csg->center_is_left) )
00408                         V2JOIN1( center2d, mid_pt, -tmp_len, dir );
00409                     start_ang = atan2( start2d[Y]-center2d[Y], start2d[X]-center2d[X] );
00410                     end_ang = atan2( end2d[Y]-center2d[Y], end2d[X]-center2d[X] );
00411                     if( csg->orientation ) /* clock-wise */
00412                         {
00413                             while( end_ang > start_ang )
00414                                 end_ang -= 2.0 * M_PI;
00415                         }
00416                     else /* counter-clock-wise */
00417                         {
00418                             while( end_ang < start_ang )
00419                                 end_ang += 2.0 * M_PI;
00420                         }
00421                     tot_ang = end_ang - start_ang;
00422                     nsegs = ceil( tot_ang / delta );
00423                     if( nsegs < 0 )
00424                         nsegs = -nsegs;
00425                     if( nsegs < 3 )
00426                         nsegs = 3;
00427                     delta = tot_ang / nsegs;
00428                     cosdel = cos( delta );
00429                     sindel = sin( delta );
00430                     VJOIN2( center, V, center2d[0], u_vec, center2d[1], v_vec );
00431                     VJOIN2( start_pt, V, start2d[0], u_vec, start2d[1], v_vec );
00432                     oldu = (start2d[0] - center2d[0]);
00433                     oldv = (start2d[1] - center2d[1]);
00434                     RT_ADD_VLIST( vhead, start_pt, BN_VLIST_LINE_MOVE );
00435                     for( i=0 ; i<nsegs ; i++ )
00436                         {
00437                             newu = oldu * cosdel - oldv * sindel;
00438                             newv = oldu * sindel + oldv * cosdel;
00439                             VJOIN2( pt, center, newu, u_vec, newv, v_vec );
00440                             RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00441                             oldu = newu;
00442                             oldv = newv;
00443                         }
00444                     break;
00445                 }
00446             case CURVE_NURB_MAGIC:
00447                 {
00448                     struct edge_g_cnurb eg;
00449                     int coords;
00450                     fastf_t inv_weight;
00451                     int num_intervals;
00452                     fastf_t param_delta, epsilon;
00453 
00454                     nsg = (struct nurb_seg *)lng;
00455                     for( i=0 ; i<nsg->c_size ; i++ )
00456                         {
00457                             if( nsg->ctl_points[i] >= sketch_ip->vert_count )
00458                                 {
00459                                     ret++;
00460                                     break;
00461                                 }
00462                         }
00463                     if( nsg->order < 3 )
00464                         {
00465                             /* just straight lines */
00466                             VJOIN2( start_pt, V, sketch_ip->verts[nsg->ctl_points[0]][0], u_vec, sketch_ip->verts[nsg->ctl_points[0]][1], v_vec );
00467                             if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) )
00468                                 {
00469                                     inv_weight = 1.0/nsg->weights[0];
00470                                     VSCALE( start_pt, start_pt, inv_weight );
00471                                 }
00472                             RT_ADD_VLIST( vhead, start_pt, BN_VLIST_LINE_MOVE );
00473                             for( i=1 ; i<nsg->c_size ; i++ )
00474                                 {
00475                                     VJOIN2( pt, V, sketch_ip->verts[nsg->ctl_points[i]][0], u_vec, sketch_ip->verts[nsg->ctl_points[i]][1], v_vec );
00476                                     if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) )
00477                                         {
00478                                             inv_weight = 1.0/nsg->weights[i];
00479                                             VSCALE( pt, pt, inv_weight );
00480                                         }
00481                                     RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00482                                 }
00483                             break;
00484                         }
00485                     eg.l.magic = NMG_EDGE_G_CNURB_MAGIC;
00486                     eg.order = nsg->order;
00487                     eg.k.k_size = nsg->k.k_size;
00488                     eg.k.knots = nsg->k.knots;
00489                     eg.c_size = nsg->c_size;
00490                     coords = 3 + RT_NURB_IS_PT_RATIONAL( nsg->pt_type );
00491                     eg.pt_type = RT_NURB_MAKE_PT_TYPE( coords, 2, RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) );
00492                     eg.ctl_points = (fastf_t *)bu_malloc( nsg->c_size * coords * sizeof( fastf_t ), "eg.ctl_points" );
00493                     if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) )
00494                         {
00495                             for( i=0 ; i<nsg->c_size ; i++ )
00496                                 {
00497                                     VJOIN2( &eg.ctl_points[i*coords], V, sketch_ip->verts[nsg->ctl_points[i]][0], u_vec, sketch_ip->verts[nsg->ctl_points[i]][1], v_vec );
00498                                     eg.ctl_points[(i+1)*coords - 1] = nsg->weights[i];
00499                                 }
00500                         }
00501                     else
00502                         {
00503                             for( i=0 ; i<nsg->c_size ; i++ )
00504                                 VJOIN2( &eg.ctl_points[i*coords], V, sketch_ip->verts[nsg->ctl_points[i]][0], u_vec, sketch_ip->verts[nsg->ctl_points[i]][1], v_vec );
00505                         }
00506                     epsilon = MAX_FASTF;
00507                     if( ttol->abs > 0.0 && ttol->abs < epsilon )
00508                         epsilon = ttol->abs;
00509                     if( ttol->rel > 0.0 )
00510                         {
00511                             point2d_t min_pt, max_pt, tmp_pt;
00512                             point2d_t diff;
00513                             fastf_t tmp_epsilon;
00514 
00515                             min_pt[0] = MAX_FASTF;
00516                             min_pt[1] = MAX_FASTF;
00517                             max_pt[0] = -MAX_FASTF;
00518                             max_pt[1] = -MAX_FASTF;
00519 
00520                             for( i=0 ; i<nsg->c_size ; i++ )
00521                                 {
00522                                     V2MOVE( tmp_pt, sketch_ip->verts[nsg->ctl_points[i]] );
00523                                     if( tmp_pt[0] > max_pt[0] )
00524                                         max_pt[0] = tmp_pt[0];
00525                                     if( tmp_pt[1] > max_pt[1] )
00526                                         max_pt[1] = tmp_pt[1];
00527                                     if( tmp_pt[0] < min_pt[0] )
00528                                         min_pt[0] = tmp_pt[0];
00529                                     if( tmp_pt[1] < min_pt[1] )
00530                                         min_pt[1] = tmp_pt[1];
00531                                 }
00532 
00533                             V2SUB2( diff, max_pt, min_pt )
00534                                 tmp_epsilon = ttol->rel * sqrt( MAG2SQ( diff ) );
00535                             if( tmp_epsilon < epsilon )
00536                                 epsilon = tmp_epsilon;
00537 
00538                         }
00539                     param_delta = rt_cnurb_par_edge( &eg, epsilon );
00540                     num_intervals = ceil( (nsg->k.knots[nsg->k.k_size-1] - nsg->k.knots[0])/param_delta );
00541                     if( num_intervals < 3 )
00542                         num_intervals = 3;
00543                     if( num_intervals > 500 )
00544                         {
00545                             bu_log( "num_intervals was %d, clamped to 500\n", num_intervals );
00546                             num_intervals = 500;
00547                         }
00548                     param_delta = (nsg->k.knots[nsg->k.k_size-1] - nsg->k.knots[0])/(double)num_intervals;
00549                     for( i=0 ; i<=num_intervals ; i++ )
00550                         {
00551                             fastf_t t;
00552                             int j;
00553 
00554                             t = nsg->k.knots[0] + i*param_delta;
00555                             rt_nurb_c_eval( &eg, t, pt );
00556                             if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) )
00557                                 {
00558                                     for( j=0 ; j<coords-1 ; j++ )
00559                                         pt[j] /= pt[coords-1];
00560                                 }
00561                             if( i == 0 )
00562                                 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE )
00563                                     else
00564                                         RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00565                         }
00566                     bu_free( (char *)eg.ctl_points, "eg.ctl_points" );
00567                     break;
00568                 }
00569             case CURVE_BEZIER_MAGIC: {
00570                 struct bezier_2d_list *bezier_hd, *bz;
00571                 fastf_t epsilon;
00572 
00573                 bsg = (struct bezier_seg *)lng;
00574 
00575                 for( i=0 ; i<=bsg->degree ; i++ ) {
00576                     if( bsg->ctl_points[i] >= sketch_ip->vert_count ) {
00577                         ret++;
00578                         break;
00579                     }
00580                 }
00581 
00582                 if( bsg->degree < 1 ) {
00583                     bu_log( "g_sketch: ERROR: Bezier curve with illegal degree (%d)\n",
00584                             bsg->degree );
00585                     ret++;
00586                     break;
00587                 }
00588 
00589                 if( bsg->degree == 1 ) {
00590                     /* straight line */
00591                     VJOIN2( start_pt, V, sketch_ip->verts[bsg->ctl_points[0]][0],
00592                             u_vec, sketch_ip->verts[bsg->ctl_points[0]][1], v_vec );
00593                     RT_ADD_VLIST( vhead, start_pt, BN_VLIST_LINE_MOVE );
00594                     for( i=1 ; i<=bsg->degree ; i++ ) {
00595                         VJOIN2( pt, V, sketch_ip->verts[bsg->ctl_points[i]][0],
00596                                 u_vec, sketch_ip->verts[bsg->ctl_points[i]][1], v_vec );
00597                         RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00598                     }
00599                     break;
00600                 }
00601 
00602                 /* use tolerance to determine coarseness of plot */
00603                 epsilon = MAX_FASTF;
00604                 if( ttol->abs > 0.0 && ttol->abs < epsilon )
00605                     epsilon = ttol->abs;
00606                 if( ttol->rel > 0.0 )
00607                     {
00608                         point2d_t min_pt, max_pt, tmp_pt;
00609                         point2d_t diff;
00610                         fastf_t tmp_epsilon;
00611 
00612                         min_pt[0] = MAX_FASTF;
00613                         min_pt[1] = MAX_FASTF;
00614                         max_pt[0] = -MAX_FASTF;
00615                         max_pt[1] = -MAX_FASTF;
00616 
00617                         for( i=0 ; i<=bsg->degree ; i++ )
00618                             {
00619                                 V2MOVE( tmp_pt, sketch_ip->verts[bsg->ctl_points[i]] );
00620                                 if( tmp_pt[0] > max_pt[0] )
00621                                     max_pt[0] = tmp_pt[0];
00622                                 if( tmp_pt[1] > max_pt[1] )
00623                                     max_pt[1] = tmp_pt[1];
00624                                 if( tmp_pt[0] < min_pt[0] )
00625                                     min_pt[0] = tmp_pt[0];
00626                                 if( tmp_pt[1] < min_pt[1] )
00627                                     min_pt[1] = tmp_pt[1];
00628                             }
00629 
00630                         V2SUB2( diff, max_pt, min_pt )
00631                             tmp_epsilon = ttol->rel * sqrt( MAG2SQ( diff ) );
00632                         if( tmp_epsilon < epsilon )
00633                             epsilon = tmp_epsilon;
00634 
00635                     }
00636 
00637 
00638                 /* Create an initial bezier_2d_list */
00639                 bezier_hd = (struct bezier_2d_list *)bu_malloc( sizeof( struct bezier_2d_list ),
00640                                                                 "g_sketch.c: bezier_hd" );
00641                 BU_LIST_INIT( &bezier_hd->l );
00642                 bezier_hd->ctl = (point2d_t *)bu_calloc( bsg->degree + 1, sizeof( point2d_t ),
00643                                                          "g_sketch.c: bezier_hd->ctl" );
00644                 for( i=0 ; i<=bsg->degree ; i++ ) {
00645                     V2MOVE( bezier_hd->ctl[i], sketch_ip->verts[bsg->ctl_points[i]] );
00646                 }
00647 
00648                 /* now do subdivision as necessary */
00649                 bezier_hd = subdivide_bezier( bezier_hd, bsg->degree, epsilon, 0 );
00650 
00651                 /* plot the results */
00652                 bz = BU_LIST_FIRST( bezier_2d_list, &bezier_hd->l );
00653                 VJOIN2( pt, V, bz->ctl[0][0], u_vec, bz->ctl[0][1], v_vec);
00654                 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
00655 
00656                 while( BU_LIST_WHILE( bz, bezier_2d_list, &(bezier_hd->l) ) ) {
00657                     BU_LIST_DEQUEUE( &bz->l );
00658                     for( i=1 ; i<=bsg->degree ; i++ ) {
00659                         VJOIN2( pt, V, bz->ctl[i][0], u_vec,
00660                                 bz->ctl[i][1], v_vec);
00661                         RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00662                     }
00663                     bu_free( (char *)bz->ctl, "g_sketch.c: bz->ctl" );
00664                     bu_free( (char *)bz, "g_sketch.c: bz" );
00665                 }
00666                 bu_free( (char *)bezier_hd, "g_sketch.c: bezier_hd" );
00667                 break;
00668             }
00669             default:
00670                 bu_log( "seg_to_vlist: ERROR: unrecognized segment type!!!!\n" );
00671                 break;
00672         }
00673 
00674     return( ret );
00675 }
00676 
00677 
00678 /**
00679  *                      C U R V E _ T O _ V L I S T
00680  */
00681 int
00682 curve_to_vlist(struct bu_list *vhead, const struct rt_tess_tol *ttol, fastf_t *V, fastf_t *u_vec, fastf_t *v_vec, struct rt_sketch_internal *sketch_ip, struct curve *crv)
00683 {
00684     int seg_no;
00685     int ret=0;
00686 
00687     if( bu_debug&BU_DEBUG_MEM_CHECK )
00688         {
00689             bu_log( "Barrier check at start of curve_to_vlist():\n" );
00690             bu_mem_barriercheck();
00691         }
00692 
00693     for( seg_no=0 ; seg_no < crv->seg_count ; seg_no++ )
00694         {
00695             ret += seg_to_vlist( vhead, ttol, V, u_vec, v_vec, sketch_ip, crv->segments[seg_no] );
00696         }
00697 
00698     if( bu_debug&BU_DEBUG_MEM_CHECK )
00699         {
00700             bu_log( "Barrier check at end of curve_to_vlist():\n" );
00701             bu_mem_barriercheck();
00702         }
00703 
00704     return( ret );
00705 }
00706 
00707 
00708 /**
00709  *                      R T _ S K E T C H _ P L O T
00710  */
00711 int
00712 rt_sketch_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00713 {
00714     LOCAL struct rt_sketch_internal     *sketch_ip;
00715     int                         ret;
00716     int                         myret=0;
00717 
00718     RT_CK_DB_INTERNAL(ip);
00719     sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
00720     RT_SKETCH_CK_MAGIC(sketch_ip);
00721 
00722     if( (ret=curve_to_vlist( vhead, ttol, sketch_ip->V, sketch_ip->u_vec, sketch_ip->v_vec, sketch_ip, &sketch_ip->skt_curve )) )
00723         {
00724             myret--;
00725             bu_log( "WARNING: Errors in sketch (%d segments reference non-existent vertices)\n",
00726                     ret );
00727         }
00728 
00729     return( myret );
00730 }
00731 
00732 
00733 /**
00734  *                      R T _ S K E T C H _ T E S S
00735  *
00736  *  Returns -
00737  *      -1      failure
00738  *       0      OK.  *r points to nmgregion that holds this tessellation.
00739  */
00740 int
00741 rt_sketch_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00742 {
00743     return(-1);
00744 }
00745 
00746 
00747 /**
00748  *                      R T _ S K E T C H _ I M P O R T
00749  *
00750  *  Import an SKETCH from the database format to the internal format.
00751  *  Apply modeling transformations as well.
00752  */
00753 int
00754 rt_sketch_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
00755 {
00756     LOCAL struct rt_sketch_internal     *sketch_ip;
00757     union record                        *rp;
00758     vect_t                              v;
00759     int                         seg_no;
00760     unsigned char                       *ptr;
00761     struct curve                        *crv;
00762     int                         i;
00763 
00764     BU_CK_EXTERNAL( ep );
00765     rp = (union record *)ep->ext_buf;
00766     /* Check record type */
00767     if( rp->u_id != DBID_SKETCH )  {
00768         bu_log("rt_sketch_import: defective record\n");
00769         return(-1);
00770     }
00771 
00772     if( bu_debug&BU_DEBUG_MEM_CHECK )
00773         {
00774             bu_log( "Barrier check at start of sketch_import():\n" );
00775             bu_mem_barriercheck();
00776         }
00777 
00778     RT_CK_DB_INTERNAL( ip );
00779     ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00780     ip->idb_type = ID_SKETCH;
00781     ip->idb_meth = &rt_functab[ID_SKETCH];
00782     ip->idb_ptr = bu_calloc( 1, sizeof(struct rt_sketch_internal), "rt_sketch_internal");
00783     sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
00784     sketch_ip->magic = RT_SKETCH_INTERNAL_MAGIC;
00785 
00786     ntohd( (unsigned char *)v, rp->skt.skt_V, 3 );
00787     MAT4X3PNT( sketch_ip->V, mat, v );
00788     ntohd( (unsigned char *)v, rp->skt.skt_uvec, 3 );
00789     MAT4X3VEC( sketch_ip->u_vec, mat, v );
00790     ntohd( (unsigned char *)v, rp->skt.skt_vvec, 3 );
00791     MAT4X3VEC( sketch_ip->v_vec, mat, v );
00792     sketch_ip->vert_count = bu_glong( rp->skt.skt_vert_count );
00793     sketch_ip->skt_curve.seg_count = bu_glong( rp->skt.skt_seg_count );
00794 
00795     ptr = (unsigned char *)rp;
00796     ptr += sizeof( struct sketch_rec );
00797     if( sketch_ip->vert_count )
00798         sketch_ip->verts = (point2d_t *)bu_calloc( sketch_ip->vert_count, sizeof( point2d_t ), "sketch_ip->vert" );
00799     ntohd( (unsigned char *)sketch_ip->verts, ptr, sketch_ip->vert_count*2 );
00800     ptr += 16 * sketch_ip->vert_count;
00801 
00802     if( sketch_ip->skt_curve.seg_count )
00803         sketch_ip->skt_curve.segments = (genptr_t *)bu_calloc( sketch_ip->skt_curve.seg_count, sizeof( genptr_t ), "segs" );
00804     else
00805         sketch_ip->skt_curve.segments = (genptr_t *)NULL;
00806     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
00807         {
00808             long magic;
00809             struct line_seg *lsg;
00810             struct carc_seg *csg;
00811             struct nurb_seg *nsg;
00812             struct bezier_seg *bsg;
00813             int i;
00814 
00815             magic = bu_glong( ptr );
00816             ptr += 4;
00817             switch( magic )
00818                 {
00819                     case CURVE_LSEG_MAGIC:
00820                         lsg = (struct line_seg *)bu_malloc( sizeof( struct line_seg ), "lsg" );
00821                         lsg->magic = magic;
00822                         lsg->start = bu_glong( ptr );
00823                         ptr += 4;
00824                         lsg->end = bu_glong( ptr );
00825                         ptr += 4;
00826                         sketch_ip->skt_curve.segments[seg_no] = (genptr_t)lsg;
00827                         break;
00828                     case CURVE_CARC_MAGIC:
00829                         csg = (struct carc_seg *)bu_malloc( sizeof( struct carc_seg ), "csg" );
00830                         csg->magic = magic;
00831                         csg->start = bu_glong( ptr );
00832                         ptr += 4;
00833                         csg->end = bu_glong( ptr );
00834                         ptr += 4;
00835                         csg->orientation = bu_glong( ptr );
00836                         ptr += 4;
00837                         csg->center_is_left = bu_glong( ptr );
00838                         ptr += 4;
00839                         ntohd( (unsigned char *)&csg->radius, ptr, 1 );
00840                         ptr += 8;
00841                         sketch_ip->skt_curve.segments[seg_no] = (genptr_t)csg;
00842                         break;
00843                     case CURVE_NURB_MAGIC:
00844                         nsg = (struct nurb_seg *)bu_malloc( sizeof( struct nurb_seg ), "nsg" );
00845                         nsg->magic = magic;
00846                         nsg->order = bu_glong( ptr );
00847                         ptr += 4;
00848                         nsg->pt_type = bu_glong( ptr );
00849                         ptr += 4;
00850                         nsg->k.k_size = bu_glong( ptr );
00851                         ptr += 4;
00852                         nsg->k.knots = (fastf_t *)bu_malloc( nsg->k.k_size * sizeof( fastf_t ), "nsg->k.knots" );
00853                         ntohd( (unsigned char *)nsg->k.knots, ptr, nsg->k.k_size );
00854                         ptr += 8 * nsg->k.k_size;
00855                         nsg->c_size = bu_glong( ptr );
00856                         ptr += 4;
00857                         nsg->ctl_points = (int *)bu_malloc( nsg->c_size * sizeof( int ), "nsg->ctl_points" );
00858                         for( i=0 ; i<nsg->c_size ; i++ )
00859                             {
00860                                 nsg->ctl_points[i] = bu_glong( ptr );
00861                                 ptr += 4;
00862                             }
00863                         if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) )
00864                             {
00865                                 nsg->weights = (fastf_t *)bu_malloc( nsg->c_size * sizeof( fastf_t ), "nsg->weights" );
00866                                 ntohd( (unsigned char *)nsg->weights, ptr, nsg->c_size );
00867                                 ptr += 8 * nsg->c_size;
00868                             }
00869                         else
00870                             nsg->weights = (fastf_t *)NULL;
00871                         sketch_ip->skt_curve.segments[seg_no] = (genptr_t)nsg;
00872                         break;
00873                     case CURVE_BEZIER_MAGIC:
00874                         bsg = (struct bezier_seg *)bu_malloc( sizeof( struct bezier_seg ), "bsg" );
00875                         bsg->magic = magic;
00876                         bsg->degree = bu_glong( ptr );
00877                         ptr += 4;
00878                         bsg->ctl_points = (int *)bu_calloc( bsg->degree + 1, sizeof( int ), "bsg->ctl_points" );
00879                         for( i=0 ; i<=bsg->degree ; i++ ) {
00880                             bsg->ctl_points[i] = bu_glong( ptr );
00881                             ptr += 4;
00882                         }
00883                         sketch_ip->skt_curve.segments[seg_no] = (genptr_t)bsg;
00884                         break;
00885                     default:
00886                         bu_bomb( "rt_sketch_import: ERROR: unrecognized segment type!!!\n" );
00887                         break;
00888                 }
00889         }
00890 
00891     crv = &sketch_ip->skt_curve;
00892 
00893     crv->reverse = (int *)bu_calloc( crv->seg_count, sizeof(int), "crv->reverse" );
00894     for( i=0 ; i<crv->seg_count ; i++ )
00895         {
00896             crv->reverse[i] = bu_glong( ptr );
00897             ptr += 4;
00898         }
00899 
00900     if( bu_debug&BU_DEBUG_MEM_CHECK )
00901         {
00902             bu_log( "Barrier check at end of sketch_import():\n" );
00903             bu_mem_barriercheck();
00904         }
00905 
00906     return(0);                  /* OK */
00907 }
00908 
00909 
00910 /**
00911  *                      R T _ S K E T C H _ E X P O R T
00912  *
00913  *  The name is added by the caller, in the usual place.
00914  */
00915 int
00916 rt_sketch_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00917 {
00918     struct rt_sketch_internal   *sketch_ip;
00919     union record                *rec;
00920     int i, seg_no, nbytes=0, ngran;
00921     vect_t tmp_vec;
00922     unsigned char *ptr;
00923 
00924     RT_CK_DB_INTERNAL(ip);
00925     if( ip->idb_type != ID_SKETCH )  return(-1);
00926     sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
00927     RT_SKETCH_CK_MAGIC(sketch_ip);
00928 
00929     if( bu_debug&BU_DEBUG_MEM_CHECK )
00930         {
00931             bu_log( "Barrier check at start of sketch_export():\n" );
00932             bu_mem_barriercheck();
00933         }
00934 
00935     BU_CK_EXTERNAL(ep);
00936 
00937     nbytes = sizeof(union record);              /* base record */
00938     nbytes += sketch_ip->vert_count*(8*2);      /* vertex list */
00939 
00940     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
00941         {
00942             long *lng;
00943             struct nurb_seg *nseg;
00944             struct bezier_seg *bseg;
00945 
00946             lng = (long *)sketch_ip->skt_curve.segments[seg_no];
00947             switch( *lng )
00948                 {
00949                     case CURVE_LSEG_MAGIC:
00950                         nbytes += 12;
00951                         break;
00952                     case CURVE_CARC_MAGIC:
00953                         nbytes += 28;
00954                         break;
00955                     case CURVE_NURB_MAGIC:
00956                         nseg = (struct nurb_seg *)lng;
00957                         nbytes += 16 + sizeof( struct knot_vector) + nseg->k.k_size * 8 + nseg->c_size * 4;
00958                         if( RT_NURB_IS_PT_RATIONAL( nseg->pt_type ) )
00959                             nbytes += nseg->c_size * 8; /* weights */
00960                         break;
00961                     case CURVE_BEZIER_MAGIC:
00962                         bseg = (struct bezier_seg *)lng;
00963                         nbytes += 8 + (bseg->degree + 1) * 4;
00964                         break;
00965                     default:
00966                         bu_log( "rt_sketch_export: unsupported segement type (x%x)\n", *lng );
00967                         bu_bomb( "rt_sketch_export: unsupported segement type\n" );
00968                 }
00969         }
00970 
00971     ngran = ceil((double)(nbytes + sizeof(union record)) / sizeof(union record));
00972     ep->ext_nbytes = ngran * sizeof(union record);
00973     ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "sketch external");
00974 
00975     rec = (union record *)ep->ext_buf;
00976 
00977     rec->skt.skt_id = DBID_SKETCH;
00978 
00979     /* convert from local editing units to mm and export
00980      * to database record format
00981      */
00982     VSCALE( tmp_vec, sketch_ip->V, local2mm );
00983     htond( rec->skt.skt_V, (unsigned char *)tmp_vec, 3 );
00984 
00985     /* uvec and uvec are unit vectors, do not convert to/from mm */
00986     htond( rec->skt.skt_uvec, (unsigned char *)sketch_ip->u_vec, 3 );
00987     htond( rec->skt.skt_vvec, (unsigned char *)sketch_ip->v_vec, 3 );
00988 
00989     (void)bu_plong( rec->skt.skt_vert_count, sketch_ip->vert_count );
00990     (void)bu_plong( rec->skt.skt_seg_count, sketch_ip->skt_curve.seg_count );
00991     (void)bu_plong( rec->skt.skt_count, ngran-1 );
00992 
00993     ptr = (unsigned char *)rec;
00994     ptr += sizeof( struct sketch_rec );
00995     /* convert 2D points to mm */
00996     for( i=0 ; i<sketch_ip->vert_count ; i++ )
00997         {
00998             point2d_t pt2d;
00999 
01000             V2SCALE( pt2d, sketch_ip->verts[i], local2mm )
01001                 htond( ptr, (const unsigned char *)pt2d, 2 );
01002             ptr += 16;
01003         }
01004 
01005     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
01006         {
01007             struct line_seg *lseg;
01008             struct carc_seg *cseg;
01009             struct nurb_seg *nseg;
01010             struct bezier_seg *bseg;
01011             long *lng;
01012             fastf_t tmp_fastf;
01013 
01014             /* write segment type ID, and segement parameters */
01015             lng = (long *)sketch_ip->skt_curve.segments[seg_no];
01016             switch (*lng )
01017                 {
01018                     case CURVE_LSEG_MAGIC:
01019                         lseg = (struct line_seg *)lng;
01020                         (void)bu_plong( ptr, CURVE_LSEG_MAGIC );
01021                         ptr += 4;
01022                         (void)bu_plong( ptr, lseg->start );
01023                         ptr += 4;
01024                         (void)bu_plong( ptr, lseg->end );
01025                         ptr += 4;
01026                         break;
01027                     case CURVE_CARC_MAGIC:
01028                         cseg = (struct carc_seg *)lng;
01029                         (void)bu_plong( ptr, CURVE_CARC_MAGIC );
01030                         ptr += 4;
01031                         (void)bu_plong( ptr, cseg->start );
01032                         ptr += 4;
01033                         (void)bu_plong( ptr, cseg->end );
01034                         ptr += 4;
01035                         (void) bu_plong( ptr, cseg->orientation );
01036                         ptr += 4;
01037                         (void) bu_plong( ptr, cseg->center_is_left );
01038                         ptr += 4;
01039                         tmp_fastf = cseg->radius * local2mm;
01040                         htond( ptr, (unsigned char *)&tmp_fastf, 1 );
01041                         ptr += 8;
01042                         break;
01043                     case CURVE_NURB_MAGIC:
01044                         nseg = (struct nurb_seg *)lng;
01045                         (void)bu_plong( ptr, CURVE_NURB_MAGIC );
01046                         ptr += 4;
01047                         (void)bu_plong( ptr, nseg->order );
01048                         ptr += 4;
01049                         (void)bu_plong( ptr, nseg->pt_type );
01050                         ptr += 4;
01051                         (void)bu_plong( ptr, nseg->k.k_size );
01052                         ptr += 4;
01053                         htond( ptr, (const unsigned char *)nseg->k.knots, nseg->k.k_size );
01054                         ptr += nseg->k.k_size * 8;
01055                         (void)bu_plong( ptr, nseg->c_size );
01056                         ptr += 4;
01057                         for( i=0 ; i<nseg->c_size ; i++ )
01058                             {
01059                                 (void)bu_plong( ptr, nseg->ctl_points[i] );
01060                                 ptr +=  4;
01061                             }
01062                         if( RT_NURB_IS_PT_RATIONAL( nseg->pt_type ) )
01063                             {
01064                                 htond( ptr, (const unsigned char *)nseg->weights, nseg->c_size );
01065                                 ptr += 8 * nseg->c_size;
01066                             }
01067                         break;
01068                     case CURVE_BEZIER_MAGIC:
01069                         bseg = (struct bezier_seg *)lng;
01070                         (void)bu_plong( ptr, CURVE_BEZIER_MAGIC );
01071                         ptr += 4;
01072                         (void)bu_plong( ptr, bseg->degree );
01073                         ptr += 4;
01074                         for( i=0 ; i<=bseg->degree ; i++ ) {
01075                             (void)bu_plong( ptr, bseg->ctl_points[i] );
01076                             ptr += 4;
01077                         }
01078                         break;
01079                     default:
01080                         bu_bomb( "rt_sketch_export: ERROR: unrecognized curve type!!!!\n" );
01081                         break;
01082 
01083                 }
01084         }
01085 
01086     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
01087         {
01088             (void)bu_plong( ptr, sketch_ip->skt_curve.reverse[seg_no] );
01089             ptr += 4;
01090         }
01091     if( bu_debug&BU_DEBUG_MEM_CHECK )
01092         {
01093             bu_log( "Barrier check at end of sketch_export():\n" );
01094             bu_mem_barriercheck();
01095         }
01096 
01097     return(0);
01098 }
01099 
01100 
01101 /**
01102  *                      R T _ S K E T C H _ I M P O R T 5
01103  *
01104  *  Import an SKETCH from the database format to the internal format.
01105  *  Apply modeling transformations as well.
01106  */
01107 int
01108 rt_sketch_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01109 {
01110     LOCAL struct rt_sketch_internal     *sketch_ip;
01111     vect_t                              v;
01112     int                         seg_no;
01113     unsigned char                       *ptr;
01114     struct curve                        *crv;
01115     int                         i;
01116 
01117     BU_CK_EXTERNAL( ep );
01118 
01119     if( bu_debug&BU_DEBUG_MEM_CHECK )
01120         {
01121             bu_log( "Barrier check at start of sketch_import5():\n" );
01122             bu_mem_barriercheck();
01123         }
01124 
01125     RT_CK_DB_INTERNAL( ip );
01126     ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01127     ip->idb_type = ID_SKETCH;
01128     ip->idb_meth = &rt_functab[ID_SKETCH];
01129     ip->idb_ptr = bu_calloc( 1, sizeof(struct rt_sketch_internal), "rt_sketch_internal");
01130     sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
01131     sketch_ip->magic = RT_SKETCH_INTERNAL_MAGIC;
01132 
01133     ptr = ep->ext_buf;
01134     ntohd( (unsigned char *)v, ptr, 3 );
01135     MAT4X3PNT( sketch_ip->V, mat, v );
01136     ptr += SIZEOF_NETWORK_DOUBLE * 3;
01137     ntohd( (unsigned char *)v, ptr, 3 );
01138     MAT4X3VEC( sketch_ip->u_vec, mat, v );
01139     ptr += SIZEOF_NETWORK_DOUBLE * 3;
01140     ntohd( (unsigned char *)v, ptr, 3 );
01141     MAT4X3VEC( sketch_ip->v_vec, mat, v );
01142     ptr += SIZEOF_NETWORK_DOUBLE * 3;
01143     sketch_ip->vert_count = bu_glong( ptr );
01144     ptr += SIZEOF_NETWORK_LONG;
01145     sketch_ip->skt_curve.seg_count = bu_glong( ptr );
01146     ptr += SIZEOF_NETWORK_LONG;
01147 
01148     if( sketch_ip->vert_count )
01149         sketch_ip->verts = (point2d_t *)bu_calloc( sketch_ip->vert_count, sizeof( point2d_t ), "sketch_ip->vert" );
01150     ntohd( (unsigned char *)sketch_ip->verts, ptr, sketch_ip->vert_count*2 );
01151     ptr += SIZEOF_NETWORK_DOUBLE * 2 * sketch_ip->vert_count;
01152 
01153     if( sketch_ip->skt_curve.seg_count )
01154         sketch_ip->skt_curve.segments = (genptr_t *)bu_calloc( sketch_ip->skt_curve.seg_count, sizeof( genptr_t ), "segs" );
01155     else
01156         sketch_ip->skt_curve.segments = (genptr_t *)NULL;
01157     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
01158         {
01159             long magic;
01160             struct line_seg *lsg;
01161             struct carc_seg *csg;
01162             struct nurb_seg *nsg;
01163             struct bezier_seg *bsg;
01164             int i;
01165 
01166             magic = bu_glong( ptr );
01167             ptr += SIZEOF_NETWORK_LONG;
01168             switch( magic )
01169                 {
01170                     case CURVE_LSEG_MAGIC:
01171                         lsg = (struct line_seg *)bu_malloc( sizeof( struct line_seg ), "lsg" );
01172                         lsg->magic = magic;
01173                         lsg->start = bu_glong( ptr );
01174                         ptr += SIZEOF_NETWORK_LONG;
01175                         lsg->end = bu_glong( ptr );
01176                         ptr += SIZEOF_NETWORK_LONG;
01177                         sketch_ip->skt_curve.segments[seg_no] = (genptr_t)lsg;
01178                         break;
01179                     case CURVE_CARC_MAGIC:
01180                         csg = (struct carc_seg *)bu_malloc( sizeof( struct carc_seg ), "csg" );
01181                         csg->magic = magic;
01182                         csg->start = bu_glong( ptr );
01183                         ptr += SIZEOF_NETWORK_LONG;
01184                         csg->end = bu_glong( ptr );
01185                         ptr += SIZEOF_NETWORK_LONG;
01186                         csg->orientation = bu_glong( ptr );
01187                         ptr += SIZEOF_NETWORK_LONG;
01188                         csg->center_is_left = bu_glong( ptr );
01189                         ptr += SIZEOF_NETWORK_LONG;
01190                         ntohd( (unsigned char *)&csg->radius, ptr, 1 );
01191                         ptr += SIZEOF_NETWORK_DOUBLE;
01192                         sketch_ip->skt_curve.segments[seg_no] = (genptr_t)csg;
01193                         break;
01194                     case CURVE_NURB_MAGIC:
01195                         nsg = (struct nurb_seg *)bu_malloc( sizeof( struct nurb_seg ), "nsg" );
01196                         nsg->magic = magic;
01197                         nsg->order = bu_glong( ptr );
01198                         ptr += SIZEOF_NETWORK_LONG;
01199                         nsg->pt_type = bu_glong( ptr );
01200                         ptr += SIZEOF_NETWORK_LONG;
01201                         nsg->k.k_size = bu_glong( ptr );
01202                         ptr += SIZEOF_NETWORK_LONG;
01203                         nsg->k.knots = (fastf_t *)bu_malloc( nsg->k.k_size * sizeof( fastf_t ), "nsg->k.knots" );
01204                         ntohd( (unsigned char *)nsg->k.knots, ptr, nsg->k.k_size );
01205                         ptr += SIZEOF_NETWORK_DOUBLE * nsg->k.k_size;
01206                         nsg->c_size = bu_glong( ptr );
01207                         ptr += SIZEOF_NETWORK_LONG;
01208                         nsg->ctl_points = (int *)bu_malloc( nsg->c_size * sizeof( int ), "nsg->ctl_points" );
01209                         for( i=0 ; i<nsg->c_size ; i++ )
01210                             {
01211                                 nsg->ctl_points[i] = bu_glong( ptr );
01212                                 ptr += SIZEOF_NETWORK_LONG;
01213                             }
01214                         if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) )
01215                             {
01216                                 nsg->weights = (fastf_t *)bu_malloc( nsg->c_size * sizeof( fastf_t ), "nsg->weights" );
01217                                 ntohd( (unsigned char *)nsg->weights, ptr, nsg->c_size );
01218                                 ptr += SIZEOF_NETWORK_DOUBLE * nsg->c_size;
01219                             }
01220                         else
01221                             nsg->weights = (fastf_t *)NULL;
01222                         sketch_ip->skt_curve.segments[seg_no] = (genptr_t)nsg;
01223                         break;
01224                     case CURVE_BEZIER_MAGIC:
01225                         bsg = (struct bezier_seg *)bu_malloc( sizeof( struct bezier_seg ), "bsg" );
01226                         bsg->magic = magic;
01227                         bsg->degree = bu_glong( ptr );
01228                         ptr += SIZEOF_NETWORK_LONG;
01229                         bsg->ctl_points = (int *)bu_calloc( bsg->degree+1, sizeof( int ), "bsg->ctl_points" );
01230                         for( i=0 ; i<=bsg->degree ; i++ ) {
01231                             bsg->ctl_points[i] = bu_glong( ptr );
01232                             ptr += SIZEOF_NETWORK_LONG;
01233                         }
01234                         sketch_ip->skt_curve.segments[seg_no] = (genptr_t)bsg;
01235                         break;
01236                     default:
01237                         bu_bomb( "rt_sketch_import: ERROR: unrecognized segment type!!!\n" );
01238                         break;
01239                 }
01240         }
01241 
01242     crv = &sketch_ip->skt_curve;
01243 
01244     if (crv->seg_count) {
01245         crv->reverse = (int *)bu_calloc( crv->seg_count, sizeof(int), "crv->reverse" );
01246     }
01247 
01248     for( i=0 ; i<crv->seg_count ; i++ )
01249         {
01250             crv->reverse[i] = bu_glong( ptr );
01251             ptr += SIZEOF_NETWORK_LONG;
01252         }
01253 
01254     if( bu_debug&BU_DEBUG_MEM_CHECK )
01255         {
01256             bu_log( "Barrier check at end of sketch_import5():\n" );
01257             bu_mem_barriercheck();
01258         }
01259 
01260     return(0);                  /* OK */
01261 }
01262 
01263 
01264 /**
01265  *                      R T _ S K E T C H _ E X P O R T 5
01266  *
01267  *  The name is added by the caller, in the usual place.
01268  */
01269 int
01270 rt_sketch_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
01271 {
01272     struct rt_sketch_internal   *sketch_ip;
01273     unsigned char                       *cp;
01274     int                         seg_no;
01275     int                         i;
01276     vect_t                              tmp_vec;
01277 
01278     if( bu_debug&BU_DEBUG_MEM_CHECK )
01279         {
01280             bu_log( "Barrier check at start of sketch_export5():\n" );
01281             bu_mem_barriercheck();
01282         }
01283 
01284     RT_CK_DB_INTERNAL(ip);
01285     if( ip->idb_type != ID_SKETCH )  return(-1);
01286     sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
01287     RT_SKETCH_CK_MAGIC(sketch_ip);
01288 
01289     BU_CK_EXTERNAL(ep);
01290 
01291     /* tally up size of buffer needed */
01292     ep->ext_nbytes = 3 * (3 * SIZEOF_NETWORK_DOUBLE)    /* V, u_vec, v_vec */
01293         + 2 * SIZEOF_NETWORK_LONG               /* vert_count and seg_count */
01294         + 2 * sketch_ip->vert_count * SIZEOF_NETWORK_DOUBLE     /* 2D-vertices */
01295         + sketch_ip->skt_curve.seg_count * SIZEOF_NETWORK_LONG; /* reverse flags */
01296 
01297     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
01298         {
01299             long *lng;
01300             struct nurb_seg *nseg;
01301             struct bezier_seg *bseg;
01302 
01303             lng = (long *)sketch_ip->skt_curve.segments[seg_no];
01304             switch( *lng )
01305                 {
01306                     case CURVE_LSEG_MAGIC:
01307                         ep->ext_nbytes += 3 * SIZEOF_NETWORK_LONG;
01308                         break;
01309                     case CURVE_CARC_MAGIC:
01310                         ep->ext_nbytes += 5 * SIZEOF_NETWORK_LONG + SIZEOF_NETWORK_DOUBLE;
01311                         break;
01312                     case CURVE_NURB_MAGIC:
01313                         nseg = (struct nurb_seg *)lng;
01314                         ep->ext_nbytes += 3 * SIZEOF_NETWORK_LONG; /* order, pt_type, c_size */
01315                         ep->ext_nbytes +=  SIZEOF_NETWORK_LONG + nseg->k.k_size * SIZEOF_NETWORK_DOUBLE;        /* knot vector */
01316                         ep->ext_nbytes += nseg->c_size * SIZEOF_NETWORK_LONG; /* control point indices */
01317                         if( RT_NURB_IS_PT_RATIONAL( nseg->pt_type ) )
01318                             ep->ext_nbytes += nseg->c_size * SIZEOF_NETWORK_DOUBLE;     /* weights */
01319                         break;
01320                     case CURVE_BEZIER_MAGIC:
01321                         bseg = (struct bezier_seg *)lng;
01322                         ep->ext_nbytes += (bseg->degree + 3) * SIZEOF_NETWORK_LONG;
01323                         break;
01324                     default:
01325                         bu_log( "rt_sketch_export: unsupported segement type (x%x)\n", *lng );
01326                         bu_bomb( "rt_sketch_export: unsupported segement type\n" );
01327                 }
01328         }
01329     ep->ext_buf = (genptr_t)bu_malloc( ep->ext_nbytes, "sketch external");
01330 
01331     cp = (unsigned char *)ep->ext_buf;
01332 
01333     /* scale and export */
01334     VSCALE( tmp_vec, sketch_ip->V, local2mm );
01335     htond( cp, (unsigned char *)tmp_vec, 3 );
01336     cp += 3 * SIZEOF_NETWORK_DOUBLE;
01337 
01338     /* uvec and uvec are unit vectors, do not convert to/from mm */
01339     htond( cp, (unsigned char *)sketch_ip->u_vec, 3 );
01340     cp += 3 * SIZEOF_NETWORK_DOUBLE;
01341     htond( cp, (unsigned char *)sketch_ip->v_vec, 3 );
01342     cp += 3 * SIZEOF_NETWORK_DOUBLE;
01343 
01344     (void)bu_plong( cp, sketch_ip->vert_count );
01345     cp += SIZEOF_NETWORK_LONG;
01346     (void)bu_plong( cp, sketch_ip->skt_curve.seg_count );
01347     cp += SIZEOF_NETWORK_LONG;
01348 
01349     /* convert 2D points to mm */
01350     for( i=0 ; i<sketch_ip->vert_count ; i++ )
01351         {
01352             point2d_t pt2d;
01353 
01354             V2SCALE( pt2d, sketch_ip->verts[i], local2mm )
01355                 htond( cp, (const unsigned char *)pt2d, 2 );
01356             cp += 2 * SIZEOF_NETWORK_DOUBLE;
01357         }
01358 
01359     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
01360         {
01361             struct line_seg *lseg;
01362             struct carc_seg *cseg;
01363             struct nurb_seg *nseg;
01364             struct bezier_seg *bseg;
01365             long *lng;
01366             fastf_t tmp_fastf;
01367 
01368             /* write segment type ID, and segement parameters */
01369             lng = (long *)sketch_ip->skt_curve.segments[seg_no];
01370             switch (*lng )
01371                 {
01372                     case CURVE_LSEG_MAGIC:
01373                         lseg = (struct line_seg *)lng;
01374                         (void)bu_plong( cp, CURVE_LSEG_MAGIC );
01375                         cp += SIZEOF_NETWORK_LONG;
01376                         (void)bu_plong( cp, lseg->start );
01377                         cp += SIZEOF_NETWORK_LONG;
01378                         (void)bu_plong( cp, lseg->end );
01379                         cp += SIZEOF_NETWORK_LONG;
01380                         break;
01381                     case CURVE_CARC_MAGIC:
01382                         cseg = (struct carc_seg *)lng;
01383                         (void)bu_plong( cp, CURVE_CARC_MAGIC );
01384                         cp += SIZEOF_NETWORK_LONG;
01385                         (void)bu_plong( cp, cseg->start );
01386                         cp += SIZEOF_NETWORK_LONG;
01387                         (void)bu_plong( cp, cseg->end );
01388                         cp += SIZEOF_NETWORK_LONG;
01389                         (void) bu_plong( cp, cseg->orientation );
01390                         cp += SIZEOF_NETWORK_LONG;
01391                         (void) bu_plong( cp, cseg->center_is_left );
01392                         cp += SIZEOF_NETWORK_LONG;
01393                         tmp_fastf = cseg->radius * local2mm;
01394                         htond( cp, (unsigned char *)&tmp_fastf, 1 );
01395                         cp += SIZEOF_NETWORK_DOUBLE;
01396                         break;
01397                     case CURVE_NURB_MAGIC:
01398                         nseg = (struct nurb_seg *)lng;
01399                         (void)bu_plong( cp, CURVE_NURB_MAGIC );
01400                         cp += SIZEOF_NETWORK_LONG;
01401                         (void)bu_plong( cp, nseg->order );
01402                         cp += SIZEOF_NETWORK_LONG;
01403                         (void)bu_plong( cp, nseg->pt_type );
01404                         cp += SIZEOF_NETWORK_LONG;
01405                         (void)bu_plong( cp, nseg->k.k_size );
01406                         cp += SIZEOF_NETWORK_LONG;
01407                         htond( cp, (const unsigned char *)nseg->k.knots, nseg->k.k_size );
01408                         cp += nseg->k.k_size * SIZEOF_NETWORK_DOUBLE;
01409                         (void)bu_plong( cp, nseg->c_size );
01410                         cp += SIZEOF_NETWORK_LONG;
01411                         for( i=0 ; i<nseg->c_size ; i++ )
01412                             {
01413                                 (void)bu_plong( cp, nseg->ctl_points[i] );
01414                                 cp += SIZEOF_NETWORK_LONG;
01415                             }
01416                         if( RT_NURB_IS_PT_RATIONAL( nseg->pt_type ) )
01417                             {
01418                                 htond( cp, (const unsigned char *)nseg->weights, nseg->c_size );
01419                                 cp += SIZEOF_NETWORK_DOUBLE * nseg->c_size;
01420                             }
01421                         break;
01422                     case CURVE_BEZIER_MAGIC:
01423                         bseg = (struct bezier_seg *)lng;
01424                         (void)bu_plong( cp, CURVE_BEZIER_MAGIC );
01425                         cp += SIZEOF_NETWORK_LONG;
01426                         (void)bu_plong( cp, bseg->degree );
01427                         cp += SIZEOF_NETWORK_LONG;
01428                         for( i=0 ; i<=bseg->degree ; i++ ) {
01429                             (void)bu_plong( cp, bseg->ctl_points[i] );
01430                             cp += SIZEOF_NETWORK_LONG;
01431                         }
01432                         break;
01433                     default:
01434                         bu_bomb( "rt_sketch_export: ERROR: unrecognized curve type!!!!\n" );
01435                         break;
01436 
01437                 }
01438         }
01439 
01440     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
01441         {
01442             (void)bu_plong( cp, sketch_ip->skt_curve.reverse[seg_no] );
01443             cp += SIZEOF_NETWORK_LONG;
01444         }
01445 
01446     if( bu_debug&BU_DEBUG_MEM_CHECK )
01447         {
01448             bu_log( "Barrier check at end of sketch_export5():\n" );
01449             bu_mem_barriercheck();
01450         }
01451 
01452     return(0);
01453 }
01454 
01455 
01456 /**
01457  *                      R T _ S K E T C H _ D E S C R I B E
01458  *
01459  *  Make human-readable formatted presentation of this solid.
01460  *  First line describes type of solid.
01461  *  Additional lines are indented one tab, and give parameter values.
01462  */
01463 int
01464 rt_sketch_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
01465 {
01466     register struct rt_sketch_internal  *sketch_ip =
01467         (struct rt_sketch_internal *)ip->idb_ptr;
01468     int i;
01469     int seg_no;
01470     char        buf[256];
01471     point_t V;
01472     vect_t u, v;
01473 
01474     RT_SKETCH_CK_MAGIC(sketch_ip);
01475     bu_vls_strcat( str, "2D sketch (SKETCH)\n");
01476 
01477     VSCALE( V, sketch_ip->V, mm2local );
01478     VSCALE( u, sketch_ip->u_vec, mm2local );
01479     VSCALE( v, sketch_ip->v_vec, mm2local );
01480 
01481     sprintf(buf, "\tV = (%g %g %g),  A = (%g %g %g), B = (%g %g %g)\n\t%d vertices\n",
01482             V3INTCLAMPARGS( V ),
01483             V3INTCLAMPARGS( u ),
01484             V3INTCLAMPARGS( v ),
01485             sketch_ip->vert_count );
01486     bu_vls_strcat( str, buf );
01487 
01488     if( !verbose )
01489         return( 0 );
01490 
01491     if( sketch_ip->vert_count )
01492         {
01493             bu_vls_strcat( str, "\tVertices:\n\t" );
01494             for( i=0 ; i<sketch_ip->vert_count ; i++ )
01495                 {
01496                     sprintf( buf, " %d-(%g %g)", i, V2INTCLAMPARGS( sketch_ip->verts[i] ) );
01497                     bu_vls_strcat( str, buf );
01498                     if( i && (i+1)%3 == 0 )
01499                         bu_vls_strcat( str, "\n\t" );
01500                 }
01501         }
01502     bu_vls_strcat( str, "\n" );
01503 
01504     sprintf(buf, "\n\tCurve:\n" );
01505     bu_vls_strcat( str, buf );
01506     for( seg_no=0 ; seg_no < sketch_ip->skt_curve.seg_count ; seg_no++ )
01507         {
01508             struct line_seg *lsg;
01509             struct carc_seg *csg;
01510             struct nurb_seg *nsg;
01511             struct bezier_seg *bsg;
01512 
01513             lsg = (struct line_seg *)sketch_ip->skt_curve.segments[seg_no];
01514             switch( lsg->magic )
01515                 {
01516                     case CURVE_LSEG_MAGIC:
01517                         lsg = (struct line_seg *)sketch_ip->skt_curve.segments[seg_no];
01518                         if( lsg->start >= sketch_ip->vert_count ||
01519                             lsg->end >= sketch_ip->vert_count )
01520                             {
01521                                 if( sketch_ip->skt_curve.reverse[seg_no] )
01522                                     sprintf( buf, "\t\tLine segment from vertex #%d to #%d\n",
01523                                              lsg->end, lsg->start );
01524                                 else
01525                                     sprintf( buf, "\t\tLine segment from vertex #%d to #%d\n",
01526                                              lsg->start, lsg->end );
01527                             }
01528                         else
01529                             {
01530                                 if( sketch_ip->skt_curve.reverse[seg_no] )
01531                                     sprintf( buf, "\t\tLine segment (%g %g) <-> (%g %g)\n",
01532                                              V2INTCLAMPARGS( sketch_ip->verts[lsg->end] ),
01533                                              V2INTCLAMPARGS( sketch_ip->verts[lsg->start] ) );
01534                                 else
01535                                     sprintf( buf, "\t\tLine segment (%g %g) <-> (%g %g)\n",
01536                                              V2INTCLAMPARGS( sketch_ip->verts[lsg->start] ),
01537                                              V2INTCLAMPARGS( sketch_ip->verts[lsg->end] ) );
01538                             }
01539                         bu_vls_strcat( str, buf );
01540                         break;
01541                     case CURVE_CARC_MAGIC:
01542                         csg = (struct carc_seg *)sketch_ip->skt_curve.segments[seg_no];
01543                         if( csg->radius < 0.0 )
01544                             {
01545                                 bu_vls_strcat( str, "\t\tFull Circle:\n" );
01546 
01547                                 if( csg->end >= sketch_ip->vert_count ||
01548                                     csg->start >= sketch_ip->vert_count )
01549                                     {
01550                                         sprintf( buf, "\t\tcenter at vertex #%d\n",
01551                                                  csg->end );
01552                                         bu_vls_strcat( str, buf );
01553                                         sprintf( buf, "\t\tpoint on circle at vertex #%d\n",
01554                                                  csg->start );
01555                                     }
01556                                 else
01557                                     {
01558                                         sprintf( buf, "\t\t\tcenter: (%g %g)\n",
01559                                                  V2INTCLAMPARGS( sketch_ip->verts[csg->end] ) );
01560                                         bu_vls_strcat( str, buf );
01561                                         sprintf( buf, "\t\t\tpoint on circle: (%g %g)\n",
01562                                                  V2INTCLAMPARGS( sketch_ip->verts[csg->start] ) );
01563                                     }
01564                                 bu_vls_strcat( str, buf );
01565                             }
01566                         else
01567                             {
01568                                 bu_vls_strcat( str, "\t\tCircular Arc:\n" );
01569 
01570                                 if( csg->end >= sketch_ip->vert_count ||
01571                                     csg->start >= sketch_ip->vert_count )
01572                                     {
01573                                         sprintf( buf, "\t\t\tstart at vertex #%d\n",
01574                                                  csg->start );
01575                                         bu_vls_strcat( str, buf );
01576                                         sprintf( buf, "\t\t\tend at vertex #%d\n",
01577                                                  csg->end );
01578                                         bu_vls_strcat( str, buf );
01579                                     }
01580                                 else
01581                                     {
01582                                         sprintf( buf, "\t\t\tstart: (%g, %g)\n",
01583                                                  V2INTCLAMPARGS( sketch_ip->verts[csg->start] ) );
01584                                         bu_vls_strcat( str, buf );
01585                                         sprintf( buf, "\t\t\tend: (%g, %g)\n",
01586                                                  V2INTCLAMPARGS( sketch_ip->verts[csg->end] ) );
01587                                         bu_vls_strcat( str, buf );
01588                                     }
01589                                 sprintf( buf, "\t\t\tradius: %g\n", csg->radius*mm2local );
01590                                 bu_vls_strcat( str, buf );
01591                                 if( csg->orientation )
01592                                     bu_vls_strcat( str, "\t\t\tcurve is clock-wise\n" );
01593                                 else
01594                                     bu_vls_strcat( str, "\t\t\tcurve is counter-clock-wise\n" );
01595                                 if( csg->center_is_left )
01596                                     bu_vls_strcat( str, "\t\t\tcenter of curvature is left of the line from start point to end point\n" );
01597                                 else
01598                                     bu_vls_strcat( str, "\t\t\tcenter of curvature is right of the line from start point to end point\n" );
01599                                 if( sketch_ip->skt_curve.reverse[seg_no] )
01600                                     bu_vls_strcat( str, "\t\t\tarc is reversed\n" );
01601                             }
01602                         break;
01603                     case CURVE_NURB_MAGIC:
01604                         nsg = (struct nurb_seg *)sketch_ip->skt_curve.segments[seg_no];
01605                         bu_vls_strcat( str, "\t\tNURB Curve:\n" );
01606                         if( RT_NURB_IS_PT_RATIONAL( nsg->pt_type ) )
01607                             {
01608                                 sprintf( buf, "\t\t\tCurve is rational\n" );
01609                                 bu_vls_strcat( str, buf );
01610                             }
01611                         sprintf( buf, "\t\t\torder = %d, number of control points = %d\n",
01612                                  nsg->order, nsg->c_size );
01613                         bu_vls_strcat( str, buf );
01614                         if( nsg->ctl_points[0] >= sketch_ip->vert_count ||
01615                             nsg->ctl_points[nsg->c_size-1] >= sketch_ip->vert_count )
01616                             {
01617                                 if( sketch_ip->skt_curve.reverse[seg_no] )
01618                                     sprintf( buf, "\t\t\tstarts at vertex #%d\n\t\t\tends at vertex #%d\n",
01619                                              nsg->ctl_points[nsg->c_size-1],
01620                                              nsg->ctl_points[0] );
01621                                 else
01622                                     sprintf( buf, "\t\t\tstarts at vertex #%d\n\t\t\tends at vertex #%d\n",
01623                                              nsg->ctl_points[0],
01624                                              nsg->ctl_points[nsg->c_size-1] );
01625                             }
01626                         else
01627                             {
01628                                 if( sketch_ip->skt_curve.reverse[seg_no] )
01629                                     sprintf( buf, "\t\t\tstarts at (%g %g)\n\t\t\tends at (%g %g)\n",
01630                                              V2INTCLAMPARGS( sketch_ip->verts[nsg->ctl_points[nsg->c_size-1]] ),
01631                                              V2INTCLAMPARGS( sketch_ip->verts[nsg->ctl_points[0]] ) );
01632                                 else
01633                                     sprintf( buf, "\t\t\tstarts at (%g %g)\n\t\t\tends at (%g %g)\n",
01634                                              V2INTCLAMPARGS( sketch_ip->verts[nsg->ctl_points[0]] ),
01635                                              V2INTCLAMPARGS( sketch_ip->verts[nsg->ctl_points[nsg->c_size-1]] ) );
01636                             }
01637                         bu_vls_strcat( str, buf );
01638                         sprintf( buf, "\t\t\tknot values are %g to %g\n",
01639                                  INTCLAMP(nsg->k.knots[0]), INTCLAMP(nsg->k.knots[nsg->k.k_size-1]) );
01640                         bu_vls_strcat( str, buf );
01641                         break;
01642                     case CURVE_BEZIER_MAGIC:
01643                         bsg = (struct bezier_seg *)sketch_ip->skt_curve.segments[seg_no];
01644                         bu_vls_strcat( str, "\t\tBezier segment:\n" );
01645                         sprintf( buf, "\t\t\tdegree = %d\n", bsg->degree );
01646                         bu_vls_strcat( str, buf );
01647                         if( bsg->ctl_points[0] >= sketch_ip->vert_count ||
01648                             bsg->ctl_points[bsg->degree] >= sketch_ip->vert_count ) {
01649                             if( sketch_ip->skt_curve.reverse[seg_no] ){
01650                                 sprintf( buf, "\t\t\tstarts at vertex #%d\n\t\t\tends at vertex #%d\n",
01651                                          bsg->ctl_points[bsg->degree],
01652                                          bsg->ctl_points[0] );
01653                             } else {
01654                                 sprintf( buf, "\t\t\tstarts at vertex #%d\n\t\t\tends at vertex #%d\n",
01655                                          bsg->ctl_points[0],
01656                                          bsg->ctl_points[bsg->degree] );
01657                             }
01658                         } else {
01659                             if( sketch_ip->skt_curve.reverse[seg_no] )
01660                                 sprintf( buf, "\t\t\tstarts at (%g %g)\n\t\t\tends at (%g %g)\n",
01661                                          V2INTCLAMPARGS( sketch_ip->verts[bsg->ctl_points[bsg->degree]]),
01662                                          V2INTCLAMPARGS( sketch_ip->verts[bsg->ctl_points[0]] ) );
01663                             else
01664                                 sprintf( buf, "\t\t\tstarts at (%g %g)\n\t\t\tends at (%g %g)\n",
01665                                          V2INTCLAMPARGS( sketch_ip->verts[bsg->ctl_points[0]] ),
01666                                          V2INTCLAMPARGS( sketch_ip->verts[bsg->ctl_points[bsg->degree]]));
01667                         }
01668                         bu_vls_strcat( str, buf );
01669                         break;
01670                     default:
01671                         bu_bomb( "rt_sketch_describe: ERROR: unrecognized segment type\n" );
01672                 }
01673         }
01674 
01675     return(0);
01676 }
01677 
01678 void
01679 rt_curve_free(struct curve *crv)
01680 {
01681     int i;
01682 
01683     if( crv->seg_count )
01684         bu_free( (char *)crv->reverse, "crv->reverse" );
01685     for( i=0 ; i<crv->seg_count ; i++ )
01686         {
01687             long *lng;
01688             struct nurb_seg *nsg;
01689             struct bezier_seg *bsg;
01690 
01691             lng = (long *)crv->segments[i];
01692             switch( *lng )
01693                 {
01694                     case CURVE_NURB_MAGIC:
01695                         nsg = (struct nurb_seg *)lng;
01696                         bu_free( (char *)nsg->ctl_points, "nsg->ctl_points" );
01697                         if( nsg->weights )
01698                             bu_free( ( char *)nsg->weights, "nsg->weights" );
01699                         bu_free( ( char *)nsg->k.knots, "nsg->k.knots" );
01700                         bu_free( (char *)lng, "curve segment" );
01701                         break;
01702                     case CURVE_BEZIER_MAGIC:
01703                         bsg = (struct bezier_seg *)lng;
01704                         bu_free( (char *)bsg->ctl_points, "bsg->ctl_points" );
01705                         bu_free( (char *)lng, "curve segment" );
01706                         break;
01707                     case CURVE_LSEG_MAGIC:
01708                     case CURVE_CARC_MAGIC:
01709                         bu_free( (char *)lng, "curve segment" );
01710                         break;
01711                     default:
01712                         bu_log( "ERROR: rt_curve_free: unrecognized curve segments type!!!!\n");
01713                         break;
01714                 }
01715         }
01716 
01717     if( crv->seg_count > 0 )
01718         bu_free( (char *)crv->segments, "crv->segments" );
01719 
01720     crv->seg_count = 0;
01721     crv->reverse = (int *)NULL;
01722     crv->segments = (genptr_t)NULL;
01723 }
01724 
01725 
01726 /**
01727  *                      R T _ S K E T C H _ I F R E E
01728  *
01729  *  Free the storage associated with the rt_db_internal version of this solid.
01730  */
01731 void
01732 rt_sketch_ifree( struct rt_db_internal  *ip )
01733 {
01734     register struct rt_sketch_internal  *sketch_ip;
01735     struct curve                                *crv;
01736 
01737     RT_CK_DB_INTERNAL(ip);
01738     sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
01739     RT_SKETCH_CK_MAGIC(sketch_ip);
01740     sketch_ip->magic = 0;                       /* sanity */
01741 
01742     if( bu_debug&BU_DEBUG_MEM_CHECK )
01743         {
01744             bu_log( "Barrier check at start of sketch_ifree():\n" );
01745             bu_mem_barriercheck();
01746         }
01747 
01748     if( sketch_ip->verts )
01749         bu_free( (char *)sketch_ip->verts, "sketch_ip->verts" );
01750 
01751     crv = &sketch_ip->skt_curve;
01752 
01753     rt_curve_free( crv );
01754 
01755     bu_free( (char *)sketch_ip, "sketch ifree" );
01756     ip->idb_ptr = GENPTR_NULL;  /* sanity */
01757 
01758     if( bu_debug&BU_DEBUG_MEM_CHECK )
01759         {
01760             bu_log( "Barrier check at end of sketch_ifree():\n" );
01761             bu_mem_barriercheck();
01762         }
01763 
01764 }
01765 
01766 void
01767 rt_copy_curve(struct curve *crv_out, const struct curve *crv_in)
01768 {
01769     int i, j;
01770 
01771     crv_out->seg_count = crv_in->seg_count;
01772     crv_out->reverse = (int *)bu_calloc( crv_out->seg_count, sizeof( int ), "crv->reverse" );
01773     crv_out->segments = (genptr_t *)bu_calloc( crv_out->seg_count, sizeof( genptr_t ), "crv->segments" );
01774     for( j=0 ; j<crv_out->seg_count ; j++ )
01775         {
01776             long *lng;
01777             struct line_seg *lsg_out, *lsg_in;
01778             struct carc_seg *csg_out, *csg_in;
01779             struct nurb_seg *nsg_out, *nsg_in;
01780             struct bezier_seg *bsg_out, *bsg_in;
01781 
01782             crv_out->reverse[j] = crv_in->reverse[j];
01783             lng = (long *)crv_in->segments[j];
01784             switch( *lng )
01785                 {
01786                     case CURVE_LSEG_MAGIC:
01787                         lsg_in = (struct line_seg *)lng;
01788                         lsg_out = (struct line_seg *)bu_malloc( sizeof( struct line_seg ), "line_seg" );
01789                         crv_out->segments[j] = (genptr_t)lsg_out;
01790                         *lsg_out = *lsg_in;
01791                         break;
01792                     case CURVE_CARC_MAGIC:
01793                         csg_in = (struct carc_seg *)lng;
01794                         csg_out = (struct carc_seg *)bu_malloc( sizeof( struct carc_seg ), "carc_seg" );
01795                         crv_out->segments[j] = (genptr_t)csg_out;
01796                         *csg_out = *csg_in;
01797                         break;
01798                     case CURVE_NURB_MAGIC:
01799                         nsg_in = (struct nurb_seg *)lng;
01800                         nsg_out = (struct nurb_seg *)bu_malloc( sizeof( struct nurb_seg ), "nurb_seg" );
01801                         crv_out->segments[j] = (genptr_t)nsg_out;
01802                         *nsg_out = *nsg_in;
01803                         nsg_out->ctl_points = (int *)bu_calloc( nsg_in->c_size, sizeof( int ), "nsg_out->ctl_points" );
01804                         for( i=0 ; i<nsg_out->c_size ; i++ )
01805                             nsg_out->ctl_points[i] = nsg_in->ctl_points[i];
01806                         if( RT_NURB_IS_PT_RATIONAL( nsg_in->pt_type ) )
01807                             {
01808                                 nsg_out->weights = (fastf_t *)bu_malloc( nsg_out->c_size * sizeof( fastf_t ), "nsg_out->weights" );
01809                                 for( i=0 ; i<nsg_out->c_size ; i++ )
01810                                     nsg_out->weights[i] = nsg_in->weights[i];
01811                             }
01812                         else
01813                             nsg_out->weights = (fastf_t *)NULL;
01814                         nsg_out->k.knots = bu_malloc( nsg_in->k.k_size * sizeof( fastf_t ), "nsg_out->k.knots" );
01815                         for( i=0 ; i<nsg_in->k.k_size ; i++ )
01816                             nsg_out->k.knots[i] = nsg_in->k.knots[i];
01817                         break;
01818                     case CURVE_BEZIER_MAGIC:
01819                         bsg_in = (struct bezier_seg *)lng;
01820                         bsg_out = (struct bezier_seg *)bu_malloc( sizeof( struct bezier_seg ), "bezier_seg" );
01821                         crv_out->segments[j] = (genptr_t)bsg_out;
01822                         *bsg_out = *bsg_in;
01823                         bsg_out->ctl_points = (int *)bu_calloc( bsg_out->degree + 1,
01824                                                                 sizeof( int ), "bsg_out->ctl_points" );
01825                         for( i=0 ; i<=bsg_out->degree ; i++ ) {
01826                             bsg_out->ctl_points[i] = bsg_in->ctl_points[i];
01827                         }
01828                         break;
01829                     default:
01830                         bu_bomb( "rt_copy_sketch: ERROR: unrecognized segment type!!!!\n" );
01831                 }
01832         }
01833 
01834 }
01835 
01836 
01837 struct rt_sketch_internal *
01838 rt_copy_sketch(const struct rt_sketch_internal *sketch_ip)
01839 {
01840     struct rt_sketch_internal *out;
01841     int i;
01842     struct curve *crv_out;
01843 
01844     RT_SKETCH_CK_MAGIC( sketch_ip );
01845 
01846     if( bu_debug&BU_DEBUG_MEM_CHECK )
01847         {
01848             bu_log( "Barrier check at start of rt_copy_sketch():\n" );
01849             bu_mem_barriercheck();
01850         }
01851 
01852     out = (struct rt_sketch_internal *) bu_malloc( sizeof( struct rt_sketch_internal ), "rt_sketch_internal" );
01853     *out = *sketch_ip;  /* struct copy */
01854 
01855     out->verts = (point2d_t *)bu_calloc( out->vert_count, sizeof( point2d_t ), "out->verts" );
01856     for( i=0 ; i<out->vert_count ; i++ )
01857         V2MOVE( out->verts[i], sketch_ip->verts[i] );
01858 
01859     crv_out = &out->skt_curve;
01860     rt_copy_curve( crv_out, &sketch_ip->skt_curve );
01861 
01862     if( bu_debug&BU_DEBUG_MEM_CHECK )
01863         {
01864             bu_log( "Barrier check at end of rt_copy_sketch():\n" );
01865             bu_mem_barriercheck();
01866         }
01867 
01868     return( out );
01869 }
01870 
01871 
01872 int
01873 curve_to_tcl_list(struct bu_vls *vls, struct curve *crv)
01874 {
01875     int i,j;
01876 
01877     bu_vls_printf( vls, " SL {" );
01878     for( j=0 ; j<crv->seg_count ; j++ )
01879         {
01880             switch( (*(long *)crv->segments[j]) )
01881                 {
01882                     case CURVE_LSEG_MAGIC:
01883                         {
01884                             struct line_seg *lsg = (struct line_seg *)crv->segments[j];
01885                             bu_vls_printf( vls, " { line S %d E %d }", lsg->start, lsg->end );
01886                         }
01887                         break;
01888                     case CURVE_CARC_MAGIC:
01889                         {
01890                             struct carc_seg *csg = (struct carc_seg *)crv->segments[j];
01891                             bu_vls_printf( vls, " { carc S %d E %d R %.25g L %d O %d }",
01892                                            csg->start, csg->end, csg->radius,
01893                                            csg->center_is_left, csg->orientation );
01894                         }
01895                         break;
01896                     case CURVE_BEZIER_MAGIC:
01897                         {
01898                             struct bezier_seg *bsg = (struct bezier_seg *)crv->segments[j];
01899                             bu_vls_printf( vls, " { bezier D %d P {", bsg->degree );
01900                             for( i=0 ; i<=bsg->degree ; i++ )
01901                                 bu_vls_printf( vls, " %d", bsg->ctl_points[i] );
01902                             bu_vls_printf( vls, " } }" );
01903                         }
01904                         break;
01905                     case CURVE_NURB_MAGIC:
01906                         {
01907                             int k;
01908                             struct nurb_seg *nsg = (struct nurb_seg *)crv->segments[j];
01909                             bu_vls_printf( vls, " { nurb O %d T %d K {",
01910                                            nsg->order, nsg->pt_type );
01911                             for( k=0 ; k<nsg->k.k_size ; k++ )
01912                                 bu_vls_printf( vls, " %.25g", nsg->k.knots[k] );
01913                             bu_vls_strcat( vls, "} P {" );
01914                             for( k=0 ; k<nsg->c_size ; k++ )
01915                                 bu_vls_printf( vls, " %d", nsg->ctl_points[k] );
01916                             if( nsg->weights )
01917                                 {
01918                                     bu_vls_strcat( vls, "} W {" );
01919                                     for( k=0 ; k<nsg->c_size ; k++ )
01920                                         bu_vls_printf( vls, " %.25g", nsg->weights[k] );
01921                                 }
01922                             bu_vls_strcat( vls, "} }" );
01923                         }
01924                         break;
01925                 }
01926         }
01927     bu_vls_strcat( vls, " }" ); /* end of segment list */
01928 
01929     return( 0 );
01930 }
01931 
01932 
01933 int rt_sketch_tclform( const struct rt_functab *ftp, Tcl_Interp *interp)
01934 {
01935     RT_CK_FUNCTAB(ftp);
01936 
01937     Tcl_AppendResult( interp,
01938                       "V {%f %f %f} A {%f %f %f} B {%f %f %f} VL { {%f %f} {%f %f} ...} SL { { segment_data } { segment_data} }" );
01939 
01940     return TCL_OK;
01941 }
01942 
01943 
01944 int
01945 rt_sketch_tclget(Tcl_Interp *interp, const struct rt_db_internal *intern, const char *attr)
01946 {
01947     register struct rt_sketch_internal *skt=(struct rt_sketch_internal *)intern->idb_ptr;
01948     Tcl_DString     ds;
01949     struct bu_vls   vls;
01950     int i;
01951     struct curve        *crv;
01952 
01953     RT_SKETCH_CK_MAGIC( skt );
01954 
01955     Tcl_DStringInit( &ds );
01956     bu_vls_init( &vls );
01957 
01958     if( attr == (char *)NULL )
01959         {
01960             bu_vls_strcpy( &vls, "sketch" );
01961             bu_vls_printf( &vls, " V {%.25g %.25g %.25g}", V3ARGS( skt->V ) );
01962             bu_vls_printf( &vls, " A {%.25g %.25g %.25g}", V3ARGS( skt->u_vec ) );
01963             bu_vls_printf( &vls, " B {%.25g %.25g %.25g}", V3ARGS( skt->v_vec ) );
01964             bu_vls_strcat( &vls, " VL {" );
01965             for( i=0 ; i<skt->vert_count ; i++ )
01966                 bu_vls_printf( &vls, " {%.25g %.25g}", V2ARGS( skt->verts[i] ) );
01967             bu_vls_strcat( &vls, " }" );
01968 
01969             crv = &skt->skt_curve;
01970             if( curve_to_tcl_list( &vls, crv ) )
01971                 {
01972                     bu_vls_free( &vls );
01973                     return( TCL_ERROR );
01974                 }
01975         }
01976     else if( !strcmp( attr, "V" ) )
01977         bu_vls_printf( &vls, "%.25g %.25g %.25g", V3ARGS( skt->V ) );
01978     else if( !strcmp( attr, "A" ) )
01979         bu_vls_printf( &vls, "%.25g %.25g %.25g", V3ARGS( skt->u_vec ) );
01980     else if( !strcmp( attr, "B" ) )
01981         bu_vls_printf( &vls, "%.25g %.25g %.25g", V3ARGS( skt->v_vec ) );
01982     else if( !strcmp( attr, "VL" ) )
01983         {
01984             for( i=0 ; i<skt->vert_count ; i++ )
01985                 bu_vls_printf( &vls, " {%.25g %.25g}", V2ARGS( skt->verts[i] ) );
01986         }
01987     else if( !strcmp( attr, "SL" ) )
01988         {
01989             crv = &skt->skt_curve;
01990             if( curve_to_tcl_list( &vls, crv ) )
01991                 {
01992                     bu_vls_free( &vls );
01993                     return( TCL_ERROR );
01994                 }
01995         }
01996     else if( *attr == 'V' )
01997         {
01998             i = atoi( (attr+1) );
01999             if( i < 0 || i >= skt->vert_count )
02000                 {
02001                     Tcl_SetResult( interp, "ERROR: Illegal vertex number\n", TCL_STATIC );
02002                     bu_vls_free( &vls );
02003                     return( TCL_ERROR );
02004                 }
02005 
02006             bu_vls_printf( &vls, "%.25g %.25g", V2ARGS( skt->verts[i] ) );
02007         }
02008     else        /* unrecognized attribute */
02009         {
02010             Tcl_SetResult( interp, "ERROR: Unknown attribute, choices are V, A, B, VL, SL, or V#\n", TCL_STATIC );
02011             bu_vls_free( &vls );
02012             return( TCL_ERROR );
02013         }
02014 
02015     Tcl_DStringAppend( &ds, bu_vls_addr( &vls ), -1 );
02016     Tcl_DStringResult( interp, &ds );
02017     Tcl_DStringFree( &ds );
02018     bu_vls_free( &vls );
02019     return( TCL_OK );
02020 }
02021 
02022 
02023 int
02024 get_tcl_curve(Tcl_Interp *interp, struct curve *crv, Tcl_Obj *seg_list)
02025 {
02026     int seg_count;
02027     int ret, j;
02028 
02029     /* get number of segments */
02030     seg_count = 0;
02031     if( (ret=Tcl_ListObjLength( interp, seg_list, &seg_count ) ))
02032         {
02033             return( ret );
02034         }
02035 
02036     if( seg_count )
02037         {
02038             crv->seg_count = seg_count;
02039             crv->reverse = (int *)bu_calloc( seg_count, sizeof( int ), "crv->reverse" );
02040             crv->segments = (genptr_t *)bu_calloc( seg_count, sizeof( genptr_t ), "crv->segments" );
02041         }
02042 
02043     /* loop through all the segments */
02044     for( j=0 ; j<seg_count ; j++ )
02045         {
02046             Tcl_Obj *seg, *seg_type, *seg_elem, *seg_val;
02047             char *type, *elem;
02048             int k, seg_len;
02049 
02050 
02051             /* get the next segment */
02052             if( (ret=Tcl_ListObjIndex( interp, seg_list, j, &seg ) ))
02053                 {
02054                     return( ret );
02055                 }
02056 
02057             if( (ret=Tcl_ListObjLength( interp, seg, &seg_len )) )
02058                 return( ret );
02059 
02060             /* get the segment type */
02061             if( (ret=Tcl_ListObjIndex( interp, seg, 0, &seg_type ) ))
02062                 return( ret );
02063             type = Tcl_GetString( seg_type );
02064 
02065             if( !strcmp( type, "line" ) )
02066                 {
02067                     struct line_seg *lsg;
02068 
02069                     lsg = (struct line_seg *)bu_calloc( 1, sizeof( struct line_seg ), "lsg" );
02070                     for( k=1 ; k<seg_len ; k += 2 )
02071                         {
02072                             if( (ret=Tcl_ListObjIndex( interp, seg, k, &seg_elem ) ))
02073                                 return( ret );
02074 
02075                             if( (ret=Tcl_ListObjIndex( interp, seg, k+1, &seg_val ) ))
02076                                 return( ret );
02077 
02078                             elem = Tcl_GetString( seg_elem );
02079                             switch( *elem )
02080                                 {
02081                                     case 'S':
02082                                         Tcl_GetIntFromObj( interp, seg_val, &lsg->start );
02083                                         break;
02084                                     case 'E':
02085                                         Tcl_GetIntFromObj( interp, seg_val, &lsg->end );
02086                                         break;
02087                                 }
02088                         }
02089                     lsg->magic = CURVE_LSEG_MAGIC;
02090                     crv->segments[j] = (genptr_t)lsg;
02091                 }
02092             else if( !strcmp( type, "bezier" ) )
02093                 {
02094                     struct bezier_seg *bsg;
02095                     int num_points;
02096 
02097                     bsg = (struct bezier_seg *)bu_calloc( 1, sizeof( struct bezier_seg ), "bsg" );
02098                     for( k=1 ; k<seg_len ; k+= 2 ) {
02099 
02100                         if( (ret=Tcl_ListObjIndex( interp, seg, k, &seg_elem ) ))
02101                             return( ret );
02102 
02103                         if( (ret=Tcl_ListObjIndex( interp, seg, k+1, &seg_val ) ))
02104                             return( ret );
02105 
02106                         elem = Tcl_GetString( seg_elem );
02107                         switch( *elem )
02108                             {
02109                                 case 'D': /* degree */
02110                                     Tcl_GetIntFromObj( interp, seg_val,
02111                                                        &bsg->degree );
02112                                     break;
02113                                 case 'P': /* list of control points */
02114                                     num_points = 0;
02115                                     (void)tcl_obj_to_int_array( interp,
02116                                                                 seg_val, &bsg->ctl_points,
02117                                                                 &num_points );
02118 
02119                                     if( num_points != bsg->degree + 1 ) {
02120                                         Tcl_SetResult( interp, "ERROR: degree and number of control points disagree for a Bezier segment\n", TCL_STATIC );
02121                                         return( TCL_ERROR );
02122                                     }
02123                             }
02124                     }
02125                     bsg->magic = CURVE_BEZIER_MAGIC;
02126                     crv->segments[j] = (genptr_t)bsg;
02127                 }
02128             else if( !strcmp( type, "carc" ) )
02129                 {
02130                     struct carc_seg *csg;
02131                     double tmp;
02132 
02133                     csg = (struct carc_seg *)bu_calloc( 1, sizeof( struct carc_seg ), "csg" );
02134                     for( k=1 ; k<seg_len ; k += 2 )
02135                         {
02136                             if( (ret=Tcl_ListObjIndex( interp, seg, k, &seg_elem ) ))
02137                                 return( ret );
02138 
02139                             if( (ret=Tcl_ListObjIndex( interp, seg, k+1, &seg_val ) ))
02140                                 return( ret );
02141 
02142                             elem = Tcl_GetString( seg_elem );
02143                             switch( *elem )
02144                                 {
02145                                     case 'S':
02146                                         Tcl_GetIntFromObj( interp, seg_val, &csg->start );
02147                                         break;
02148                                     case 'E':
02149                                         Tcl_GetIntFromObj( interp, seg_val, &csg->end );
02150                                         break;
02151                                     case 'R':
02152                                         Tcl_GetDoubleFromObj( interp, seg_val, &tmp );
02153                                         csg->radius = tmp;
02154                                         break;
02155                                     case 'L' :
02156                                         Tcl_GetBooleanFromObj( interp, seg_val, &csg->center_is_left );
02157                                         break;
02158                                     case 'O':
02159                                         Tcl_GetBooleanFromObj( interp, seg_val, &csg->orientation );
02160                                         break;
02161                                 }
02162                         }
02163                     csg->magic = CURVE_CARC_MAGIC;
02164                     crv->segments[j] = (genptr_t)csg;
02165                 }
02166             else if( !strcmp( type, "nurb" ) )
02167                 {
02168                     struct nurb_seg *nsg;
02169 
02170                     nsg = (struct nurb_seg *)bu_calloc( 1, sizeof( struct nurb_seg ), "nsg" );
02171                     for( k=1 ; k<seg_len ; k += 2 )
02172                         {
02173                             if( (ret=Tcl_ListObjIndex( interp, seg, k, &seg_elem ) ))
02174                                 return( ret );
02175 
02176                             if( (ret=Tcl_ListObjIndex( interp, seg, k+1, &seg_val ) ))
02177                                 return( ret );
02178 
02179                             elem = Tcl_GetString( seg_elem );
02180                             switch( *elem )
02181                                 {
02182                                     case 'O':
02183                                         Tcl_GetIntFromObj( interp, seg_val, &nsg->order );
02184                                         break;
02185                                     case 'T':
02186                                         Tcl_GetIntFromObj( interp, seg_val, &nsg->pt_type );
02187                                         break;
02188                                     case 'K':
02189                                         tcl_obj_to_fastf_array( interp, seg_val, &nsg->k.knots, &nsg->k.k_size );
02190                                         break;
02191                                     case 'P' :
02192                                         tcl_obj_to_int_array( interp, seg_val, &nsg->ctl_points, &nsg->c_size );
02193                                         break;
02194                                     case 'W':
02195                                         tcl_obj_to_fastf_array( interp, seg_val, &nsg->weights, &nsg->c_size );
02196                                         break;
02197                                 }
02198                         }
02199                     nsg->magic = CURVE_NURB_MAGIC;
02200                     crv->segments[j] = (genptr_t)nsg;
02201                 }
02202             else
02203                 {
02204                     Tcl_ResetResult( interp );
02205                     Tcl_AppendResult( interp, "ERROR: Unrecognized segment type: ",
02206                                       Tcl_GetString( seg ), (char *)NULL);
02207                     return( TCL_ERROR );
02208                 }
02209         }
02210 
02211     return( TCL_OK );
02212 }
02213 
02214 
02215 int
02216 rt_sketch_tcladjust(Tcl_Interp *interp, struct rt_db_internal *intern, int argc, char **argv)
02217 {
02218     struct rt_sketch_internal *skt;
02219     int ret, array_len;
02220     fastf_t *new;
02221 
02222     RT_CK_DB_INTERNAL( intern );
02223     skt = (struct rt_sketch_internal *)intern->idb_ptr;
02224     RT_SKETCH_CK_MAGIC( skt );
02225 
02226     while( argc >= 2 )
02227         {
02228             if( !strcmp( argv[0], "V" ) )
02229                 {
02230                     new = skt->V;
02231                     array_len = 3;
02232                     if( tcl_list_to_fastf_array( interp, argv[1], &new, &array_len) !=
02233                         array_len ) {
02234                         Tcl_SetResult( interp,
02235                                        "ERROR: Incorrect number of coordinates for vertex\n",
02236                                        TCL_STATIC );
02237                         return( TCL_ERROR );
02238                     }
02239                 }
02240             else if( !strcmp( argv[0], "A" ) )
02241                 {
02242                     new = skt->u_vec;
02243                     array_len = 3;
02244                     if( tcl_list_to_fastf_array( interp, argv[1], &new, &array_len) !=
02245                         array_len ) {
02246                         Tcl_SetResult( interp,
02247                                        "ERROR: Incorrect number of coordinates for vertex\n",
02248                                        TCL_STATIC );
02249                         return( TCL_ERROR );
02250                     }
02251                 }
02252             else if( !strcmp( argv[0], "B" ) )
02253                 {
02254                     new = skt->v_vec;
02255                     array_len = 3;
02256                     if( tcl_list_to_fastf_array( interp, argv[1], &new, &array_len) !=
02257                         array_len ) {
02258                         Tcl_SetResult( interp,
02259                                        "ERROR: Incorrect number of coordinates for vertex\n",
02260                                        TCL_STATIC );
02261                         return( TCL_ERROR );
02262                     }
02263                 }
02264             else if( !strcmp( argv[0], "VL" ) )
02265                 {
02266                     fastf_t *new_verts=(fastf_t *)NULL;
02267                     int len;
02268                     char *ptr;
02269 
02270                     /* the vertex list is a list of lists (each element is a list of two coordinates)
02271                      * so eliminate all the '{' and '}' chars in the list
02272                      */
02273                     ptr = argv[1];
02274                     while( *ptr != '\0' )
02275                         {
02276                             if( *ptr == '{' || *ptr == '}' )
02277                                 *ptr = ' ';
02278                             ptr++;
02279                         }
02280 
02281                     len = 0;
02282                     (void)tcl_list_to_fastf_array( interp, argv[1], &new_verts, &len );
02283                     if( len%2 ) {
02284                         Tcl_SetResult( interp,
02285                                        "ERROR: Incorrect number of coordinates for vertices\n",
02286                                        TCL_STATIC );
02287                         return( TCL_ERROR );
02288                     }
02289 
02290                     if( skt->verts )
02291                         bu_free( (char *)skt->verts, "verts" );
02292                     skt->verts = (point2d_t *)new_verts;
02293                     skt->vert_count = len / 2;
02294                 }
02295             else if( !strcmp( argv[0], "SL" ) ) /* the entire segment list */
02296                 {
02297                     Tcl_Obj *tmp;
02298                     struct curve *crv;
02299 
02300                     /* create a Tcl object */
02301                     tmp = Tcl_NewStringObj( argv[1], -1 );
02302 
02303                     crv = &skt->skt_curve;
02304                     crv->seg_count = 0;
02305                     crv->reverse = (int *)NULL;
02306                     crv->segments = (genptr_t)NULL;
02307 
02308                     if( (ret=get_tcl_curve( interp, crv, tmp )) != TCL_OK )
02309                         return( ret );
02310                 }
02311             else if( *argv[0] == 'V' && isdigit( *(argv[0]+1) )  )
02312                 {
02313                     /* changing a specific vertex */
02314                     int vert_no;
02315                     fastf_t *new_vert;
02316 
02317                     vert_no = atoi( argv[0] + 1 );
02318                     new_vert = skt->verts[vert_no];
02319                     if( vert_no < 0 || vert_no > skt->vert_count )
02320                         {
02321                             Tcl_SetResult( interp, "ERROR: Illegal vertex number\n",
02322                                            TCL_STATIC );
02323                             return( TCL_ERROR );
02324                         }
02325                     array_len = 2;
02326                     if(tcl_list_to_fastf_array( interp, argv[1], &new_vert, &array_len)
02327                        != array_len )
02328                         {
02329                             Tcl_SetResult( interp,
02330                                            "ERROR: Incorrect number of coordinates for vertex\n",
02331                                            TCL_STATIC );
02332                             return( TCL_ERROR );
02333                         }
02334                 }
02335 
02336             argc -= 2;
02337             argv += 2;
02338         }
02339 
02340     return( TCL_OK );
02341 }
02342 
02343 
02344 void
02345 rt_curve_reverse_segment( long *lng )
02346 {
02347     struct line_seg *lsg;
02348     struct carc_seg *csg;
02349     struct bezier_seg *bsg;
02350     int tmp, i;
02351 
02352     switch( *lng ) {
02353         case CURVE_LSEG_MAGIC:
02354             lsg = (struct line_seg *)lng;
02355             tmp = lsg->start;
02356             lsg->start = lsg->end;
02357             lsg->end = tmp;
02358             break;
02359         case CURVE_CARC_MAGIC:
02360             csg = (struct carc_seg *)lng;
02361             if( csg->radius < 0.0 ) {
02362                 /* this is a full circle */
02363                 csg->orientation = !csg->orientation; /* no real effect, but just for completeness */
02364             } else {
02365                 tmp = csg->start;
02366                 csg->start = csg->end;
02367                 csg->end = tmp;
02368                 csg->center_is_left = !csg->center_is_left;
02369                 csg->orientation = !csg->orientation;
02370             }
02371             break;
02372         case CURVE_BEZIER_MAGIC:
02373             bsg = (struct bezier_seg *)lng;
02374             for( i=0 ; i<bsg->degree/2 ; i++ ) {
02375                 tmp = bsg->ctl_points[i];
02376                 bsg->ctl_points[i] = bsg->ctl_points[bsg->degree-i];
02377                 bsg->ctl_points[bsg->degree-i] = tmp;
02378             }
02379             break;
02380     }
02381 }
02382 
02383 
02384 void
02385 rt_curve_order_segments( struct curve *crv )
02386 {
02387     int i, j, k;
02388     int seg_count;
02389     int start1, end1, start2, end2, start3, end3;
02390 
02391     seg_count = crv->seg_count;
02392     if( seg_count < 2 ) {
02393         return;
02394     }
02395 
02396     for( j=1 ; j<seg_count ; j++ ) {
02397         i = j - 1;
02398 
02399         get_indices( crv->segments[i], &start1, &end1 );
02400         get_indices( crv->segments[j], &start2, &end2 );
02401 
02402         if( end1 != start2 ) {
02403             int fixed=0;
02404 
02405             for( k=j+1 ; k<seg_count ; k++ ) {
02406                 get_indices( crv->segments[k], &start3, &end3 );
02407                 if( start3 == end1 ) {
02408                     int tmp_reverse;
02409                     genptr_t tmp_seg;
02410 
02411                     /* exchange j and k segments */
02412                     tmp_seg = crv->segments[j];
02413                     crv->segments[j] = crv->segments[k];
02414                     crv->segments[k] = tmp_seg;
02415 
02416                     tmp_reverse = crv->reverse[j];
02417                     crv->reverse[j] = crv->reverse[k];
02418                     crv->reverse[k] = tmp_reverse;
02419                     fixed = 1;
02420                     break;
02421                 }
02422             }
02423             if( !fixed ) {
02424                 /* try reversing a segment */
02425                 for( k=j ; k<seg_count ; k++ ) {
02426                     get_indices( crv->segments[k], &start3, &end3 );
02427                     if( end3 == end1 ) {
02428                         int tmp_reverse;
02429                         genptr_t tmp_seg;
02430 
02431                         rt_curve_reverse_segment( crv->segments[k] );
02432 
02433                         if( k != j ) {
02434                             /* exchange j and k segments */
02435                             tmp_seg = crv->segments[j];
02436                             crv->segments[j] = crv->segments[k];
02437                             crv->segments[k] = tmp_seg;
02438 
02439                             tmp_reverse = crv->reverse[j];
02440                             crv->reverse[j] = crv->reverse[k];
02441                             crv->reverse[k] = tmp_reverse;
02442                         }
02443                         fixed = 1;
02444                         break;
02445                     }
02446                 }
02447             }
02448         }
02449     }
02450 }
02451 
02452 
02453 /*
02454  * Local Variables:
02455  * mode: C
02456  * tab-width: 8
02457  * c-basic-offset: 4
02458  * indent-tabs-mode: t
02459  * End:
02460  * ex: shiftwidth=4 tabstop=8
02461  */

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