wdb.c

Go to the documentation of this file.
00001 /*                           W D B . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2000-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 wdb */
00023 /*@{*/
00024 /** @file wdb.c
00025  *  Routines to allow libwdb to use librt's import/export interface,
00026  *  rather than having to know about the database formats directly.
00027  *
00028  *  Author -
00029  *      Michael John Muuss
00030  *
00031  *  Source -
00032  *      The U. S. Army Research Laboratory
00033  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00034  */
00035 /*@}*/
00036 
00037 #ifndef lint
00038 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/wdb.c,v 14.13 2006/09/16 02:04:26 lbutler Exp $ (ARL)";
00039 #endif
00040 
00041 #include "common.h"
00042 
00043 #include <stdio.h>
00044 #include <math.h>
00045 
00046 #include "machine.h"
00047 #include "bu.h"
00048 #include "vmath.h"
00049 #include "bn.h"
00050 #include "rtgeom.h"
00051 #include "raytrace.h"
00052 #include "wdb.h"
00053 
00054 /*
00055  *                      W D B _ F O P E N
00056  *
00057  *  Create a libwdb output stream destined for a disk file.
00058  *  This will destroy any existing file by this name, and start fresh.
00059  *  The file is then opened in the normal "update" mode and
00060  *  an in-memory directory is built along the way,
00061  *  allowing retrievals and object replacements as needed.
00062  *
00063  *  Users can change the database title by calling: ???
00064  */
00065 struct rt_wdb *
00066 wdb_fopen_v( const char *filename, int version )
00067 {
00068         struct db_i     *dbip;
00069 
00070         if( rt_uniresource.re_magic != RESOURCE_MAGIC )
00071                 rt_init_resource( &rt_uniresource, 0, NULL );
00072 
00073         if( (dbip = db_create( filename, version )) == DBI_NULL )
00074                 return RT_WDB_NULL;
00075 
00076         return wdb_dbopen( dbip, RT_WDB_TYPE_DB_DISK );
00077 }
00078 
00079 struct rt_wdb *
00080 wdb_fopen( const char *filename)
00081 {
00082     return wdb_fopen_v(filename, 5);
00083 }
00084 
00085 
00086 /*
00087  *                      W D B _ D B O P E N
00088  *
00089  *  Create a libwdb output stream destined for an existing BRL-CAD database,
00090  *  already opened via a db_open() call.
00091  *      RT_WDB_TYPE_DB_DISK                     Add to on-disk database
00092  *      RT_WDB_TYPE_DB_DISK_APPEND_ONLY         Add to on-disk database, don't clobber existing names, use prefix
00093  *      RT_WDB_TYPE_DB_INMEM                    Add to in-memory database only
00094  *      RT_WDB_TYPE_DB_INMEM_APPEND_ONLY        Ditto, but give errors if name in use.
00095  */
00096 struct rt_wdb *
00097 wdb_dbopen( struct db_i *dbip, int mode )
00098 {
00099         struct rt_wdb   *wdbp;
00100 
00101         RT_CK_DBI(dbip);
00102 
00103         if (mode != RT_WDB_TYPE_DB_DISK  && mode != RT_WDB_TYPE_DB_DISK_APPEND_ONLY &&
00104             mode != RT_WDB_TYPE_DB_INMEM && mode != RT_WDB_TYPE_DB_INMEM_APPEND_ONLY) {
00105                 bu_log("wdb_dbopen(%s) mode %d unknown\n",
00106                         dbip->dbi_filename, mode );
00107                 return RT_WDB_NULL;
00108         }
00109 
00110 #if 0
00111         if( (mode == RT_WDB_TYPE_DB_DISK || mode == RT_WDB_TYPE_DB_DISK_APPEND_ONLY ) &&
00112             dbip->dbi_read_only )  {
00113                 /* In-mem updates happen regardless of disk read-only flag */
00114                 bu_log("wdb_dbopen(%s): read-only\n",
00115                         dbip->dbi_filename );
00116         }
00117 #endif
00118 
00119         if( rt_uniresource.re_magic != RESOURCE_MAGIC )
00120                 rt_init_resource( &rt_uniresource, 0, NULL );
00121 
00122         BU_GETSTRUCT(wdbp, rt_wdb);
00123         wdbp->l.magic = RT_WDB_MAGIC;
00124         wdbp->type = mode;
00125         wdbp->dbip = dbip;
00126         wdbp->dbip->dbi_wdbp = wdbp;
00127 
00128         /* Provide the same default tolerance that librt/prep.c does */
00129         wdbp->wdb_tol.magic = BN_TOL_MAGIC;
00130         wdbp->wdb_tol.dist = 0.005;
00131         wdbp->wdb_tol.dist_sq = wdbp->wdb_tol.dist * wdbp->wdb_tol.dist;
00132         wdbp->wdb_tol.perp = 1e-6;
00133         wdbp->wdb_tol.para = 1 - wdbp->wdb_tol.perp;
00134 
00135         wdbp->wdb_ttol.magic = RT_TESS_TOL_MAGIC;
00136         wdbp->wdb_ttol.abs = 0.0;
00137         wdbp->wdb_ttol.rel = 0.01;
00138         wdbp->wdb_ttol.norm = 0;
00139         bu_vls_init( &wdbp->wdb_prestr );
00140 
00141         return wdbp;
00142 
00143 }
00144 
00145 /*
00146  *                      W D B _ I M P O R T
00147  *
00148  *  Returns -
00149  *      0       and modified *internp;
00150  *      -1      ft_import failure (from rt_db_get_internal)
00151  *      -2      db_get_external failure (from rt_db_get_internal)
00152  *      -3      Attempt to import from write-only (stream) file.
00153  *      -4      Name not found in database TOC.
00154  *
00155  *  NON-PARALLEL because of rt_uniresource
00156  */
00157 int
00158 wdb_import(struct rt_wdb *wdbp, struct rt_db_internal *internp, const char *name, const mat_t mat )
00159 {
00160         struct directory        *dp;
00161 
00162         if( (dp = db_lookup( wdbp->dbip, name, LOOKUP_QUIET )) == DIR_NULL )
00163                 return -4;
00164 
00165         return rt_db_get_internal( internp, dp, wdbp->dbip, mat, &rt_uniresource );
00166 }
00167 
00168 /*
00169  *                      W D B _ E X P O R T _ E X T E R N A L
00170  *
00171  *  The caller must free "ep".
00172  *
00173  *  Returns -
00174  *       0      OK
00175  *      <0      error
00176  */
00177 int
00178 wdb_export_external(
00179         struct rt_wdb *wdbp,
00180         struct bu_external *ep,
00181         const char *name,
00182         int flags,
00183         unsigned char type)
00184 {
00185         struct directory        *dp;
00186 
00187         RT_CK_WDB(wdbp);
00188         BU_CK_EXTERNAL(ep);
00189 
00190         /* Stash name into external representation */
00191         if( wdbp->dbip->dbi_version <= 4 )  {
00192                 db_wrap_v4_external( ep, name );
00193         } else if( wdbp->dbip->dbi_version == 5 )  {
00194                 if( db_wrap_v5_external( ep, name ) < 0 )  {
00195                         bu_log("wdb_export_external(%s): db_wrap_v5_external error\n",
00196                                 name );
00197                         return -4;
00198                 }
00199         } else {
00200                 bu_log("wdb_export_external(%s): version %d unsupported\n",
00201                                 name, wdbp->dbip->dbi_version );
00202                 return -4;
00203         }
00204 
00205         switch( wdbp->type )  {
00206 
00207         case RT_WDB_TYPE_DB_DISK:
00208                 if( wdbp->dbip->dbi_read_only )  {
00209                         bu_log("wdb_export_external(%s): read-only database, write aborted\n");
00210                         return -5;
00211                 }
00212                 /* If name already exists, that object will be updated. */
00213                 dp = db_lookup( wdbp->dbip, name, LOOKUP_QUIET );
00214                 if( dp == DIR_NULL ) {
00215                         if( (dp = db_diradd( wdbp->dbip, name, -1L, 0, flags,
00216                                            (genptr_t)&type )) == DIR_NULL )  {
00217                         bu_log("wdb_export_external(%s): db_diradd error\n",
00218                                name );
00219                         return -3;
00220                         }
00221                 }
00222                 dp->d_flags = (dp->d_flags & ~7) | flags;
00223                 if( db_put_external( ep, dp, wdbp->dbip ) < 0 )  {
00224                         bu_log("wdb_export_external(%s): db_put_external error\n",
00225                                 name );
00226                         return -3;
00227                 }
00228                 break;
00229 
00230         case RT_WDB_TYPE_DB_DISK_APPEND_ONLY:
00231                 if( wdbp->dbip->dbi_read_only )  {
00232                         bu_log("wdb_export_external(%s): read-only database, write aborted\n");
00233                         return -5;
00234                 }
00235                 /* If name already exists, new non-conflicting name will be generated */
00236                 if( (dp = db_diradd( wdbp->dbip, name, -1L, 0, flags,
00237                                     (genptr_t)&type )) == DIR_NULL )  {
00238                         bu_log("wdb_export_external(%s): db_diradd error\n",
00239                                name );
00240                         return -3;
00241                 }
00242                 if( db_put_external( ep, dp, wdbp->dbip ) < 0 )  {
00243                         bu_log("wdb_export_external(%s): db_put_external error\n",
00244                                 name );
00245                         return -3;
00246                 }
00247                 break;
00248 
00249         case RT_WDB_TYPE_DB_INMEM_APPEND_ONLY:
00250                 if( (dp = db_lookup( wdbp->dbip, name, 0 )) != DIR_NULL )  {
00251                         bu_log("wdb_export_external(%s): ERROR, that name is already in use, and APPEND_ONLY mode has been specified.\n",
00252                                 name );
00253                         return -3;
00254                 }
00255                 if( (dp = db_diradd( wdbp->dbip, name, -1L, 0, flags,
00256                                 (genptr_t)&type )) == DIR_NULL )  {
00257                         bu_log("wdb_export_external(%s): db_diradd error\n",
00258                                name );
00259                         return -3;
00260                 }
00261 
00262                 db_inmem( dp, ep, flags, wdbp->dbip );
00263                 /* ep->buf has been stolen, replaced with null. */
00264                 break;
00265 
00266         case RT_WDB_TYPE_DB_INMEM:
00267                 if( (dp = db_lookup( wdbp->dbip, name, 0 )) == DIR_NULL )  {
00268                         if( (dp = db_diradd( wdbp->dbip, name, -1L, 0, flags,
00269                                         (genptr_t)&type )) == DIR_NULL )  {
00270                                 bu_log("wdb_export_external(%s): db_diradd error\n",
00271                                        name );
00272                                 bu_free_external( ep );
00273                                 return -3;
00274                         }
00275                 } else {
00276                         dp->d_flags = (dp->d_flags & ~7) | flags;
00277                 }
00278 
00279                 db_inmem( dp, ep, flags, wdbp->dbip );
00280                 /* ep->buf has been stolen, replaced with null. */
00281                 break;
00282         }
00283 
00284         return 0;
00285 }
00286 
00287 /*
00288  *                      W D B _ P U T _ I N T E R N A L
00289  *
00290  *  Convert the internal representation of a solid to the external one,
00291  *  and write it into the database.
00292  *  The internal representation is always freed.
00293  *  This is the analog of rt_db_put_internal() for rt_wdb objects.
00294  *
00295  *  Use this routine in preference to wdb_export() whenever the
00296  *  caller already has an rt_db_internal structure handy.
00297  *
00298  *  NON-PARALLEL because of rt_uniresource
00299  *
00300  *  Returns -
00301  *       0      OK
00302  *      <0      error
00303  */
00304 int
00305 wdb_put_internal(
00306         struct rt_wdb *wdbp,
00307         const char *name,
00308         struct rt_db_internal *ip,
00309         double local2mm )
00310 {
00311         struct bu_external      ext;
00312         int                     ret;
00313         int                     flags;
00314 
00315         RT_CK_WDB(wdbp);
00316         RT_CK_DB_INTERNAL(ip);
00317 
00318         if( wdbp->dbip->dbi_version <= 4 )  {
00319                 BU_INIT_EXTERNAL( &ext );
00320                 ret = ip->idb_meth->ft_export( &ext, ip, local2mm, wdbp->dbip, &rt_uniresource );
00321                 if( ret < 0 )  {
00322                         bu_log("rt_db_put_internal(%s):  solid export failure\n",
00323                                 name);
00324                         ret = -1;
00325                         goto out;
00326                 }
00327                 db_wrap_v4_external( &ext, name );
00328         } else {
00329                 if( rt_db_cvt_to_external5( &ext, name, ip, local2mm, wdbp->dbip, &rt_uniresource, ip->idb_major_type ) < 0 )  {
00330                         bu_log("wdb_export(%s): solid export failure\n",
00331                                 name );
00332                         ret = -2;
00333                         goto out;
00334                 }
00335         }
00336         BU_CK_EXTERNAL( &ext );
00337 
00338         flags = db_flags_internal( ip );
00339         ret = wdb_export_external( wdbp, &ext, name, flags, ip->idb_type );
00340 out:
00341         bu_free_external( &ext );
00342         rt_db_free_internal( ip, &rt_uniresource );
00343         return ret;
00344 }
00345 
00346 /*
00347  *                      W D B _ E X P O R T
00348  *
00349  *  Export an in-memory representation of an object,
00350  *  as described in the file h/rtgeom.h, into the indicated database.
00351  *
00352  *  The internal representation (gp) is always freed.
00353  *
00354  *  WARNING: The caller must be careful not to double-free gp,
00355  *  particularly if it's been extracted from an rt_db_internal,
00356  *  e.g. by passing intern.idb_ptr for gp.
00357  *
00358  *  If the caller has an rt_db_internal structure handy already,
00359  *  they should call wdb_put_internal() directly -- this is a
00360  *  convenience routine intended primarily for internal use in LIBWDB.
00361  *
00362  *  Returns -
00363  *       0      OK
00364  *      <0      error
00365  */
00366 int
00367 wdb_export(
00368         struct rt_wdb *wdbp,
00369         const char *name,
00370         genptr_t gp,
00371         int id,
00372         double local2mm )
00373 {
00374         struct rt_db_internal   intern;
00375 
00376         RT_CK_WDB(wdbp);
00377 
00378         if( (id <= 0 || id > ID_MAX_SOLID) && id != ID_COMBINATION )  {
00379                 bu_log("wdb_export(%s): id=%d bad\n",
00380                         name, id );
00381                 return(-1);
00382         }
00383 
00384         RT_INIT_DB_INTERNAL( &intern );
00385         intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
00386         intern.idb_type = id;
00387         intern.idb_ptr = gp;
00388         intern.idb_meth = &rt_functab[id];
00389 
00390         return wdb_put_internal( wdbp, name, &intern, local2mm );
00391 }
00392 
00393 /*
00394  *                      W D B _ C L O S E
00395  *
00396  *  Release from associated database "file", destroy dynamic data structure.
00397  */
00398 void
00399 wdb_close( struct rt_wdb *wdbp )
00400 {
00401 
00402         RT_CK_WDB(wdbp);
00403 
00404         /* XXX Flush any unwritten "struct matter" records here */
00405 
00406         db_close( wdbp->dbip );
00407 
00408         bu_vls_free( &wdbp->wdb_prestr );
00409         bu_free( (genptr_t)wdbp, "struct rt_wdb");
00410 }
00411 
00412 /*
00413  * Local Variables:
00414  * mode: C
00415  * tab-width: 8
00416  * c-basic-offset: 4
00417  * indent-tabs-mode: t
00418  * End:
00419  * ex: shiftwidth=4 tabstop=8
00420  */

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