00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #ifndef lint
00042 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/db_scan.c,v 14.12 2006/09/16 02:04:24 lbutler Exp $ (ARL)";
00043 #endif
00044
00045 #include "common.h"
00046
00047
00048
00049 #include <stdio.h>
00050 #ifdef HAVE_STRING_H
00051 #include <string.h>
00052 #else
00053 #include <strings.h>
00054 #endif
00055
00056 #include "machine.h"
00057 #include "vmath.h"
00058 #include "db.h"
00059 #include "raytrace.h"
00060
00061 #include "./debug.h"
00062
00063 #define DEBUG_PR(aaa, rrr) {\
00064 if(RT_G_DEBUG&DEBUG_DB) bu_log("db_scan x%x %c (0%o)\n", \
00065 aaa,rrr.u_id,rrr.u_id ); }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 int
00095 db_scan(register struct db_i *dbip, int (*handler) (struct db_i *, const char *, long int, int, int, genptr_t), int do_old_matter, genptr_t client_data)
00096
00097
00098
00099
00100 {
00101 union record record;
00102 union record rec2;
00103 register long addr;
00104 register long here;
00105 register long next;
00106 register int nrec;
00107 register int totrec;
00108 register int j;
00109
00110 RT_CK_DBI(dbip);
00111 if(RT_G_DEBUG&DEBUG_DB) bu_log("db_scan( x%x, x%x )\n", dbip, handler);
00112
00113
00114
00115 rewind( dbip->dbi_fp );
00116 if( fread( (char *)&record, sizeof record, 1, dbip->dbi_fp ) != 1 ||
00117 record.u_id != ID_IDENT ) {
00118 bu_log("db_scan ERROR: File is lacking a proper MGED database header\n");
00119 return(-1);
00120 }
00121 rewind( dbip->dbi_fp );
00122 next = ftell(dbip->dbi_fp);
00123
00124 here = addr = -1L;
00125 totrec = 0;
00126 while(1) {
00127 nrec = 0;
00128 if( fseek(dbip->dbi_fp, next, 0) != 0 ) {
00129 bu_log("db_scan: fseek(offset=%d) failure\n", next);
00130 return(-1);
00131 }
00132 addr = next;
00133
00134 if( fread( (char *)&record, sizeof record, 1, dbip->dbi_fp ) != 1
00135 || feof(dbip->dbi_fp) )
00136 break;
00137 next = ftell(dbip->dbi_fp);
00138 DEBUG_PR( addr, record );
00139
00140 nrec++;
00141 switch( record.u_id ) {
00142 case ID_IDENT:
00143 if( strcmp( record.i.i_version, ID_VERSION) != 0 ) {
00144 bu_log("db_scan WARNING: File is Version %s, Program is version %s\n",
00145 record.i.i_version, ID_VERSION );
00146 }
00147
00148 if( dbip->dbi_title == (char *)0 ) {
00149 dbip->dbi_title = bu_strdup( record.i.i_title );
00150 db_conversions( dbip, record.i.i_units );
00151 }
00152 break;
00153 case ID_FREE:
00154
00155 rt_memfree( &(dbip->dbi_freep), (unsigned)1,
00156 addr/sizeof(union record) );
00157 break;
00158 case ID_ARS_A:
00159 while(1) {
00160 here = ftell( dbip->dbi_fp );
00161 if( fread( (char *)&rec2, sizeof(rec2),
00162 1, dbip->dbi_fp ) != 1 )
00163 break;
00164 DEBUG_PR( here, rec2 );
00165 if( rec2.u_id != ID_ARS_B ) {
00166 fseek( dbip->dbi_fp, here, 0 );
00167 break;
00168 }
00169 nrec++;
00170 }
00171 next = ftell(dbip->dbi_fp);
00172 handler( dbip, record.a.a_name, addr, nrec,
00173 DIR_SOLID, client_data );
00174 break;
00175 case ID_ARS_B:
00176 bu_log("db_scan ERROR: Unattached ARS 'B' record\n");
00177 break;
00178 case ID_SOLID:
00179 handler( dbip, record.s.s_name, addr, nrec,
00180 DIR_SOLID, client_data );
00181 break;
00182 case DBID_STRSOL:
00183 for( ; nrec < DB_SS_NGRAN; nrec++ ) {
00184 if( fread( (char *)&rec2, sizeof(rec2),
00185 1, dbip->dbi_fp ) != 1 )
00186 break;
00187 }
00188 next = ftell(dbip->dbi_fp);
00189 handler( dbip, record.ss.ss_name, addr, nrec,
00190 DIR_SOLID, client_data );
00191 break;
00192 case ID_MATERIAL:
00193 if( do_old_matter ) {
00194
00195 rt_color_addrec(
00196 record.md.md_low,
00197 record.md.md_hi,
00198 record.md.md_r,
00199 record.md.md_g,
00200 record.md.md_b,
00201 addr );
00202 }
00203 break;
00204 case ID_P_HEAD:
00205 while(1) {
00206 here = ftell( dbip->dbi_fp );
00207 if( fread( (char *)&rec2, sizeof(rec2),
00208 1, dbip->dbi_fp ) != 1 )
00209 break;
00210 DEBUG_PR( here, rec2 );
00211 if( rec2.u_id != ID_P_DATA ) {
00212 fseek( dbip->dbi_fp, here, 0 );
00213 break;
00214 }
00215 nrec++;
00216 }
00217 next = ftell(dbip->dbi_fp);
00218 handler( dbip, record.p.p_name, addr, nrec,
00219 DIR_SOLID, client_data );
00220 break;
00221 case ID_P_DATA:
00222 bu_log("db_scan ERROR: Unattached P_DATA record\n");
00223 break;
00224 case ID_BSOLID:
00225 while(1) {
00226
00227 here = ftell( dbip->dbi_fp );
00228 if( fread( (char *)&rec2, sizeof(rec2),
00229 1, dbip->dbi_fp ) != 1 )
00230 break;
00231 DEBUG_PR( here, rec2 );
00232 if( rec2.u_id != ID_BSURF ) {
00233 fseek( dbip->dbi_fp, here, 0 );
00234 break;
00235 }
00236
00237
00238 j = (rec2.d.d_nknots + rec2.d.d_nctls);
00239 nrec += j+1;
00240 while( j-- > 0 )
00241 fread( (char *)&rec2, sizeof(rec2), 1, dbip->dbi_fp );
00242 next = ftell(dbip->dbi_fp);
00243 }
00244 handler( dbip, record.B.B_name, addr, nrec,
00245 DIR_SOLID, client_data );
00246 break;
00247 case ID_BSURF:
00248 bu_log("db_scan ERROR: Unattached B-spline surface record\n");
00249
00250
00251 j = (record.d.d_nknots + record.d.d_nctls);
00252 nrec += j;
00253 while( j-- > 0 )
00254 fread( (char *)&rec2, sizeof(rec2), 1, dbip->dbi_fp );
00255 break;
00256 case DBID_ARBN:
00257 j = bu_glong(record.n.n_grans);
00258 nrec += j;
00259 while( j-- > 0 )
00260 fread( (char *)&rec2, sizeof(rec2), 1, dbip->dbi_fp );
00261 next = ftell(dbip->dbi_fp);
00262 handler( dbip, record.n.n_name, addr, nrec,
00263 DIR_SOLID, client_data );
00264 break;
00265 case DBID_PARTICLE:
00266 handler( dbip, record.part.p_name, addr, nrec,
00267 DIR_SOLID, client_data );
00268 break;
00269 case DBID_PIPE:
00270 j = bu_glong(record.pwr.pwr_count);
00271 nrec += j;
00272 while( j-- > 0 )
00273 fread( (char *)&rec2, sizeof(rec2), 1, dbip->dbi_fp );
00274 next = ftell(dbip->dbi_fp);
00275 handler( dbip, record.pwr.pwr_name, addr, nrec,
00276 DIR_SOLID, client_data );
00277 break;
00278 case DBID_NMG:
00279 j = bu_glong(record.nmg.N_count);
00280 nrec += j;
00281 while( j-- > 0 )
00282 (void)fread( (char *)&rec2, sizeof(rec2), 1, dbip->dbi_fp );
00283 next = ftell(dbip->dbi_fp);
00284 handler( dbip, record.nmg.N_name, addr, nrec,
00285 DIR_SOLID, client_data );
00286 break;
00287 case DBID_SKETCH:
00288 j = bu_glong(record.skt.skt_count);
00289 nrec += j;
00290 while( j-- > 0 )
00291 (void)fread( (char *)&rec2, sizeof(rec2), 1, dbip->dbi_fp );
00292 next = ftell(dbip->dbi_fp);
00293 handler( dbip, record.skt.skt_name, addr, nrec,
00294 DIR_SOLID, client_data );
00295 break;
00296 case DBID_EXTR:
00297 j = bu_glong(record.extr.ex_count);
00298 nrec += j;
00299 while( j-- > 0 )
00300 (void)fread( (char *)&rec2, sizeof(rec2), 1, dbip->dbi_fp );
00301 next = ftell(dbip->dbi_fp);
00302 handler( dbip, record.extr.ex_name, addr, nrec,
00303 DIR_SOLID, client_data );
00304 break;
00305 case DBID_CLINE:
00306 handler( dbip, record.s.s_name, addr, nrec,
00307 DIR_SOLID, client_data );
00308 break;
00309 case DBID_BOT:
00310 j = bu_glong( record.bot.bot_nrec );
00311 nrec += j;
00312 while( j-- > 0 )
00313 (void)fread( (char *)&rec2, sizeof(rec2), 1, dbip->dbi_fp );
00314 next = ftell(dbip->dbi_fp);
00315 handler( dbip, record.s.s_name, addr, nrec,
00316 DIR_SOLID, client_data );
00317 break;
00318 case ID_MEMB:
00319 bu_log("db_scan ERROR: Unattached combination MEMBER record\n");
00320 break;
00321 case ID_COMB:
00322 while(1) {
00323 here = ftell( dbip->dbi_fp );
00324 if( fread( (char *)&rec2, sizeof(rec2),
00325 1, dbip->dbi_fp ) != 1 )
00326 break;
00327 DEBUG_PR( here, rec2 );
00328 if( rec2.u_id != ID_MEMB ) {
00329 fseek( dbip->dbi_fp, here, 0 );
00330 break;
00331 }
00332 nrec++;
00333 }
00334 next = ftell(dbip->dbi_fp);
00335 switch(record.c.c_flags) {
00336 default:
00337 case DBV4_NON_REGION:
00338 j = DIR_COMB;
00339 break;
00340 case DBV4_REGION:
00341 case DBV4_REGION_FASTGEN_PLATE:
00342 case DBV4_REGION_FASTGEN_VOLUME:
00343 j = DIR_COMB|DIR_REGION;
00344 break;
00345 }
00346 handler( dbip, record.c.c_name, addr, nrec, j,
00347 client_data );
00348 break;
00349 default:
00350 bu_log("db_scan ERROR: bad record %c (0%o), addr=x%x\n",
00351 record.u_id, record.u_id, addr );
00352
00353 break;
00354 }
00355 totrec += nrec;
00356 }
00357 dbip->dbi_nrec = totrec;
00358 dbip->dbi_eof = ftell( dbip->dbi_fp );
00359 rewind( dbip->dbi_fp );
00360
00361 return( 0 );
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 int
00374 db_update_ident( struct db_i *dbip, const char *new_title, double local2mm )
00375 {
00376 struct directory dir;
00377 union record rec;
00378 char *old_title;
00379 int v4units;
00380
00381 RT_CK_DBI(dbip);
00382 if(RT_G_DEBUG&DEBUG_DB) bu_log("db_update_ident( x%x, '%s', %g )\n",
00383 dbip, new_title, local2mm );
00384
00385 BU_ASSERT_LONG( dbip->dbi_version, >, 0 );
00386
00387 if( dbip->dbi_read_only )
00388 return(-1);
00389
00390 if( dbip->dbi_version > 4 ) return db5_update_ident( dbip, new_title, local2mm );
00391
00392 RT_DIR_SET_NAMEP(&dir, "/IDENT/");
00393 dir.d_addr = 0L;
00394 dir.d_len = 1;
00395 dir.d_magic = RT_DIR_MAGIC;
00396 dir.d_flags = 0;
00397 if( db_get( dbip, &dir, &rec, 0, 1 ) < 0 ||
00398 rec.u_id != ID_IDENT ) {
00399 bu_log("db_update_ident() corrupted database header!\n");
00400 dbip->dbi_read_only = 1;
00401 return(-1);
00402 }
00403
00404 rec.i.i_title[0] = '\0';
00405 (void)strncpy(rec.i.i_title, new_title, sizeof(rec.i.i_title)-1 );
00406
00407 old_title = dbip->dbi_title;
00408 dbip->dbi_title = bu_strdup( new_title );
00409
00410 if( (v4units = db_v4_get_units_code(bu_units_string(local2mm))) < 0 ) {
00411 bu_log("db_update_ident(): \
00412 Due to a restriction in previous versions of the BRL-CAD database format, your\n\
00413 editing units %g will not be remembered on your next editing session.\n\
00414 This will not harm the integrity of your database.\n\
00415 You may wish to consider upgrading your database using \"dbupgrade\".\n",
00416 local2mm);
00417 v4units = ID_MM_UNIT;
00418 }
00419 rec.i.i_units = v4units;
00420
00421 if( old_title )
00422 bu_free( old_title, "old dbi_title" );
00423
00424 return( db_put( dbip, &dir, &rec, 0, 1 ) );
00425
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 int
00443 db_fwrite_ident( FILE *fp, const char *title, double local2mm )
00444 {
00445 union record rec;
00446 int code;
00447
00448 code = db_v4_get_units_code(bu_units_string(local2mm));
00449
00450 if(RT_G_DEBUG&DEBUG_DB) bu_log("db_fwrite_ident( x%x, '%s', %g ) code=%d\n",
00451 fp, title, local2mm, code );
00452
00453 bzero( (char *)&rec, sizeof(rec) );
00454 rec.i.i_id = ID_IDENT;
00455 rec.i.i_units = code;
00456 (void)strncpy( rec.i.i_version, ID_VERSION, sizeof(rec.i.i_version) );
00457 (void)strncpy(rec.i.i_title, title, sizeof(rec.i.i_title)-1 );
00458
00459 if( fwrite( (char *)&rec, sizeof(rec), 1, fp ) != 1 )
00460 return -1;
00461 return 0;
00462 }
00463
00464
00465
00466
00467
00468
00469 void
00470 db_conversions(struct db_i *dbip, int local)
00471
00472
00473 {
00474 RT_CK_DBI(dbip);
00475
00476
00477 switch( local ) {
00478
00479 case ID_NO_UNIT:
00480
00481 dbip->dbi_local2base = 1.0;
00482 break;
00483
00484 case ID_UM_UNIT:
00485
00486 dbip->dbi_local2base = 0.001;
00487 break;
00488
00489 case ID_MM_UNIT:
00490
00491 dbip->dbi_local2base = 1.0;
00492 break;
00493
00494 case ID_CM_UNIT:
00495
00496 dbip->dbi_local2base = 10.0;
00497 break;
00498
00499 case ID_M_UNIT:
00500
00501 dbip->dbi_local2base = 1000.0;
00502 break;
00503
00504 case ID_KM_UNIT:
00505
00506 dbip->dbi_local2base = 1000000.0;
00507 break;
00508
00509 case ID_IN_UNIT:
00510
00511 dbip->dbi_local2base = 25.4;
00512 break;
00513
00514 case ID_FT_UNIT:
00515
00516 dbip->dbi_local2base = 304.8;
00517 break;
00518
00519 case ID_YD_UNIT:
00520
00521 dbip->dbi_local2base = 914.4;
00522 break;
00523
00524 case ID_MI_UNIT:
00525
00526 dbip->dbi_local2base = 1609344;
00527 break;
00528
00529 default:
00530 dbip->dbi_local2base = 1.0;
00531 break;
00532 }
00533 dbip->dbi_base2local = 1.0 / dbip->dbi_local2base;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 int
00548 db_v4_get_units_code( const char *str )
00549 {
00550 if( !str ) return ID_NO_UNIT;
00551
00552 if( strcmp(str, "mm") == 0 || strcmp(str, "millimeters") == 0 )
00553 return ID_MM_UNIT;
00554 if( strcmp(str, "um") == 0 || strcmp(str, "micrometers") == 0)
00555 return ID_UM_UNIT;
00556 if( strcmp(str, "cm") == 0 || strcmp(str, "centimeters") == 0)
00557 return ID_CM_UNIT;
00558 if( strcmp(str,"m")==0 || strcmp(str,"meters")==0 )
00559 return ID_M_UNIT;
00560 if( strcmp(str, "km") == 0 || strcmp(str, "kilometers") == 0)
00561 return ID_KM_UNIT;
00562 if( strcmp(str,"in")==0 || strcmp(str,"inches")==0 || strcmp(str,"inch")==0 )
00563 return ID_IN_UNIT;
00564 if( strcmp(str,"ft")==0 || strcmp(str,"feet")==0 || strcmp(str,"foot")==0 )
00565 return ID_FT_UNIT;
00566 if( strcmp(str,"yd")==0 || strcmp(str,"yards")==0 || strcmp(str,"yard")==0 )
00567 return ID_YD_UNIT;
00568 if( strcmp(str,"mi")==0 || strcmp(str,"miles")==0 || strcmp(str,"mile")==0 )
00569 return ID_MI_UNIT;
00570
00571 return -1;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583