⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dgnwrite.cpp

📁 在Linux环境下读写DGN文件
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************** * $Id: dgnwrite.cpp,v 1.5 2002/11/13 21:26:32 warmerda Exp $ * * Project:  Microstation DGN Access Library * Purpose:  DGN Access functions related to writing DGN elements. * Author:   Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** * * $Log: dgnwrite.cpp,v $ * Revision 1.5  2002/11/13 21:26:32  warmerda * added more documentation * * Revision 1.4  2002/11/12 19:45:54  warmerda * added support to update TCB in DGNCreate * * Revision 1.3  2002/11/11 20:38:43  warmerda * implemented write api * * Revision 1.2  2002/10/20 01:50:20  warmerda * added new write prototypes * * Revision 1.1  2002/03/14 21:40:43  warmerda * New * */#include "dgnlibp.h"CPL_CVSID("$Id: dgnwrite.cpp,v 1.5 2002/11/13 21:26:32 warmerda Exp $");/************************************************************************//*                          DGNResizeElement()                          *//************************************************************************//** * Resize an existing element. * * If the new size is the same as the old nothing happens.  * * Otherwise, the old element in the file is marked as deleted, and the * DGNElemCore.offset and element_id are set to -1 indicating that the * element should be written to the end of file when next written by * DGNWriteElement().  The internal raw data buffer is updated to the new * size. *  * Only elements with "raw_data" loaded may be moved. * * In normal use the DGNResizeElement() call would be called on a previously * loaded element, and afterwards the raw_data would be updated before calling * DGNWriteElement().  If DGNWriteElement() isn't called after  * DGNResizeElement() then the element will be lost having been marked as * deleted in it's old position but never written at the new location.  * * @param hDGN the DGN file on which the element lives. * @param psElement the element to alter.   * @param nNewSize the desired new size of the element in bytes.  Must be * a multiple of 2.  * * @return TRUE on success, or FALSE on error. */int DGNResizeElement( DGNHandle hDGN, DGNElemCore *psElement, int nNewSize ){    DGNInfo	*psDGN = (DGNInfo *) hDGN;/* -------------------------------------------------------------------- *//*      Check various conditions.                                       *//* -------------------------------------------------------------------- */    if( psElement->raw_bytes == 0         || psElement->raw_bytes != psElement->size )    {        CPLError( CE_Failure, CPLE_AppDefined,                   "Raw bytes not loaded, or not matching element size." );        return FALSE;    }    if( nNewSize % 2 == 1 )    {        CPLError( CE_Failure, CPLE_AppDefined,                   "DGNResizeElement(%d): "                  "can't change to odd (not divisible by two) size.",                   nNewSize );        return FALSE;    }    if( nNewSize == psElement->raw_bytes )        return TRUE;/* -------------------------------------------------------------------- *//*      Mark the existing element as deleted if the element has to      *//*      move to the end of the file.                                    *//* -------------------------------------------------------------------- */    if( psElement->offset != -1 )    {        int nOldFLoc = VSIFTell( psDGN->fp );        unsigned char abyLeader[2];                if( VSIFSeek( psDGN->fp, psElement->offset, SEEK_SET ) != 0            || VSIFRead( abyLeader, sizeof(abyLeader), 1, psDGN->fp ) != 1 )        {            CPLError( CE_Failure, CPLE_AppDefined,                       "Failed seek or read when trying to mark existing\n"                      "element as deleted in DGNResizeElement()\n" );            return FALSE;        }        abyLeader[1] |= 0x80;                if( VSIFSeek( psDGN->fp, psElement->offset, SEEK_SET ) != 0            || VSIFWrite( abyLeader, sizeof(abyLeader), 1, psDGN->fp ) != 1 )        {            CPLError( CE_Failure, CPLE_AppDefined,                       "Failed seek or write when trying to mark existing\n"                      "element as deleted in DGNResizeElement()\n" );            return FALSE;        }        VSIFSeek( psDGN->fp, SEEK_SET, nOldFLoc );        if( psElement->element_id != -1 && psDGN->index_built )            psDGN->element_index[psElement->element_id].flags                 |= DGNEIF_DELETED;    }    psElement->offset = -1; /* move to end of file. */    psElement->element_id = -1;/* -------------------------------------------------------------------- *//*      Set the new size information, and realloc the raw data buffer.  *//* -------------------------------------------------------------------- */    psElement->size = nNewSize;    psElement->raw_data = (unsigned char *)         CPLRealloc( psElement->raw_data, nNewSize );    psElement->raw_bytes = nNewSize;/* -------------------------------------------------------------------- *//*      Update the size information within the raw buffer.              *//* -------------------------------------------------------------------- */    int nWords = (nNewSize / 2) - 2;    psElement->raw_data[2] = nWords % 256;    psElement->raw_data[3] = nWords / 256;    return TRUE;}/************************************************************************//*                          DGNWriteElement()                           *//************************************************************************//**  * Write element to file.  * * Only elements with "raw_data" loaded may be written. * * The passed element is written to the indicated file.  If the  * DGNElemCore.offset field is -1 then the element is written at the end of * the file (and offset/element are reset properly) otherwise the element  * is written back to the location indicated by DGNElemCore.offset.   * * If the element is added at the end of the file, and if an element index * has already been built, it will be updated to reference the new element. * * This function takes care of ensuring that the end-of-file marker is  * maintained after the last element. * * @param hDGN the file to write the element to. * @param psElement the element to write.  * * @return TRUE on success or FALSE in case of failure. */int DGNWriteElement( DGNHandle hDGN, DGNElemCore *psElement ){    DGNInfo	*psDGN = (DGNInfo *) hDGN;/* ==================================================================== *//*      If this element hasn't been positioned yet, place it at the     *//*      end of the file.                                                *//* ==================================================================== */    if( psElement->offset == -1 )    {        int nJunk;        // We must have an index, in order to properly assign the         // element id of the newly written element.  Ensure it is built.        if( !psDGN->index_built )            DGNBuildIndex( psDGN );        // Read the current "last" element.        if( !DGNGotoElement( hDGN, psDGN->element_count-1 ) )            return FALSE;        if( !DGNLoadRawElement( psDGN, &nJunk, &nJunk ) )            return FALSE;        // Establish the position of the new element.        psElement->offset = VSIFTell( psDGN->fp );        psElement->element_id = psDGN->element_count;        // Grow element buffer if needed.        if( psDGN->element_count == psDGN->max_element_count )        {            psDGN->max_element_count += 500;                        psDGN->element_index = (DGNElementInfo *)                 CPLRealloc( psDGN->element_index,                             psDGN->max_element_count * sizeof(DGNElementInfo));        }        // Set up the element info        DGNElementInfo *psInfo;                psInfo = psDGN->element_index + psDGN->element_count;        psInfo->level = psElement->level;        psInfo->type = psElement->type;        psInfo->stype = psElement->stype;        psInfo->offset = psElement->offset;        if( psElement->complex )            psInfo->flags = DGNEIF_COMPLEX;        else            psInfo->flags = 0;            psDGN->element_count++;    }/* -------------------------------------------------------------------- *//*      Write out the element.                                          *//* -------------------------------------------------------------------- */    if( VSIFSeek( psDGN->fp, psElement->offset, SEEK_SET ) != 0         || VSIFWrite( psElement->raw_data, psElement->raw_bytes,                       1, psDGN->fp) != 1 )    {        CPLError( CE_Failure, CPLE_AppDefined,                   "Error seeking or writing new element of %d bytes at %d.",                  psElement->offset,                   psElement->raw_bytes );        return FALSE;    }    psDGN->next_element_id = psElement->element_id + 1;/* -------------------------------------------------------------------- *//*      Write out the end of file 0xffff marker (if we were             *//*      extending the file), but push the file pointer back before      *//*      this EOF when done.                                             *//* -------------------------------------------------------------------- */    if( psDGN->next_element_id == psDGN->element_count )    {        unsigned char abyEOF[2];        abyEOF[0] = 0xff;        abyEOF[1] = 0xff;        VSIFWrite( abyEOF, 2, 1, psDGN->fp );        VSIFSeek( psDGN->fp, -2, SEEK_CUR );    }            return TRUE;}    /************************************************************************//*                             DGNCreate()                              *//************************************************************************//** * Create new DGN file. * * This function will create a new DGN file based on the provided seed * file, and return a handle on which elements may be read and written. * * The following creation flags may be passed: * <ul> * <li> DGNCF_USE_SEED_UNITS: The master and subunit resolutions and names * from the seed file will be used in the new file.  The nMasterUnitPerSubUnit, * nUORPerSubUnit, pszMasterUnits, and pszSubUnits arguments will be ignored. * <li> DGNCF_USE_SEED_ORIGIN: The origin from the seed file will be used * and the X, Y and Z origin passed into the call will be ignored.  * <li> DGNCF_COPY_SEED_FILE_COLOR_TABLE: Should the first color table occuring * in the seed file also be copied?  * <li> DGNCF_COPY_WHOLE_SEED_FILE: By default only the first three elements * (TCB, Digitizer Setup and Level Symbology) are copied from the seed file.  * If this flag is provided the entire seed file is copied verbatim (with the * TCB origin and units possibly updated). * </ul> *  * @param pszNewFilename the filename to create.  If it already exists * it will be overwritten. * @param pszSeedFile the seed file to copy header from. * @param nCreationFlags An ORing of DGNCF_* flags that are to take effect. * @param dfOriginX the X origin for the file.   * @param dfOriginY the Y origin for the file.  * @param dfOriginZ the Z origin for the file.  * @param nSubUnitPerMasterUnit the number of subunits in one master unit. * @param nUORPerSubUnit the number of UOR (units of resolution) per subunit. * @param pszMasterUnits the name of the master units (2 characters).  * @param pszSubUnits the name of the subunits (2 characters).  */DGNHandle      DGNCreate( const char *pszNewFilename, const char *pszSeedFile,                  int nCreationFlags,                  double dfOriginX, double dfOriginY, double dfOriginZ,                 int nSubUnitsPerMasterUnit, int nUORPerSubUnit,                  const char *pszMasterUnits, const char *pszSubUnits ){    DGNInfo *psSeed, *psDGN;    FILE    *fpNew;    DGNElemCore *psSrcTCB;/* -------------------------------------------------------------------- *//*      Open seed file, and read TCB element.                           *//* -------------------------------------------------------------------- */    psSeed = (DGNInfo *) DGNOpen( pszSeedFile, FALSE );    if( psSeed == NULL )        return NULL;    DGNSetOptions( psSeed, DGNO_CAPTURE_RAW_DATA );        psSrcTCB = DGNReadElement( psSeed );    CPLAssert( psSrcTCB->raw_bytes >= 1536 );    /* -------------------------------------------------------------------- *//*      Open output file.                                               *//* -------------------------------------------------------------------- */    fpNew = VSIFOpen( pszNewFilename, "wb" );    if( fpNew == NULL )    {        CPLError( CE_Failure, CPLE_OpenFailed,                   "Failed to open output file: %s", pszNewFilename );        return NULL;    }/* -------------------------------------------------------------------- *//*      Modify TCB appropriately for the output file.                   *//* -------------------------------------------------------------------- */    GByte *pabyRawTCB = (GByte *) CPLMalloc(psSrcTCB->raw_bytes);        memcpy( pabyRawTCB, psSrcTCB->raw_data, psSrcTCB->raw_bytes );    if( !(nCreationFlags & DGNCF_USE_SEED_UNITS) )    {        memcpy( pabyRawTCB+1120, pszMasterUnits, 2 );        memcpy( pabyRawTCB+1122, pszSubUnits, 2 );        DGN_WRITE_INT32( nUORPerSubUnit, pabyRawTCB+1116 );        DGN_WRITE_INT32( nSubUnitsPerMasterUnit, pabyRawTCB+1112 );    }    else    {        nUORPerSubUnit = DGN_INT32( pabyRawTCB+1120 );        nSubUnitsPerMasterUnit = DGN_INT32( pabyRawTCB+1112 );    }    if( !(nCreationFlags & DGNCF_USE_SEED_ORIGIN) )    {        dfOriginX *= (nUORPerSubUnit * nSubUnitsPerMasterUnit);        dfOriginY *= (nUORPerSubUnit * nSubUnitsPerMasterUnit);        dfOriginZ *= (nUORPerSubUnit * nSubUnitsPerMasterUnit);        memcpy( pabyRawTCB+1240, &dfOriginX, 8 );        memcpy( pabyRawTCB+1248, &dfOriginY, 8 );        memcpy( pabyRawTCB+1256, &dfOriginZ, 8 );        IEEE2DGNDouble( pabyRawTCB+1240 );        IEEE2DGNDouble( pabyRawTCB+1248 );        IEEE2DGNDouble( pabyRawTCB+1246 );    }/* -------------------------------------------------------------------- *//*      Write TCB and EOF to new file.                                  *//* -------------------------------------------------------------------- */    unsigned char abyEOF[2];        VSIFWrite( pabyRawTCB, psSrcTCB->raw_bytes, 1, fpNew );    abyEOF[0] = 0xff;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -