dgnwrite.cpp
来自「支持各种栅格图像和矢量图像读取的库」· C++ 代码 · 共 1,687 行 · 第 1/5 页
CPP
1,687 行
/****************************************************************************** * $Id: dgnwrite.cpp 10646 2007-01-18 02:38:10Z warmerdam $ * * 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. ****************************************************************************/#include "dgnlibp.h"CPL_CVSID("$Id: dgnwrite.cpp 10646 2007-01-18 02:38:10Z warmerdam $");static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint, unsigned char *pabyTarget );/************************************************************************//* 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] = (unsigned char) (nWords % 256); psElement->raw_data[3] = (unsigned char) (nWords / 256); return TRUE;}/************************************************************************//* DGNWriteElement() *//************************************************************************//** * Write element to file. * * Only elements with "raw_data" loaded may be written. This should * include elements created with the various DGNCreate*() functions, and * those read from the file with the DGNO_CAPTURE_RAW_DATA flag turned on * with DGNSetOptions(). * * 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 = (unsigned char) psElement->level; psInfo->type = (unsigned char) psElement->type; psInfo->stype = (unsigned char) 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. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?