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 + -
显示快捷键?