LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/dgn - dgnopen.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 87 76 87.4 %
Date: 2010-01-09 Functions: 7 7 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: dgnopen.cpp 10645 2007-01-18 02:22:39Z warmerdam $
       3                 :  *
       4                 :  * Project:  Microstation DGN Access Library
       5                 :  * Purpose:  DGN Access Library file open code.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2000, Avenza Systems Inc, http://www.avenza.com/
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "dgnlibp.h"
      31                 : 
      32                 : CPL_CVSID("$Id: dgnopen.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
      33                 : 
      34                 : /************************************************************************/
      35                 : /*                            DGNTestOpen()                             */
      36                 : /************************************************************************/
      37                 : 
      38                 : /** 
      39                 :  * Test if header is DGN.
      40                 :  *
      41                 :  * @param pabyHeader block of header data from beginning of file.
      42                 :  * @param nByteCount number of bytes in pabyHeader. 
      43                 :  *
      44                 :  * @return TRUE if the header appears to be from a DGN file, otherwise FALSE.
      45                 :  */
      46                 : 
      47              77 : int DGNTestOpen( GByte *pabyHeader, int nByteCount )
      48                 : 
      49                 : {
      50              77 :     if( nByteCount < 4 )
      51               0 :         return TRUE;
      52                 : 
      53                 :     // Is it a cell library?
      54              85 :     if( pabyHeader[0] == 0x08
      55               8 :         && pabyHeader[1] == 0x05
      56               0 :         && pabyHeader[2] == 0x17
      57               0 :         && pabyHeader[3] == 0x00 )
      58               0 :         return TRUE;
      59                 : 
      60                 :     // Is it not a regular 2D or 3D file?
      61             101 :     if( (pabyHeader[0] != 0x08 && pabyHeader[0] != 0xC8) 
      62               8 :         || pabyHeader[1] != 0x09
      63              16 :         || pabyHeader[2] != 0xFE || pabyHeader[3] != 0x02 )
      64              69 :         return FALSE;
      65                 : 
      66               8 :     return TRUE;
      67                 : }
      68                 : 
      69                 : /************************************************************************/
      70                 : /*                              DGNOpen()                               */
      71                 : /************************************************************************/
      72                 : 
      73                 : /**
      74                 :  * Open a DGN file. 
      75                 :  *
      76                 :  * The file is opened, and minimally verified to ensure it is a DGN (ISFF)
      77                 :  * file.  If the file cannot be opened for read access an error with code
      78                 :  * CPLE_OpenFailed with be reported via CPLError() and NULL returned.  
      79                 :  * If the file header does
      80                 :  * not appear to be a DGN file, an error with code CPLE_AppDefined will be
      81                 :  * reported via CPLError(), and NULL returned.
      82                 :  *
      83                 :  * If successful a handle for further access is returned.  This should be
      84                 :  * closed with DGNClose() when no longer needed.  
      85                 :  *
      86                 :  * DGNOpen() does not scan the file on open, and should be very fast even for
      87                 :  * large files.  
      88                 :  *
      89                 :  * @param pszFilename name of file to try opening.
      90                 :  * @param bUpdate should the file be opened with read+update (r+) mode?
      91                 :  *
      92                 :  * @return handle to use for further access to file using DGN API, or NULL
      93                 :  * if open fails.
      94                 :  */
      95                 : 
      96               5 : DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
      97                 : 
      98                 : {
      99                 :     DGNInfo     *psDGN;
     100                 :     FILE        *fp;
     101                 : 
     102                 : /* -------------------------------------------------------------------- */
     103                 : /*      Open the file.                                                  */
     104                 : /* -------------------------------------------------------------------- */
     105               5 :     if( bUpdate )
     106               1 :         fp = VSIFOpen( pszFilename, "rb+" );
     107                 :     else
     108               4 :         fp = VSIFOpen( pszFilename, "rb" );
     109               5 :     if( fp == NULL )
     110                 :     {
     111                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     112                 :                   "Unable to open `%s' for read access.\n", 
     113               0 :                   pszFilename );
     114               0 :         return NULL;
     115                 :     }
     116                 : 
     117                 : /* -------------------------------------------------------------------- */
     118                 : /*      Verify the format ... add later.                                */
     119                 : /* -------------------------------------------------------------------- */
     120                 :     GByte       abyHeader[512];
     121                 : 
     122               5 :     VSIFRead( abyHeader, 1, sizeof(abyHeader), fp );
     123               5 :     if( !DGNTestOpen( abyHeader, sizeof(abyHeader) ) )
     124                 :     {
     125                 :         CPLError( CE_Failure, CPLE_AppDefined,
     126                 :                   "File `%s' does not have expected DGN header.\n", 
     127               0 :                   pszFilename );
     128               0 :         VSIFClose( fp );
     129               0 :         return NULL;
     130                 :     }
     131                 : 
     132               5 :     VSIRewind( fp );
     133                 : 
     134                 : /* -------------------------------------------------------------------- */
     135                 : /*      Create the info structure.                                      */
     136                 : /* -------------------------------------------------------------------- */
     137               5 :     psDGN = (DGNInfo *) CPLCalloc(sizeof(DGNInfo),1);
     138               5 :     psDGN->fp = fp;
     139               5 :     psDGN->next_element_id = 0;
     140                 : 
     141               5 :     psDGN->got_tcb = FALSE;
     142               5 :     psDGN->scale = 1.0;
     143               5 :     psDGN->origin_x = 0.0;
     144               5 :     psDGN->origin_y = 0.0;
     145               5 :     psDGN->origin_z = 0.0;                                             
     146                 : 
     147               5 :     psDGN->index_built = FALSE;
     148               5 :     psDGN->element_count = 0;
     149               5 :     psDGN->element_index = NULL;
     150                 : 
     151               5 :     psDGN->got_bounds = FALSE;
     152                 : 
     153               5 :     if( abyHeader[0] == 0xC8 )
     154               0 :         psDGN->dimension = 3;
     155                 :     else
     156               5 :         psDGN->dimension = 2;
     157                 : 
     158               5 :     psDGN->has_spatial_filter = FALSE;
     159               5 :     psDGN->sf_converted_to_uor = FALSE;
     160               5 :     psDGN->select_complex_group = FALSE;
     161               5 :     psDGN->in_complex_group = FALSE;
     162                 : 
     163               5 :     return (DGNHandle) psDGN;
     164                 : }
     165                 : 
     166                 : /************************************************************************/
     167                 : /*                           DGNSetOptions()                            */
     168                 : /************************************************************************/
     169                 : 
     170                 : /**
     171                 :  * Set file access options.
     172                 :  *
     173                 :  * Sets a flag affecting how the file is accessed.  Currently
     174                 :  * there is only one support flag:
     175                 :  *
     176                 :  * DGNO_CAPTURE_RAW_DATA: If this is enabled (it is off by default),
     177                 :  * then the raw binary data associated with elements will be kept in
     178                 :  * the raw_data field within the DGNElemCore when they are read.  This
     179                 :  * is required if the application needs to interprete the raw data itself.
     180                 :  * It is also necessary if the element is to be written back to this file,
     181                 :  * or another file using DGNWriteElement().  Off by default (to conserve
     182                 :  * memory). 
     183                 :  *
     184                 :  * @param hDGN handle to file returned by DGNOpen(). 
     185                 :  * @param nOptions ORed option flags.
     186                 :  */
     187                 : 
     188               1 : void DGNSetOptions( DGNHandle hDGN, int nOptions )
     189                 : 
     190                 : {
     191               1 :     DGNInfo     *psDGN = (DGNInfo *) hDGN;
     192                 : 
     193               1 :     psDGN->options = nOptions;
     194               1 : }
     195                 : 
     196                 : /************************************************************************/
     197                 : /*                        DGNSetSpatialFilter()                         */
     198                 : /************************************************************************/
     199                 : 
     200                 : /**
     201                 :  * Set rectangle for which features are desired.
     202                 :  *
     203                 :  * If a spatial filter is set with this function, DGNReadElement() will
     204                 :  * only return spatial elements (elements with a known bounding box) and
     205                 :  * only those elements for which this bounding box overlaps the requested
     206                 :  * region. 
     207                 :  *
     208                 :  * If all four values (dfXMin, dfXMax, dfYMin and dfYMax) are zero, the
     209                 :  * spatial filter is disabled.   Note that installing a spatial filter
     210                 :  * won't reduce the amount of data read from disk.  All elements are still
     211                 :  * scanned, but the amount of processing work for elements outside the 
     212                 :  * spatial filter is minimized.  
     213                 :  *
     214                 :  * @param hDGN Handle from DGNOpen() for file to update.
     215                 :  * @param dfXMin minimum x coordinate for extents (georeferenced coordinates).
     216                 :  * @param dfYMin minimum y coordinate for extents (georeferenced coordinates).
     217                 :  * @param dfXMax maximum x coordinate for extents (georeferenced coordinates).
     218                 :  * @param dfYMax maximum y coordinate for extents (georeferenced coordinates).
     219                 :  */ 
     220                 : 
     221               2 : void DGNSetSpatialFilter( DGNHandle hDGN, 
     222                 :                           double dfXMin, double dfYMin, 
     223                 :                           double dfXMax, double dfYMax )
     224                 : 
     225                 : {
     226               2 :     DGNInfo     *psDGN = (DGNInfo *) hDGN;
     227                 : 
     228               2 :     if( dfXMin == 0.0 && dfXMax == 0.0
     229                 :         && dfYMin == 0.0 && dfYMax == 0.0 )
     230                 :     {
     231               1 :         psDGN->has_spatial_filter = FALSE;
     232               1 :         return;
     233                 :     }
     234                 : 
     235               1 :     psDGN->has_spatial_filter = TRUE;
     236               1 :     psDGN->sf_converted_to_uor = FALSE;
     237                 : 
     238               1 :     psDGN->sf_min_x_geo = dfXMin;
     239               1 :     psDGN->sf_min_y_geo = dfYMin;
     240               1 :     psDGN->sf_max_x_geo = dfXMax;
     241               1 :     psDGN->sf_max_y_geo = dfYMax;
     242                 : 
     243               1 :     DGNSpatialFilterToUOR( psDGN );
     244                 : 
     245                 : }
     246                 : 
     247                 : /************************************************************************/
     248                 : /*                       DGNSpatialFilterToUOR()                        */
     249                 : /************************************************************************/
     250                 : 
     251               1 : void DGNSpatialFilterToUOR( DGNInfo *psDGN )
     252                 : 
     253                 : {
     254                 :     DGNPoint    sMin, sMax;
     255                 : 
     256               1 :     if( psDGN->sf_converted_to_uor 
     257                 :         || !psDGN->has_spatial_filter 
     258                 :         || !psDGN->got_tcb )
     259               0 :         return;
     260                 : 
     261               1 :     sMin.x = psDGN->sf_min_x_geo;
     262               1 :     sMin.y = psDGN->sf_min_y_geo;
     263               1 :     sMin.z = 0;
     264                 :     
     265               1 :     sMax.x = psDGN->sf_max_x_geo;
     266               1 :     sMax.y = psDGN->sf_max_y_geo;
     267               1 :     sMax.z = 0;
     268                 : 
     269               1 :     DGNInverseTransformPoint( psDGN, &sMin );
     270               1 :     DGNInverseTransformPoint( psDGN, &sMax );
     271                 : 
     272               1 :     psDGN->sf_min_x = (GUInt32) (sMin.x + 2147483648.0);
     273               1 :     psDGN->sf_min_y = (GUInt32) (sMin.y + 2147483648.0);
     274               1 :     psDGN->sf_max_x = (GUInt32) (sMax.x + 2147483648.0);
     275               1 :     psDGN->sf_max_y = (GUInt32) (sMax.y + 2147483648.0);
     276                 : 
     277               1 :     psDGN->sf_converted_to_uor = TRUE;
     278                 : }
     279                 : 
     280                 : /************************************************************************/
     281                 : /*                              DGNClose()                              */
     282                 : /************************************************************************/
     283                 : 
     284                 : /**
     285                 :  * Close DGN file. 
     286                 :  *
     287                 :  * @param hDGN Handle from DGNOpen() for file to close.
     288                 :  */
     289                 : 
     290               5 : void DGNClose( DGNHandle hDGN )
     291                 : 
     292                 : {
     293               5 :     DGNInfo     *psDGN = (DGNInfo *) hDGN;
     294                 : 
     295               5 :     VSIFClose( psDGN->fp );
     296               5 :     CPLFree( psDGN->element_index );
     297               5 :     CPLFree( psDGN );
     298               5 : }
     299                 : 
     300                 : /************************************************************************/
     301                 : /*                          DGNGetDimension()                           */
     302                 : /************************************************************************/
     303                 : 
     304                 : /**
     305                 :  * Return 2D/3D dimension of file.
     306                 :  *
     307                 :  * Return 2 or 3 depending on the dimension value of the provided file.
     308                 :  */
     309                 : 
     310              21 : int DGNGetDimension( DGNHandle hDGN )
     311                 : 
     312                 : {
     313              21 :     DGNInfo     *psDGN = (DGNInfo *) hDGN;
     314                 : 
     315              21 :     return psDGN->dimension;
     316                 : }

Generated by: LCOV version 1.7