LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/dgn - dgnopen.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 71 79 89.9 %
Date: 2024-05-08 14:54:11 Functions: 7 7 100.0 %

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

Generated by: LCOV version 1.14