dgnread.cpp
来自「支持各种栅格图像和矢量图像读取的库」· C++ 代码 · 共 1,808 行 · 第 1/5 页
CPP
1,808 行
/****************************************************************************** * $Id: dgnread.cpp 10646 2007-01-18 02:38:10Z warmerdam $ * * Project: Microstation DGN Access Library * Purpose: DGN Access Library element reading code. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2000, Avenza Systems Inc, http://www.avenza.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: dgnread.cpp 10646 2007-01-18 02:38:10Z warmerdam $");static DGNElemCore *DGNParseTCB( DGNInfo * );static DGNElemCore *DGNParseColorTable( DGNInfo * );static DGNElemCore *DGNParseTagSet( DGNInfo * );/************************************************************************//* DGNGotoElement() *//************************************************************************//** * Seek to indicated element. * * Changes what element will be read on the next call to DGNReadElement(). * Note that this function requires and index, and one will be built if * not already available. * * @param hDGN the file to affect. * @param element_id the element to seek to. These values are sequentially * ordered starting at zero for the first element. * * @return returns TRUE on success or FALSE on failure. */int DGNGotoElement( DGNHandle hDGN, int element_id ){ DGNInfo *psDGN = (DGNInfo *) hDGN; DGNBuildIndex( psDGN ); if( element_id < 0 || element_id >= psDGN->element_count ) return FALSE; if( VSIFSeek( psDGN->fp, psDGN->element_index[element_id].offset, SEEK_SET ) != 0 ) return FALSE; psDGN->next_element_id = element_id; psDGN->in_complex_group = FALSE; return TRUE;}/************************************************************************//* DGNLoadRawElement() *//************************************************************************/int DGNLoadRawElement( DGNInfo *psDGN, int *pnType, int *pnLevel ){/* -------------------------------------------------------------------- *//* Read the first four bytes to get the level, type, and word *//* count. *//* -------------------------------------------------------------------- */ int nType, nWords, nLevel; if( VSIFRead( psDGN->abyElem, 1, 4, psDGN->fp ) != 4 ) return FALSE; /* Is this an 0xFFFF endof file marker? */ if( psDGN->abyElem[0] == 0xff && psDGN->abyElem[1] == 0xff ) return FALSE; nWords = psDGN->abyElem[2] + psDGN->abyElem[3]*256; nType = psDGN->abyElem[1] & 0x7f; nLevel = psDGN->abyElem[0] & 0x3f;/* -------------------------------------------------------------------- *//* Read the rest of the element data into the working buffer. *//* -------------------------------------------------------------------- */ CPLAssert( nWords * 2 + 4 <= (int) sizeof(psDGN->abyElem) ); if( (int) VSIFRead( psDGN->abyElem + 4, 2, nWords, psDGN->fp ) != nWords ) return FALSE; psDGN->nElemBytes = nWords * 2 + 4; psDGN->next_element_id++;/* -------------------------------------------------------------------- *//* Return requested info. *//* -------------------------------------------------------------------- */ if( pnType != NULL ) *pnType = nType; if( pnLevel != NULL ) *pnLevel = nLevel; return TRUE;}/************************************************************************//* DGNGetRawExtents() *//* *//* Returns FALSE if the element type does not have reconisable *//* element extents, other TRUE and the extents will be updated. *//* *//* It is assumed the raw element data has been loaded into the *//* working area by DGNLoadRawElement(). *//************************************************************************/static int DGNGetRawExtents( DGNInfo *psDGN, int nType, unsigned char *pabyRawData, GUInt32 *pnXMin, GUInt32 *pnYMin, GUInt32 *pnZMin, GUInt32 *pnXMax, GUInt32 *pnYMax, GUInt32 *pnZMax ){ if( pabyRawData == NULL ) pabyRawData = psDGN->abyElem + 0; switch( nType ) { case DGNT_LINE: case DGNT_LINE_STRING: case DGNT_SHAPE: case DGNT_CURVE: case DGNT_BSPLINE_POLE: case DGNT_BSPLINE_SURFACE_HEADER: case DGNT_BSPLINE_CURVE_HEADER: case DGNT_ELLIPSE: case DGNT_ARC: case DGNT_TEXT: case DGNT_TEXT_NODE: case DGNT_COMPLEX_CHAIN_HEADER: case DGNT_COMPLEX_SHAPE_HEADER: case DGNT_CONE: case DGNT_3DSURFACE_HEADER: case DGNT_3DSOLID_HEADER: *pnXMin = DGN_INT32( pabyRawData + 4 ); *pnYMin = DGN_INT32( pabyRawData + 8 ); if( pnZMin != NULL ) *pnZMin = DGN_INT32( pabyRawData + 12 ); *pnXMax = DGN_INT32( pabyRawData + 16 ); *pnYMax = DGN_INT32( pabyRawData + 20 ); if( pnZMax != NULL ) *pnZMax = DGN_INT32( pabyRawData + 24 ); return TRUE; default: return FALSE; }}/************************************************************************//* DGNGetElementExtents() *//************************************************************************//** * Fetch extents of an element. * * This function will return the extents of the passed element if possible. * The extents are extracted from the element header if it contains them, * and transformed into master georeferenced format. Some element types * do not have extents at all and will fail. * * This call will also fail if the extents raw data for the element is not * available. This will occur if it was not the most recently read element, * and if the raw_data field is not loaded. * * @param hDGN the handle of the file to read from. * * @param psElement the element to extract extents from. * * @param psMin structure loaded with X, Y and Z minimum values for the * extent. * * @param psMax structure loaded with X, Y and Z maximum values for the * extent. * * @return TRUE on success of FALSE if extracting extents fails. */int DGNGetElementExtents( DGNHandle hDGN, DGNElemCore *psElement, DGNPoint *psMin, DGNPoint *psMax ){ DGNInfo *psDGN = (DGNInfo *) hDGN; GUInt32 anMin[3], anMax[3]; int bResult;/* -------------------------------------------------------------------- *//* Get the extents if we have raw data in the element, or *//* loaded in the file buffer. *//* -------------------------------------------------------------------- */ if( psElement->raw_data != NULL ) bResult = DGNGetRawExtents( psDGN, psElement->type, psElement->raw_data, anMin + 0, anMin + 1, anMin + 2, anMax + 0, anMax + 1, anMax + 2 ); else if( psElement->element_id == psDGN->next_element_id - 1 ) bResult = DGNGetRawExtents( psDGN, psElement->type, psDGN->abyElem + 0, anMin + 0, anMin + 1, anMin + 2, anMax + 0, anMax + 1, anMax + 2 ); else { CPLError(CE_Warning, CPLE_AppDefined, "DGNGetElementExtents() fails because the requested element\n" " does not have raw data available." ); return FALSE; } if( !bResult ) return FALSE;/* -------------------------------------------------------------------- *//* Transform to user coordinate system and return. The offset *//* is to convert from "binary offset" form to twos complement. *//* -------------------------------------------------------------------- */ psMin->x = anMin[0] - 2147483648.0; psMin->y = anMin[1] - 2147483648.0; psMin->z = anMin[2] - 2147483648.0; psMax->x = anMax[0] - 2147483648.0; psMax->y = anMax[1] - 2147483648.0; psMax->z = anMax[2] - 2147483648.0; DGNTransformPoint( psDGN, psMin ); DGNTransformPoint( psDGN, psMax ); return TRUE;}/************************************************************************//* DGNProcessElement() *//* *//* Assumes the raw element data has already been loaded, and *//* tries to convert it into an element structure. *//************************************************************************/static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel ){ DGNElemCore *psElement = NULL;/* -------------------------------------------------------------------- *//* Handle based on element type. *//* -------------------------------------------------------------------- */ switch( nType ) { case DGNT_CELL_HEADER: { DGNElemCellHeader *psCell; psCell = (DGNElemCellHeader *) CPLCalloc(sizeof(DGNElemCellHeader),1); psElement = (DGNElemCore *) psCell; psElement->stype = DGNST_CELL_HEADER; DGNParseCore( psDGN, psElement ); psCell->totlength = psDGN->abyElem[36] + psDGN->abyElem[37] * 256; DGNRad50ToAscii( psDGN->abyElem[38] + psDGN->abyElem[39] * 256, psCell->name + 0 ); DGNRad50ToAscii( psDGN->abyElem[40] + psDGN->abyElem[41] * 256, psCell->name + 3 ); psCell->cclass = psDGN->abyElem[42] + psDGN->abyElem[43] * 256; psCell->levels[0] = psDGN->abyElem[44] + psDGN->abyElem[45] * 256; psCell->levels[1] = psDGN->abyElem[46] + psDGN->abyElem[47] * 256; psCell->levels[2] = psDGN->abyElem[48] + psDGN->abyElem[49] * 256; psCell->levels[3] = psDGN->abyElem[50] + psDGN->abyElem[51] * 256; if( psDGN->dimension == 2 ) { psCell->rnglow.x = DGN_INT32( psDGN->abyElem + 52 ); psCell->rnglow.y = DGN_INT32( psDGN->abyElem + 56 ); psCell->rnghigh.x = DGN_INT32( psDGN->abyElem + 60 ); psCell->rnghigh.y = DGN_INT32( psDGN->abyElem + 64 ); psCell->trans[0] = 1.0 * DGN_INT32( psDGN->abyElem + 68 ) / (1<<31); psCell->trans[1] = 1.0 * DGN_INT32( psDGN->abyElem + 72 ) / (1<<31); psCell->trans[2] = 1.0 * DGN_INT32( psDGN->abyElem + 76 ) / (1<<31); psCell->trans[3] = 1.0 * DGN_INT32( psDGN->abyElem + 80 ) / (1<<31); psCell->origin.x = DGN_INT32( psDGN->abyElem + 84 ); psCell->origin.y = DGN_INT32( psDGN->abyElem + 88 ); { double a, b, c, d, a2, c2; a = DGN_INT32( psDGN->abyElem + 68 ); b = DGN_INT32( psDGN->abyElem + 72 ); c = DGN_INT32( psDGN->abyElem + 76 ); d = DGN_INT32( psDGN->abyElem + 80 ); a2 = a * a; c2 = c * c; psCell->xscale = sqrt(a2 + c2) / 214748; psCell->yscale = sqrt(b*b + d*d) / 214748; if( (a2 + c2) <= 0.0 ) psCell->rotation = 0.0; else psCell->rotation = acos(a / sqrt(a2 + c2)); if (b <= 0) psCell->rotation = psCell->rotation * 180 / PI; else psCell->rotation = 360 - psCell->rotation * 180 / PI; } } else { psCell->rnglow.x = DGN_INT32( psDGN->abyElem + 52 ); psCell->rnglow.y = DGN_INT32( psDGN->abyElem + 56 ); psCell->rnglow.z = DGN_INT32( psDGN->abyElem + 60 ); psCell->rnghigh.x = DGN_INT32( psDGN->abyElem + 64 ); psCell->rnghigh.y = DGN_INT32( psDGN->abyElem + 68 ); psCell->rnghigh.z = DGN_INT32( psDGN->abyElem + 72 ); psCell->trans[0] = 1.0 * DGN_INT32( psDGN->abyElem + 76 ) / (1<<31); psCell->trans[1] = 1.0 * DGN_INT32( psDGN->abyElem + 80 ) / (1<<31); psCell->trans[2] = 1.0 * DGN_INT32( psDGN->abyElem + 84 ) / (1<<31); psCell->trans[3] = 1.0 * DGN_INT32( psDGN->abyElem + 88 ) / (1<<31); psCell->trans[4] = 1.0 * DGN_INT32( psDGN->abyElem + 92 ) / (1<<31); psCell->trans[5] = 1.0 * DGN_INT32( psDGN->abyElem + 96 ) / (1<<31); psCell->trans[6] =
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?