LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/dgn - dgnhelp.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 386 51 13.2 %
Date: 2011-12-18 Functions: 13 4 30.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: dgnhelp.cpp 15591 2008-10-24 19:43:56Z warmerdam $
       3                 :  *
       4                 :  * Project:  Microstation DGN Access Library
       5                 :  * Purpose:  Application visible helper functions for parsing DGN information.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, Avenza Systems Inc, http://www.avenza.com/
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "dgnlibp.h"
      31                 : 
      32                 : CPL_CVSID("$Id: dgnhelp.cpp 15591 2008-10-24 19:43:56Z warmerdam $");
      33                 : 
      34                 : static unsigned char abyDefaultPCT[256][3] = 
      35                 : {
      36                 :   {255,255,255},
      37                 :   {0,0,255},
      38                 :   {0,255,0},
      39                 :   {255,0,0},
      40                 :   {255,255,0},
      41                 :   {255,0,255},
      42                 :   {255,127,0},
      43                 :   {0,255,255},
      44                 :   {64,64,64},
      45                 :   {192,192,192},
      46                 :   {254,0,96},
      47                 :   {160,224,0},
      48                 :   {0,254,160},
      49                 :   {128,0,160},
      50                 :   {176,176,176},
      51                 :   {0,240,240},
      52                 :   {240,240,240},
      53                 :   {0,0,240},
      54                 :   {0,240,0},
      55                 :   {240,0,0},
      56                 :   {240,240,0},
      57                 :   {240,0,240},
      58                 :   {240,122,0},
      59                 :   {0,240,240},
      60                 :   {240,240,240},
      61                 :   {0,0,240},
      62                 :   {0,240,0},
      63                 :   {240,0,0},
      64                 :   {240,240,0},
      65                 :   {240,0,240},
      66                 :   {240,122,0},
      67                 :   {0,225,225},
      68                 :   {225,225,225},
      69                 :   {0,0,225},
      70                 :   {0,225,0},
      71                 :   {225,0,0},
      72                 :   {225,225,0},
      73                 :   {225,0,225},
      74                 :   {225,117,0},
      75                 :   {0,225,225},
      76                 :   {225,225,225},
      77                 :   {0,0,225},
      78                 :   {0,225,0},
      79                 :   {225,0,0},
      80                 :   {225,225,0},
      81                 :   {225,0,225},
      82                 :   {225,117,0},
      83                 :   {0,210,210},
      84                 :   {210,210,210},
      85                 :   {0,0,210},
      86                 :   {0,210,0},
      87                 :   {210,0,0},
      88                 :   {210,210,0},
      89                 :   {210,0,210},
      90                 :   {210,112,0},
      91                 :   {0,210,210},
      92                 :   {210,210,210},
      93                 :   {0,0,210},
      94                 :   {0,210,0},
      95                 :   {210,0,0},
      96                 :   {210,210,0},
      97                 :   {210,0,210},
      98                 :   {210,112,0},
      99                 :   {0,195,195},
     100                 :   {195,195,195},
     101                 :   {0,0,195},
     102                 :   {0,195,0},
     103                 :   {195,0,0},
     104                 :   {195,195,0},
     105                 :   {195,0,195},
     106                 :   {195,107,0},
     107                 :   {0,195,195},
     108                 :   {195,195,195},
     109                 :   {0,0,195},
     110                 :   {0,195,0},
     111                 :   {195,0,0},
     112                 :   {195,195,0},
     113                 :   {195,0,195},
     114                 :   {195,107,0},
     115                 :   {0,180,180},
     116                 :   {180,180,180},
     117                 :   {0,0,180},
     118                 :   {0,180,0},
     119                 :   {180,0,0},
     120                 :   {180,180,0},
     121                 :   {180,0,180},
     122                 :   {180,102,0},
     123                 :   {0,180,180},
     124                 :   {180,180,180},
     125                 :   {0,0,180},
     126                 :   {0,180,0},
     127                 :   {180,0,0},
     128                 :   {180,180,0},
     129                 :   {180,0,180},
     130                 :   {180,102,0},
     131                 :   {0,165,165},
     132                 :   {165,165,165},
     133                 :   {0,0,165},
     134                 :   {0,165,0},
     135                 :   {165,0,0},
     136                 :   {165,165,0},
     137                 :   {165,0,165},
     138                 :   {165,97,0},
     139                 :   {0,165,165},
     140                 :   {165,165,165},
     141                 :   {0,0,165},
     142                 :   {0,165,0},
     143                 :   {165,0,0},
     144                 :   {165,165,0},
     145                 :   {165,0,165},
     146                 :   {165,97,0},
     147                 :   {0,150,150},
     148                 :   {150,150,150},
     149                 :   {0,0,150},
     150                 :   {0,150,0},
     151                 :   {150,0,0},
     152                 :   {150,150,0},
     153                 :   {150,0,150},
     154                 :   {150,92,0},
     155                 :   {0,150,150},
     156                 :   {150,150,150},
     157                 :   {0,0,150},
     158                 :   {0,150,0},
     159                 :   {150,0,0},
     160                 :   {150,150,0},
     161                 :   {150,0,150},
     162                 :   {150,92,0},
     163                 :   {0,135,135},
     164                 :   {135,135,135},
     165                 :   {0,0,135},
     166                 :   {0,135,0},
     167                 :   {135,0,0},
     168                 :   {135,135,0},
     169                 :   {135,0,135},
     170                 :   {135,87,0},
     171                 :   {0,135,135},
     172                 :   {135,135,135},
     173                 :   {0,0,135},
     174                 :   {0,135,0},
     175                 :   {135,0,0},
     176                 :   {135,135,0},
     177                 :   {135,0,135},
     178                 :   {135,87,0},
     179                 :   {0,120,120},
     180                 :   {120,120,120},
     181                 :   {0,0,120},
     182                 :   {0,120,0},
     183                 :   {120,0,0},
     184                 :   {120,120,0},
     185                 :   {120,0,120},
     186                 :   {120,82,0},
     187                 :   {0,120,120},
     188                 :   {120,120,120},
     189                 :   {0,0,120},
     190                 :   {0,120,0},
     191                 :   {120,0,0},
     192                 :   {120,120,0},
     193                 :   {120,0,120},
     194                 :   {120,82,0},
     195                 :   {0,105,105},
     196                 :   {105,105,105},
     197                 :   {0,0,105},
     198                 :   {0,105,0},
     199                 :   {105,0,0},
     200                 :   {105,105,0},
     201                 :   {105,0,105},
     202                 :   {105,77,0},
     203                 :   {0,105,105},
     204                 :   {105,105,105},
     205                 :   {0,0,105},
     206                 :   {0,105,0},
     207                 :   {105,0,0},
     208                 :   {105,105,0},
     209                 :   {105,0,105},
     210                 :   {105,77,0},
     211                 :   {0,90,90},
     212                 :   {90,90,90},
     213                 :   {0,0,90},
     214                 :   {0,90,0},
     215                 :   {90,0,0},
     216                 :   {90,90,0},
     217                 :   {90,0,90},
     218                 :   {90,72,0},
     219                 :   {0,90,90},
     220                 :   {90,90,90},
     221                 :   {0,0,90},
     222                 :   {0,90,0},
     223                 :   {90,0,0},
     224                 :   {90,90,0},
     225                 :   {90,0,90},
     226                 :   {90,72,0},
     227                 :   {0,75,75},
     228                 :   {75,75,75},
     229                 :   {0,0,75},
     230                 :   {0,75,0},
     231                 :   {75,0,0},
     232                 :   {75,75,0},
     233                 :   {75,0,75},
     234                 :   {75,67,0},
     235                 :   {0,75,75},
     236                 :   {75,75,75},
     237                 :   {0,0,75},
     238                 :   {0,75,0},
     239                 :   {75,0,0},
     240                 :   {75,75,0},
     241                 :   {75,0,75},
     242                 :   {75,67,0},
     243                 :   {0,60,60},
     244                 :   {60,60,60},
     245                 :   {0,0,60},
     246                 :   {0,60,0},
     247                 :   {60,0,0},
     248                 :   {60,60,0},
     249                 :   {60,0,60},
     250                 :   {60,62,0},
     251                 :   {0,60,60},
     252                 :   {60,60,60},
     253                 :   {0,0,60},
     254                 :   {0,60,0},
     255                 :   {60,0,0},
     256                 :   {60,60,0},
     257                 :   {60,0,60},
     258                 :   {60,62,0},
     259                 :   {0,45,45},
     260                 :   {45,45,45},
     261                 :   {0,0,45},
     262                 :   {0,45,0},
     263                 :   {45,0,0},
     264                 :   {45,45,0},
     265                 :   {45,0,45},
     266                 :   {45,57,0},
     267                 :   {0,45,45},
     268                 :   {45,45,45},
     269                 :   {0,0,45},
     270                 :   {0,45,0},
     271                 :   {45,0,0},
     272                 :   {45,45,0},
     273                 :   {45,0,45},
     274                 :   {45,57,0},
     275                 :   {0,30,30},
     276                 :   {30,30,30},
     277                 :   {0,0,30},
     278                 :   {0,30,0},
     279                 :   {30,0,0},
     280                 :   {30,30,0},
     281                 :   {30,0,30},
     282                 :   {30,52,0},
     283                 :   {0,30,30},
     284                 :   {30,30,30},
     285                 :   {0,0,30},
     286                 :   {0,30,0},
     287                 :   {30,0,0},
     288                 :   {30,30,0},
     289                 :   {30,0,30},
     290                 :   {192,192,192},
     291                 :   {28,0,100}
     292                 : };
     293                 : 
     294                 : 
     295                 : /************************************************************************/
     296                 : /*                           DGNLookupColor()                           */
     297                 : /************************************************************************/
     298                 : 
     299                 : /**
     300                 :  * Translate color index into RGB values.
     301                 :  *
     302                 :  * If no color table has yet been encountered in the file a hard-coded
     303                 :  * "default" color table will be used.  This seems to be what Microstation
     304                 :  * uses as a color table when there isn't one in a DGN file but I am not
     305                 :  * absolutely convinced it is appropriate.
     306                 :  *
     307                 :  * @param hDGN the file.
     308                 :  * @param color_index the color index to lookup.
     309                 :  * @param red location to put red component.
     310                 :  * @param green location to put green component.
     311                 :  * @param blue location to put blue component.
     312                 :  *
     313                 :  * @return TRUE on success or FALSE on failure.  May fail if color_index is
     314                 :  * out of range.
     315                 :  */
     316                 : 
     317              92 : int DGNLookupColor( DGNHandle hDGN, int color_index, 
     318                 :                     int * red, int * green, int * blue )
     319                 : 
     320                 : {
     321              92 :     DGNInfo     *psDGN = (DGNInfo *) hDGN;
     322                 : 
     323              92 :     if( color_index < 0 || color_index > 255  )
     324               0 :         return FALSE;
     325                 : 
     326              92 :     if( !psDGN->got_color_table )
     327                 :     {
     328              92 :         *red = abyDefaultPCT[color_index][0];
     329              92 :         *green = abyDefaultPCT[color_index][1];
     330              92 :         *blue = abyDefaultPCT[color_index][2];
     331                 :     }
     332                 :     else
     333                 :     {
     334               0 :         *red = psDGN->color_table[color_index][0];
     335               0 :         *green = psDGN->color_table[color_index][1];
     336               0 :         *blue = psDGN->color_table[color_index][2];
     337                 :     }
     338                 : 
     339              92 :     return TRUE;
     340                 : }
     341                 : 
     342                 : /************************************************************************/
     343                 : /*                        DGNGetShapeFillInfo()                         */
     344                 : /************************************************************************/
     345                 : 
     346                 : /**
     347                 :  * Fetch fill color for a shape.
     348                 :  *
     349                 :  * This method will check for a 0x0041 user attribute linkaged with fill
     350                 :  * color information for the element.  If found the function returns TRUE,
     351                 :  * and places the fill color in *pnColor, otherwise FALSE is returned and
     352                 :  * *pnColor is not updated.
     353                 :  *
     354                 :  * @param hDGN the file.
     355                 :  * @param psElem the element.
     356                 :  * @param pnColor the location to return the fill color. 
     357                 :  *
     358                 :  * @return TRUE on success or FALSE on failure.
     359                 :  */
     360                 : 
     361               6 : int DGNGetShapeFillInfo( DGNHandle hDGN, DGNElemCore *psElem, int *pnColor )
     362                 : 
     363                 : {
     364                 :     int iLink;
     365                 :     
     366               7 :     for( iLink = 0; TRUE; iLink++ )
     367                 :     {
     368                 :         int nLinkType, nLinkSize;
     369                 :         unsigned char *pabyData;
     370                 : 
     371                 :         pabyData = DGNGetLinkage( hDGN, psElem, iLink, &nLinkType, 
     372               7 :                                   NULL, NULL, &nLinkSize );
     373               7 :         if( pabyData == NULL )
     374               2 :             return FALSE;
     375                 : 
     376               5 :         if( nLinkType == DGNLT_SHAPE_FILL && nLinkSize >= 7 )
     377                 :         {
     378               4 :             *pnColor = pabyData[8];
     379               4 :             return TRUE;
     380                 :         }
     381                 :     }
     382                 : }
     383                 : 
     384                 : /************************************************************************/
     385                 : /*                        DGNGetAssocID()                               */
     386                 : /************************************************************************/
     387                 : 
     388                 : /**
     389                 :  * Fetch association id for an element.
     390                 :  *
     391                 :  * This method will check if an element has an association id, and if so
     392                 :  * returns it, otherwise returning -1.  Association ids are kept as a
     393                 :  * user attribute linkage where present.
     394                 :  *
     395                 :  * @param hDGN the file.
     396                 :  * @param psElem the element.
     397                 :  *
     398                 :  * @return The id or -1 on failure.
     399                 :  */
     400                 : 
     401               0 : int DGNGetAssocID( DGNHandle hDGN, DGNElemCore *psElem )
     402                 : 
     403                 : {
     404                 :     int iLink;
     405                 :     
     406               0 :     for( iLink = 0; TRUE; iLink++ )
     407                 :     {
     408                 :         int nLinkType, nLinkSize;
     409                 :         unsigned char *pabyData;
     410                 : 
     411                 :         pabyData = DGNGetLinkage( hDGN, psElem, iLink, &nLinkType, 
     412               0 :                                   NULL, NULL, &nLinkSize );
     413               0 :         if( pabyData == NULL )
     414               0 :             return -1;
     415                 : 
     416               0 :         if( nLinkType == DGNLT_ASSOC_ID && nLinkSize >= 8 )
     417                 :         {
     418               0 :             return pabyData[4] 
     419               0 :                 + pabyData[5] * 256 
     420               0 :                 + pabyData[6]*256*256
     421               0 :                 + pabyData[7] * 256*256*256;
     422                 :         }
     423                 :     }
     424                 : }
     425                 : 
     426                 : /************************************************************************/
     427                 : /*                          DGNRad50ToAscii()                           */
     428                 : /*                                                                      */
     429                 : /*      Convert one 16-bits Radix-50 to ASCII (3 chars).                */
     430                 : /************************************************************************/
     431                 : 
     432               0 : void DGNRad50ToAscii(unsigned short sRad50, char *str )
     433                 : {
     434                 :     unsigned short sValue;
     435               0 :     char           ch = '\0';
     436               0 :     unsigned short saQuots[3] = {1600,40,1};
     437                 :     int i;
     438                 : 
     439               0 :     for ( i=0; i<3; i++)
     440                 :     {
     441               0 :         sValue = sRad50;
     442               0 :         sValue /= saQuots[i];
     443                 :         /* Map 0..39 to ASCII */
     444               0 :         if (sValue==0)                     
     445               0 :             ch = ' ';          /* space */
     446               0 :         else if (sValue >= 1 && sValue <= 26) 
     447               0 :             ch = (char) (sValue-1+'A');/* printable alpha A..Z */
     448               0 :         else if (sValue == 27)             
     449               0 :             ch = '$';          /* dollar */
     450               0 :         else if (sValue == 28)             
     451               0 :             ch = '.';          /* period */
     452               0 :         else if (sValue == 29)             
     453               0 :             ch = ' ';          /* unused char, emit a space instead */
     454               0 :         else if (sValue >= 30 && sValue <= 39)
     455               0 :             ch = (char) (sValue-30+'0');   /* digit 0..9 */
     456               0 :         *str = ch;
     457               0 :         str++;
     458                 : 
     459               0 :         sRad50-=(sValue*saQuots[i]);
     460                 :     }
     461                 : 
     462                 :     /* Do zero-terminate */
     463               0 :     *str = '\0';
     464               0 : }
     465                 : 
     466                 : /************************************************************************/
     467                 : /*                          DGNAsciiToRad50()                           */
     468                 : /************************************************************************/
     469                 : 
     470               0 : void DGNAsciiToRad50( const char *str, unsigned short *pRad50 )
     471                 : 
     472                 : {
     473               0 :     unsigned short rad50 = 0;
     474                 :     int  i;
     475                 : 
     476               0 :     for( i = 0; i < 3; i++ )
     477                 :     {
     478                 :         unsigned short value;
     479                 : 
     480               0 :         if( i >= (int) strlen(str) )
     481                 :         {
     482               0 :             rad50 = rad50 * 40;
     483               0 :             continue;
     484                 :         }
     485                 : 
     486               0 :         if( str[i] == '$' )
     487               0 :             value = 27;
     488               0 :         else if( str[i] == '.' )
     489               0 :             value = 28;
     490               0 :         else if( str[i] == ' ' )
     491               0 :             value = 29;
     492               0 :         else if( str[i] >= '0' && str[i] <= '9' )
     493               0 :             value = str[i] - '0' + 30;
     494               0 :         else if( str[i] >= 'a' && str[i] <= 'z' )
     495               0 :             value = str[i] - 'a' + 1;
     496               0 :         else if( str[i] >= 'A' && str[i] <= 'Z' )
     497               0 :             value = str[i] - 'A' + 1;
     498                 :         else
     499               0 :             value = 0;
     500                 : 
     501               0 :         rad50 = rad50 * 40 + value;
     502                 :     }
     503                 : 
     504               0 :     *pRad50 = rad50;
     505               0 : }
     506                 : 
     507                 : 
     508                 : /************************************************************************/
     509                 : /*                        DGNGetLineStyleName()                         */
     510                 : /*                                                                      */
     511                 : /*      Read the line style name from symbol table.                     */
     512                 : /*      The got name is stored in psLine.                               */
     513                 : /************************************************************************/
     514                 : 
     515               0 : int DGNGetLineStyleName(DGNInfo *psDGN, DGNElemMultiPoint *psLine,
     516                 :                         char szLineStyle[65] )
     517                 : {
     518               0 :     if (psLine->core.attr_bytes > 0 &&
     519               0 :         psLine->core.attr_data[1] == 0x10 &&
     520               0 :         psLine->core.attr_data[2] == 0xf9 &&
     521               0 :         psLine->core.attr_data[3] == 0x79)
     522                 :     {
     523                 : #ifdef notdef
     524                 :         for (int i=0;i<SYMBOL_TABLE_SIZE;i++)
     525                 :         {
     526                 :             if (*((unsigned char*)psDGN->buffer + 0x21e5 + i) == psLine->core.attr_data[4] &&
     527                 :                 *((unsigned char*)psDGN->buffer + 0x21e6 + i) == psLine->core.attr_data[5] &&
     528                 :                 *((unsigned char*)psDGN->buffer + 0x21e7 + i) == psLine->core.attr_data[6] &&
     529                 :                 *((unsigned char*)psDGN->buffer + 0x21e8 + i) == psLine->core.attr_data[7])
     530                 :             {
     531                 :                 memcpy( szLineStyle, 
     532                 :                         (unsigned char*)psDGN->buffer + 0x21e9 + i, 64 );
     533                 :                 szLineStyle[64] = '\0';
     534                 :                 return TRUE;
     535                 :             }
     536                 :         }
     537                 : #endif
     538               0 :         return FALSE;
     539                 :     }
     540                 :     else
     541                 :     {
     542               0 :         szLineStyle[0] = '\0';
     543               0 :         return FALSE;
     544                 :     }
     545                 : }
     546                 : 
     547                 : /************************************************************************/
     548                 : /*                           DGNDumpElement()                           */
     549                 : /************************************************************************/
     550                 : 
     551                 : /**
     552                 :  * Emit textual report of an element.
     553                 :  *
     554                 :  * This function exists primarily for debugging, and will produce a textual
     555                 :  * report about any element type to the designated file. 
     556                 :  *
     557                 :  * @param hDGN the file from which the element originated.
     558                 :  * @param psElement the element to report on.
     559                 :  * @param fp the file (such as stdout) to report the element information to.
     560                 :  */
     561                 : 
     562               0 : void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
     563                 : 
     564                 : {
     565               0 :     DGNInfo *psInfo = (DGNInfo *) hDGN;
     566                 : 
     567               0 :     fprintf( fp, "\n" );
     568                 :     fprintf( fp, "Element:%-12s Level:%2d id:%-6d ",
     569                 :              DGNTypeToName( psElement->type ),
     570                 :              psElement->level, 
     571               0 :              psElement->element_id );
     572                 : 
     573               0 :     if( psElement->complex )
     574               0 :         fprintf( fp, "(Complex) " );
     575                 : 
     576               0 :     if( psElement->deleted )
     577               0 :         fprintf( fp, "(DELETED) " );
     578                 : 
     579               0 :     fprintf( fp, "\n" );
     580                 : 
     581                 :     fprintf( fp, "  offset=%d  size=%d bytes\n", 
     582               0 :              psElement->offset, psElement->size );
     583                 : 
     584                 :     fprintf( fp, 
     585                 :              "  graphic_group:%-3d color:%d weight:%d style:%d\n", 
     586                 :              psElement->graphic_group,
     587                 :              psElement->color,
     588                 :              psElement->weight,
     589               0 :              psElement->style );
     590                 : 
     591               0 :     if( psElement->properties != 0 )
     592                 :     {
     593                 :         int     nClass;
     594                 : 
     595               0 :         fprintf( fp, "  properties=%d", psElement->properties );
     596               0 :         if( psElement->properties & DGNPF_HOLE )
     597               0 :             fprintf( fp, ",HOLE" );
     598               0 :         if( psElement->properties & DGNPF_SNAPPABLE )
     599               0 :             fprintf( fp, ",SNAPPABLE" );
     600               0 :         if( psElement->properties & DGNPF_PLANAR )
     601               0 :             fprintf( fp, ",PLANAR" );
     602               0 :         if( psElement->properties & DGNPF_ORIENTATION )
     603               0 :             fprintf( fp, ",ORIENTATION" );
     604               0 :         if( psElement->properties & DGNPF_ATTRIBUTES )
     605               0 :             fprintf( fp, ",ATTRIBUTES" );
     606               0 :         if( psElement->properties & DGNPF_MODIFIED )
     607               0 :             fprintf( fp, ",MODIFIED" );
     608               0 :         if( psElement->properties & DGNPF_NEW )
     609               0 :             fprintf( fp, ",NEW" );
     610               0 :         if( psElement->properties & DGNPF_LOCKED )
     611               0 :             fprintf( fp, ",LOCKED" );
     612                 : 
     613               0 :         nClass = psElement->properties & DGNPF_CLASS;
     614               0 :         if( nClass == DGNC_PATTERN_COMPONENT )
     615               0 :             fprintf( fp, ",PATTERN_COMPONENT" );
     616               0 :         else if( nClass == DGNC_CONSTRUCTION_ELEMENT )
     617               0 :             fprintf( fp, ",CONSTRUCTION ELEMENT" );
     618               0 :         else if( nClass == DGNC_DIMENSION_ELEMENT )
     619               0 :             fprintf( fp, ",DIMENSION ELEMENT" );
     620               0 :         else if( nClass == DGNC_PRIMARY_RULE_ELEMENT )
     621               0 :             fprintf( fp, ",PRIMARY RULE ELEMENT" );
     622               0 :         else if( nClass == DGNC_LINEAR_PATTERNED_ELEMENT )
     623               0 :             fprintf( fp, ",LINEAR PATTERNED ELEMENT" );
     624               0 :         else if( nClass == DGNC_CONSTRUCTION_RULE_ELEMENT )
     625               0 :             fprintf( fp, ",CONSTRUCTION_RULE_ELEMENT" );
     626                 :             
     627               0 :         fprintf( fp, "\n" );
     628                 :     }
     629                 : 
     630               0 :     switch( psElement->stype )
     631                 :     {
     632                 :       case DGNST_MULTIPOINT:
     633                 :       {
     634               0 :           DGNElemMultiPoint     *psLine = (DGNElemMultiPoint *) psElement;
     635                 :           int                   i;
     636                 :           
     637               0 :           for( i=0; i < psLine->num_vertices; i++ )
     638                 :               fprintf( fp, "  (%.6f,%.6f,%.6f)\n", 
     639                 :                        psLine->vertices[i].x, 
     640                 :                        psLine->vertices[i].y, 
     641               0 :                        psLine->vertices[i].z );
     642                 :       }
     643               0 :       break;
     644                 : 
     645                 :       case DGNST_CELL_HEADER:
     646                 :       {
     647               0 :           DGNElemCellHeader     *psCell = (DGNElemCellHeader*) psElement;
     648                 : 
     649                 :           fprintf( fp, "  totlength=%d, name=%s, class=%x, levels=%02x%02x%02x%02x\n",
     650                 :                    psCell->totlength, psCell->name, psCell->cclass,
     651               0 :                    psCell->levels[0], psCell->levels[1], psCell->levels[2],
     652               0 :                    psCell->levels[3] );
     653                 :           fprintf( fp, "  rnglow=(%.5f,%.5f,%.5f)\n"
     654                 :                        "  rnghigh=(%.5f,%.5f,%.5f)\n",
     655                 :                    psCell->rnglow.x, psCell->rnglow.y, psCell->rnglow.z,
     656               0 :                    psCell->rnghigh.x, psCell->rnghigh.y, psCell->rnghigh.z );
     657                 :           fprintf( fp, "  origin=(%.5f,%.5f,%.5f)\n",
     658               0 :                    psCell->origin.x, psCell->origin.y, psCell->origin.z);
     659                 :           
     660               0 :           if( psInfo->dimension == 2 )
     661                 :               fprintf( fp, "  xscale=%g, yscale=%g, rotation=%g\n",
     662               0 :                        psCell->xscale, psCell->yscale, psCell->rotation );
     663                 :           else
     664                 :               fprintf( fp, "  trans=%g,%g,%g,%g,%g,%g,%g,%g,%g\n",
     665                 :                        psCell->trans[0],
     666                 :                        psCell->trans[1],
     667                 :                        psCell->trans[2],
     668                 :                        psCell->trans[3],
     669                 :                        psCell->trans[4],
     670                 :                        psCell->trans[5],
     671                 :                        psCell->trans[6],
     672                 :                        psCell->trans[7],
     673               0 :                        psCell->trans[8] );
     674                 :       }
     675               0 :       break;
     676                 : 
     677                 :       case DGNST_CELL_LIBRARY:
     678                 :       {
     679               0 :           DGNElemCellLibrary    *psCell = (DGNElemCellLibrary*) psElement;
     680                 : 
     681                 :           fprintf( fp, 
     682                 :                    "  name=%s, class=%x, levels=%02x%02x%02x%02x, numwords=%d\n", 
     683                 :                    psCell->name, psCell->cclass, 
     684               0 :                    psCell->levels[0], psCell->levels[1], psCell->levels[2], 
     685               0 :                    psCell->levels[3], psCell->numwords );
     686                 :           fprintf( fp, "  dispsymb=%d, description=%s\n", 
     687               0 :                    psCell->dispsymb, psCell->description );
     688                 :       }
     689               0 :       break;
     690                 : 
     691                 :       case DGNST_SHARED_CELL_DEFN:
     692                 :       {
     693               0 :           DGNElemSharedCellDefn *psShared = (DGNElemSharedCellDefn *) psElement;
     694                 : 
     695               0 :           fprintf( fp, "  totlength=%d\n", psShared->totlength);
     696                 :       }
     697               0 :       break;
     698                 : 
     699                 :       case DGNST_ARC:
     700                 :       {
     701               0 :           DGNElemArc    *psArc = (DGNElemArc *) psElement;
     702                 : 
     703               0 :           if( psInfo->dimension == 2 )
     704                 :               fprintf( fp, "  origin=(%.5f,%.5f), rotation=%f\n",
     705                 :                        psArc->origin.x, 
     706                 :                        psArc->origin.y, 
     707               0 :                        psArc->rotation );
     708                 :           else
     709                 :               fprintf( fp, "  origin=(%.5f,%.5f,%.5f), quat=%d,%d,%d,%d\n",
     710                 :                        psArc->origin.x, 
     711                 :                        psArc->origin.y, 
     712                 :                        psArc->origin.z, 
     713                 :                        psArc->quat[0], 
     714                 :                        psArc->quat[1], 
     715                 :                        psArc->quat[2], 
     716               0 :                        psArc->quat[3] );
     717                 :           fprintf( fp, "  axes=(%.5f,%.5f), start angle=%f, sweep=%f\n", 
     718                 :                    psArc->primary_axis,
     719                 :                    psArc->secondary_axis,
     720                 :                    psArc->startang,
     721               0 :                    psArc->sweepang );                   
     722                 :       }
     723               0 :       break;
     724                 : 
     725                 :       case DGNST_TEXT:
     726                 :       {
     727               0 :           DGNElemText   *psText = (DGNElemText *) psElement;
     728                 : 
     729                 :           fprintf( fp, 
     730                 :                    "  origin=(%.5f,%.5f), rotation=%f\n"
     731                 :                    "  font=%d, just=%d, length_mult=%g, height_mult=%g\n"
     732                 :                    "  string = \"%s\"\n",
     733                 :                    psText->origin.x, 
     734                 :                    psText->origin.y, 
     735                 :                    psText->rotation,
     736                 :                    psText->font_id,
     737                 :                    psText->justification,
     738                 :                    psText->length_mult,
     739                 :                    psText->height_mult,
     740               0 :                    psText->string );
     741                 :       }
     742               0 :       break;
     743                 : 
     744                 :       case DGNST_TEXT_NODE:
     745                 :       {
     746               0 :           DGNElemTextNode *psNode = (DGNElemTextNode *) psElement;
     747                 : 
     748                 :           fprintf( fp, 
     749                 :                    "  totlength=%d, num_texts=%d\n",
     750                 :                    psNode->totlength,
     751               0 :                    psNode->numelems );
     752                 :           fprintf( fp, 
     753                 :                    "  origin=(%.5f,%.5f), rotation=%f\n"
     754                 :                    "  font=%d, just=%d, length_mult=%g, height_mult=%g\n",
     755                 :                    psNode->origin.x, 
     756                 :                    psNode->origin.y, 
     757                 :                    psNode->rotation,
     758                 :                    psNode->font_id,
     759                 :                    psNode->justification,
     760                 :                    psNode->length_mult,
     761               0 :                    psNode->height_mult );
     762                 :           fprintf( fp, 
     763                 :        "  max_length=%d, used=%d,",
     764                 :        psNode->max_length, 
     765               0 :        psNode->max_used );
     766                 :           fprintf( fp, 
     767                 :        "  node_number=%d\n", 
     768               0 :        psNode->node_number );
     769                 :       }
     770               0 :       break;
     771                 : 
     772                 :       case DGNST_COMPLEX_HEADER:
     773                 :       {
     774               0 :           DGNElemComplexHeader  *psHdr = (DGNElemComplexHeader *) psElement;
     775                 : 
     776                 :           fprintf( fp, 
     777                 :                    "  totlength=%d, numelems=%d\n",
     778                 :                    psHdr->totlength,
     779               0 :                    psHdr->numelems );
     780               0 :           if (psElement->type  == DGNT_3DSOLID_HEADER ||
     781                 :               psElement->type  == DGNT_3DSURFACE_HEADER) {
     782                 :             fprintf( fp, 
     783                 :                      "  surftype=%d, boundelms=%d\n", 
     784               0 :                      psHdr->surftype, psHdr->boundelms );
     785                 :           }
     786                 :       }
     787               0 :       break;
     788                 : 
     789                 :       case DGNST_COLORTABLE:
     790                 :       {
     791               0 :           DGNElemColorTable *psCT = (DGNElemColorTable *) psElement;
     792                 :           int                   i;
     793                 : 
     794               0 :           fprintf( fp, "  screen_flag: %d\n", psCT->screen_flag );
     795               0 :           for( i = 0; i < 256; i++ )
     796                 :           {
     797                 :               fprintf( fp, "  %3d: (%3d,%3d,%3d)\n",
     798                 :                        i, 
     799               0 :                        psCT->color_info[i][0], 
     800               0 :                        psCT->color_info[i][1], 
     801               0 :                        psCT->color_info[i][2] );
     802                 :           }
     803                 :       }
     804               0 :       break;
     805                 : 
     806                 :       case DGNST_TCB:
     807                 :       {
     808               0 :           DGNElemTCB *psTCB = (DGNElemTCB *) psElement;
     809                 :           int iView;
     810                 : 
     811               0 :           fprintf( fp, "  dimension = %d\n", psTCB->dimension );
     812                 :           fprintf( fp, "  uor_per_subunit = %ld, subunits = `%s'\n",
     813               0 :                    psTCB->uor_per_subunit, psTCB->sub_units );
     814                 :           fprintf( fp, "  subunits_per_master = %ld, master units = `%s'\n",
     815               0 :                    psTCB->subunits_per_master, psTCB->master_units );
     816                 :           fprintf( fp, "  origin = (%.5f,%.5f,%.5f)\n", 
     817                 :                    psTCB->origin_x,
     818                 :                    psTCB->origin_y,
     819               0 :                    psTCB->origin_z );
     820                 : 
     821               0 :           for( iView = 0; iView < 8; iView++ )
     822                 :           {
     823               0 :               DGNViewInfo *psView = psTCB->views + iView;
     824                 :               
     825                 :               fprintf(fp, 
     826                 :                       "  View%d: flags=%04X, levels=%02X%02X%02X%02X%02X%02X%02X%02X\n",
     827                 :                       iView,
     828                 :                       psView->flags, 
     829               0 :                       psView->levels[0],
     830               0 :                       psView->levels[1],
     831               0 :                       psView->levels[2],
     832               0 :                       psView->levels[3],
     833               0 :                       psView->levels[4],
     834               0 :                       psView->levels[5],
     835               0 :                       psView->levels[6],
     836               0 :                       psView->levels[7] );
     837                 :               fprintf(fp, 
     838                 :                       "        origin=(%g,%g,%g)\n        delta=(%g,%g,%g)\n", 
     839                 :                       psView->origin.x, psView->origin.y, psView->origin.z,
     840               0 :                       psView->delta.x, psView->delta.y, psView->delta.z );
     841                 :               fprintf(fp, 
     842                 :                       "       trans=(%g,%g,%g,%g,%g,%g,%g,%g,%g)\n",
     843                 :                       psView->transmatrx[0],
     844                 :                       psView->transmatrx[1],
     845                 :                       psView->transmatrx[2],
     846                 :                       psView->transmatrx[3],
     847                 :                       psView->transmatrx[4],
     848                 :                       psView->transmatrx[5],
     849                 :                       psView->transmatrx[6],
     850                 :                       psView->transmatrx[7],
     851               0 :                       psView->transmatrx[8] );
     852                 :           }
     853                 :       }
     854               0 :       break;
     855                 : 
     856                 :       case DGNST_TAG_SET:
     857                 :       {
     858               0 :           DGNElemTagSet *psTagSet = (DGNElemTagSet*) psElement;
     859                 :           int            iTag;
     860                 : 
     861                 :           fprintf( fp, "  tagSetName=%s, tagSet=%d, tagCount=%d, flags=%d\n", 
     862                 :                    psTagSet->tagSetName, psTagSet->tagSet, 
     863               0 :                    psTagSet->tagCount, psTagSet->flags );
     864               0 :           for( iTag = 0; iTag < psTagSet->tagCount; iTag++ )
     865                 :           {
     866               0 :               DGNTagDef *psTagDef = psTagSet->tagList + iTag;
     867                 : 
     868                 :               fprintf( fp, "    %d: name=%s, type=%d, prompt=%s", 
     869                 :                        psTagDef->id, psTagDef->name, psTagDef->type, 
     870               0 :                        psTagDef->prompt );
     871               0 :               if( psTagDef->type == 1 )
     872                 :                   fprintf( fp, ", default=%s\n", 
     873               0 :                            psTagDef->defaultValue.string );
     874               0 :               else if( psTagDef->type == 3 || psTagDef->type == 5 )
     875                 :                   fprintf( fp, ", default=%d\n", 
     876               0 :                            psTagDef->defaultValue.integer );
     877               0 :               else if( psTagDef->type == 4 )
     878                 :                   fprintf( fp, ", default=%g\n", 
     879               0 :                            psTagDef->defaultValue.real );
     880                 :               else
     881               0 :                   fprintf( fp, ", default=<unknown>\n" );
     882                 :           }
     883                 :       }
     884               0 :       break;
     885                 : 
     886                 :       case DGNST_TAG_VALUE:
     887                 :       {
     888               0 :           DGNElemTagValue *psTag = (DGNElemTagValue*) psElement;
     889                 : 
     890                 :           fprintf( fp, "  tagType=%d, tagSet=%d, tagIndex=%d, tagLength=%d\n", 
     891                 :                    psTag->tagType, psTag->tagSet, psTag->tagIndex, 
     892               0 :                    psTag->tagLength );
     893               0 :           if( psTag->tagType == 1 )
     894               0 :               fprintf( fp, "  value=%s\n", psTag->tagValue.string );
     895               0 :           else if( psTag->tagType == 3 )
     896               0 :               fprintf( fp, "  value=%d\n", psTag->tagValue.integer );
     897               0 :           else if( psTag->tagType == 4 )
     898               0 :               fprintf( fp, "  value=%g\n", psTag->tagValue.real );
     899                 :       }
     900               0 :       break;
     901                 : 
     902                 :       case DGNST_CONE:
     903                 :       {
     904               0 :           DGNElemCone *psCone = (DGNElemCone *) psElement;
     905                 : 
     906                 :           fprintf( fp, 
     907                 :                    "  center_1=(%g,%g,%g) radius=%g\n"
     908                 :                    "  center_2=(%g,%g,%g) radius=%g\n"
     909                 :                    "  quat=%d,%d,%d,%d unknown=%d\n", 
     910                 :                    psCone->center_1.x, psCone->center_1.y, psCone->center_1.z,
     911                 :                    psCone->radius_1, 
     912                 :                    psCone->center_2.x, psCone->center_2.y, psCone->center_2.z,
     913                 :                    psCone->radius_2, 
     914                 :                    psCone->quat[0], psCone->quat[1],
     915                 :                    psCone->quat[2], psCone->quat[3],
     916               0 :                    psCone->unknown );
     917                 :       }
     918               0 :       break;
     919                 : 
     920                 :       case DGNST_BSPLINE_SURFACE_HEADER:
     921                 :       {
     922                 :           DGNElemBSplineSurfaceHeader *psSpline =
     923               0 :             (DGNElemBSplineSurfaceHeader *) psElement;
     924                 : 
     925                 :           fprintf( fp, "  desc_words=%ld, curve type=%d\n",
     926               0 :                    psSpline->desc_words, psSpline->curve_type);
     927                 : 
     928                 :           fprintf( fp, "  U: properties=%02x",
     929               0 :                    psSpline->u_properties);
     930               0 :           if (psSpline->u_properties != 0) {
     931               0 :             if (psSpline->u_properties & DGNBSC_CURVE_DISPLAY) {
     932               0 :               fprintf(fp, ",CURVE_DISPLAY");
     933                 :             }
     934               0 :             if (psSpline->u_properties & DGNBSC_POLY_DISPLAY) {
     935               0 :               fprintf(fp, ",POLY_DISPLAY");
     936                 :             }
     937               0 :             if (psSpline->u_properties & DGNBSC_RATIONAL) {
     938               0 :               fprintf(fp, ",RATIONAL");
     939                 :             }
     940               0 :             if (psSpline->u_properties & DGNBSC_CLOSED) {
     941               0 :               fprintf(fp, ",CLOSED");
     942                 :             }
     943                 :           }
     944               0 :           fprintf(fp, "\n");
     945                 :           fprintf( fp, "     order=%d\n  %d poles, %d knots, %d rule lines\n",
     946                 :                    psSpline->u_order, psSpline->num_poles_u, 
     947               0 :                    psSpline->num_knots_u, psSpline->rule_lines_u);
     948                 : 
     949                 :           fprintf( fp, "  V: properties=%02x",
     950               0 :                    psSpline->v_properties);
     951               0 :           if (psSpline->v_properties != 0) {
     952               0 :             if (psSpline->v_properties & DGNBSS_ARC_SPACING) {
     953               0 :               fprintf(fp, ",ARC_SPACING");
     954                 :             }
     955               0 :             if (psSpline->v_properties & DGNBSS_CLOSED) {
     956               0 :               fprintf(fp, ",CLOSED");
     957                 :             }
     958                 :           }
     959               0 :           fprintf(fp, "\n");
     960                 :           fprintf( fp, "     order=%d\n  %d poles, %d knots, %d rule lines\n",
     961                 :                    psSpline->v_order, psSpline->num_poles_v, 
     962               0 :                    psSpline->num_knots_v, psSpline->rule_lines_v);
     963                 :       }
     964               0 :       break;
     965                 : 
     966                 :       case DGNST_BSPLINE_CURVE_HEADER:
     967                 :       {
     968                 :           DGNElemBSplineCurveHeader *psSpline =
     969               0 :             (DGNElemBSplineCurveHeader *) psElement;
     970                 : 
     971                 :           fprintf( fp, 
     972                 :                    "  desc_words=%ld, curve type=%d\n"
     973                 :                    "  properties=%02x",
     974                 :                    psSpline->desc_words, psSpline->curve_type,
     975               0 :                    psSpline->properties);
     976               0 :           if (psSpline->properties != 0) {
     977               0 :             if (psSpline->properties & DGNBSC_CURVE_DISPLAY) {
     978               0 :               fprintf(fp, ",CURVE_DISPLAY");
     979                 :             }
     980               0 :             if (psSpline->properties & DGNBSC_POLY_DISPLAY) {
     981               0 :               fprintf(fp, ",POLY_DISPLAY");
     982                 :             }
     983               0 :             if (psSpline->properties & DGNBSC_RATIONAL) {
     984               0 :               fprintf(fp, ",RATIONAL");
     985                 :             }
     986               0 :             if (psSpline->properties & DGNBSC_CLOSED) {
     987               0 :               fprintf(fp, ",CLOSED");
     988                 :             }
     989                 :           }
     990               0 :           fprintf(fp, "\n");
     991                 :           fprintf( fp, "  order=%d\n  %d poles, %d knots\n",
     992               0 :                    psSpline->order, psSpline->num_poles, psSpline->num_knots);
     993                 :       }
     994               0 :       break;
     995                 : 
     996                 :       case DGNST_BSPLINE_SURFACE_BOUNDARY:
     997                 :       {
     998                 :           DGNElemBSplineSurfaceBoundary *psBounds =
     999               0 :             (DGNElemBSplineSurfaceBoundary *) psElement;
    1000                 : 
    1001                 :           fprintf( fp, "  boundary number=%d, # vertices=%d\n",
    1002               0 :                    psBounds->number, psBounds->numverts);
    1003               0 :           for (int i=0;i<psBounds->numverts;i++) {
    1004                 :             fprintf( fp, "  (%.6f,%.6f)\n",
    1005                 :                      psBounds->vertices[i].x,
    1006               0 :                      psBounds->vertices[i].y);
    1007                 :           }
    1008                 :       }
    1009               0 :       break;
    1010                 : 
    1011                 :       case DGNST_KNOT_WEIGHT:
    1012                 :       {
    1013               0 :           DGNElemKnotWeight *psArray = (DGNElemKnotWeight *) psElement;
    1014               0 :           int numelems = (psArray->core.size-36)/4;
    1015               0 :           for (int i=0;i<numelems;i++) {
    1016               0 :             fprintf(fp, "  %.6f\n", psArray->array[i]);
    1017                 :           }
    1018                 :       }
    1019                 :       break;
    1020                 : 
    1021                 :       default:
    1022                 :         break;
    1023                 :     }
    1024                 : 
    1025               0 :     if( psElement->attr_bytes > 0 )
    1026                 :     {
    1027                 :         int iLink;
    1028                 : 
    1029               0 :         fprintf( fp, "Attributes (%d bytes):\n", psElement->attr_bytes );
    1030                 :         
    1031               0 :         for( iLink = 0; TRUE; iLink++ )
    1032                 : 
    1033                 :         {
    1034               0 :             int nLinkType, nEntityNum=0, nMSLink=0, nLinkSize, i;
    1035                 :             unsigned char *pabyData;
    1036                 : 
    1037                 :             pabyData = DGNGetLinkage( hDGN, psElement, iLink, &nLinkType, 
    1038               0 :                                       &nEntityNum, &nMSLink, &nLinkSize );
    1039               0 :             if( pabyData == NULL )
    1040               0 :                 break;
    1041                 : 
    1042               0 :             fprintf( fp, "Type=0x%04x", nLinkType );
    1043               0 :             if( nMSLink != 0 || nEntityNum != 0 )
    1044                 :                 fprintf( fp, ", EntityNum=%d, MSLink=%d", 
    1045               0 :                          nEntityNum, nMSLink );
    1046                 : 
    1047               0 :             int nBytes = psElement->attr_data + psElement->attr_bytes - pabyData;
    1048               0 :             if( nBytes < nLinkSize )
    1049                 :             {
    1050                 :                 CPLError( CE_Failure, CPLE_AppDefined,
    1051                 :                         "Corrupt linkage, element id:%d, link:%d",
    1052               0 :                         psElement->element_id, iLink);
    1053                 :                 fprintf(fp, " (Corrupt, declared size: %d, assuming size: %d)", 
    1054               0 :                     nLinkSize, nBytes);
    1055               0 :                 nLinkSize = nBytes;
    1056                 :             }
    1057               0 :             fprintf( fp, "\n  0x" );
    1058                 : 
    1059               0 :             for( i = 0; i < nLinkSize; i++ )
    1060               0 :                 fprintf( fp, "%02x", pabyData[i] );
    1061               0 :             fprintf( fp, "\n" );
    1062                 :             
    1063                 :         }
    1064                 :     }
    1065               0 : }
    1066                 : 
    1067                 : 
    1068                 : /************************************************************************/
    1069                 : /*                           DGNTypeToName()                            */
    1070                 : /************************************************************************/
    1071                 : 
    1072                 : /**
    1073                 :  * Convert type to name.
    1074                 :  *
    1075                 :  * Returns a human readable name for an element type such as DGNT_LINE.
    1076                 :  *
    1077                 :  * @param nType the DGNT_* type code to translate.
    1078                 :  *
    1079                 :  * @return a pointer to an internal string with the translation.  This string
    1080                 :  * should not be modified or freed.
    1081                 :  */
    1082                 : 
    1083               0 : const char *DGNTypeToName( int nType )
    1084                 : 
    1085                 : {
    1086                 :     static char szNumericResult[16];
    1087                 : 
    1088               0 :     switch( nType )
    1089                 :     {
    1090                 :       case DGNT_CELL_LIBRARY:
    1091               0 :         return "Cell Library";
    1092                 :         
    1093                 :       case DGNT_CELL_HEADER:
    1094               0 :         return "Cell Header";
    1095                 :         
    1096                 :       case DGNT_LINE:
    1097               0 :         return "Line";
    1098                 :         
    1099                 :       case DGNT_LINE_STRING:
    1100               0 :         return "Line String";
    1101                 : 
    1102                 :       case DGNT_POINT_STRING:
    1103               0 :         return "Point String";
    1104                 : 
    1105                 :       case DGNT_GROUP_DATA:
    1106               0 :         return "Group Data";
    1107                 : 
    1108                 :       case DGNT_SHAPE:
    1109               0 :         return "Shape";
    1110                 :         
    1111                 :       case DGNT_TEXT_NODE:
    1112               0 :         return "Text Node";
    1113                 : 
    1114                 :       case DGNT_DIGITIZER_SETUP:
    1115               0 :         return "Digitizer Setup";
    1116                 :         
    1117                 :       case DGNT_TCB:
    1118               0 :         return "TCB";
    1119                 :         
    1120                 :       case DGNT_LEVEL_SYMBOLOGY:
    1121               0 :         return "Level Symbology";
    1122                 :         
    1123                 :       case DGNT_CURVE:
    1124               0 :         return "Curve";
    1125                 :         
    1126                 :       case DGNT_COMPLEX_CHAIN_HEADER:
    1127               0 :         return "Complex Chain Header";
    1128                 :         
    1129                 :       case DGNT_COMPLEX_SHAPE_HEADER:
    1130               0 :         return "Complex Shape Header";
    1131                 :         
    1132                 :       case DGNT_ELLIPSE:
    1133               0 :         return "Ellipse";
    1134                 :         
    1135                 :       case DGNT_ARC:
    1136               0 :         return "Arc";
    1137                 :         
    1138                 :       case DGNT_TEXT:
    1139               0 :         return "Text";
    1140                 : 
    1141                 :       case DGNT_BSPLINE_POLE:
    1142               0 :         return "B-Spline Pole";
    1143                 : 
    1144                 :       case DGNT_BSPLINE_SURFACE_HEADER:
    1145               0 :         return "B-Spline Surface Header";
    1146                 : 
    1147                 :       case DGNT_BSPLINE_SURFACE_BOUNDARY:
    1148               0 :         return "B-Spline Surface Boundary";
    1149                 : 
    1150                 :       case DGNT_BSPLINE_KNOT:
    1151               0 :         return "B-Spline Knot";
    1152                 : 
    1153                 :       case DGNT_BSPLINE_CURVE_HEADER:
    1154               0 :         return "B-Spline Curve Header";
    1155                 : 
    1156                 :       case DGNT_BSPLINE_WEIGHT_FACTOR:
    1157               0 :         return "B-Spline Weight Factor";
    1158                 : 
    1159                 :       case DGNT_APPLICATION_ELEM:
    1160               0 :         return "Application Element";
    1161                 : 
    1162                 :       case DGNT_SHARED_CELL_DEFN:
    1163               0 :         return "Shared Cell Definition";
    1164                 :         
    1165                 :       case DGNT_SHARED_CELL_ELEM:
    1166               0 :         return "Shared Cell Element";
    1167                 :         
    1168                 :       case DGNT_TAG_VALUE:
    1169               0 :         return "Tag Value";
    1170                 :         
    1171                 :       case DGNT_CONE:
    1172               0 :         return "Cone";
    1173                 : 
    1174                 :       case DGNT_3DSURFACE_HEADER:
    1175               0 :         return "3D Surface Header";
    1176                 : 
    1177                 :       case DGNT_3DSOLID_HEADER:
    1178               0 :         return "3D Solid Header";
    1179                 : 
    1180                 :       default:
    1181               0 :         sprintf( szNumericResult, "%d", nType );
    1182               0 :         return szNumericResult;
    1183                 :     }
    1184                 : }
    1185                 : 
    1186                 : /************************************************************************/
    1187                 : /*                         DGNGetAttrLinkSize()                         */
    1188                 : /************************************************************************/
    1189                 : 
    1190                 : /**
    1191                 :  * Get attribute linkage size. 
    1192                 :  *
    1193                 :  * Returns the size, in bytes, of the attribute linkage starting at byte
    1194                 :  * offset nOffset.  On failure a value of 0 is returned.
    1195                 :  *
    1196                 :  * @param hDGN the file from which the element originated.
    1197                 :  * @param psElement the element to report on.
    1198                 :  * @param nOffset byte offset within attribute data of linkage to check.
    1199                 :  *
    1200                 :  * @return size of linkage in bytes, or zero. 
    1201                 :  */
    1202                 : 
    1203             109 : int DGNGetAttrLinkSize( DGNHandle hDGN, DGNElemCore *psElement, 
    1204                 :                         int nOffset )
    1205                 : 
    1206                 : {
    1207             109 :     if( psElement->attr_bytes < nOffset + 4 )
    1208              91 :         return 0;
    1209                 : 
    1210                 :     /* DMRS Linkage */
    1211              36 :     if( (psElement->attr_data[nOffset+0] == 0 
    1212               6 :          && psElement->attr_data[nOffset+1] == 0)
    1213              12 :         || (psElement->attr_data[nOffset+0] == 0 
    1214               0 :             && psElement->attr_data[nOffset+1] == 0x80) )
    1215               6 :         return 8;
    1216                 : 
    1217                 :     /* If low order bit of second byte is set, first byte is length */
    1218              12 :     if( psElement->attr_data[nOffset+1] & 0x10 )
    1219              12 :         return psElement->attr_data[nOffset+0] * 2 + 2;
    1220                 : 
    1221                 :     /* unknown */
    1222               0 :     return 0;
    1223                 : }
    1224                 : 
    1225                 : /************************************************************************/
    1226                 : /*                           DGNGetLinkage()                            */
    1227                 : /************************************************************************/
    1228                 : 
    1229                 : /**
    1230                 :  * Returns requested linkage raw data. 
    1231                 :  *
    1232                 :  * A pointer to the raw data for the requested attribute linkage is returned
    1233                 :  * as well as (potentially) various information about the linkage including
    1234                 :  * the linkage type, database entity number and MSLink value, and the length
    1235                 :  * of the raw linkage data in bytes.
    1236                 :  *
    1237                 :  * If the requested linkage (iIndex) does not exist a value of zero is 
    1238                 :  * returned.
    1239                 :  *
    1240                 :  * The entity number is (loosely speaking) the index of the table within
    1241                 :  * the current database to which the MSLINK value will refer.  The entity
    1242                 :  * number should be used to lookup the table name in the MSCATALOG table. 
    1243                 :  * The MSLINK value is the key value for the record in the target table. 
    1244                 :  *
    1245                 :  * @param hDGN the file from which the element originated.
    1246                 :  * @param psElement the element to report on.
    1247                 :  * @param iIndex the zero based index of the linkage to fetch.
    1248                 :  * @param pnLinkageType variable to return linkage type.  This may be one of
    1249                 :  * the predefined DGNLT_ values or a different value. This pointer may be NULL.
    1250                 :  * @param pnEntityNum variable to return the entity number in or NULL if not
    1251                 :  * required.  
    1252                 :  * @param pnMSLink variable to return the MSLINK value in, or NULL if not 
    1253                 :  * required.
    1254                 :  * @param pnLength variable to returned the linkage size in bytes or NULL.
    1255                 :  * 
    1256                 :  * @return pointer to raw internal linkage data.  This data should not be
    1257                 :  * altered or freed.  NULL returned on failure. 
    1258                 :  */
    1259                 : 
    1260             102 : unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement, 
    1261                 :                               int iIndex, int *pnLinkageType,
    1262                 :                               int *pnEntityNum, int *pnMSLink, int *pnLength )
    1263                 :     
    1264                 : {
    1265                 :     int nAttrOffset;
    1266                 :     int iLinkage, nLinkSize;
    1267                 : 
    1268             109 :     for( iLinkage=0, nAttrOffset=0;
    1269                 :          (nLinkSize = DGNGetAttrLinkSize( hDGN, psElement, nAttrOffset)) != 0;
    1270                 :          iLinkage++, nAttrOffset += nLinkSize )
    1271                 :     {
    1272              18 :         if( iLinkage == iIndex )
    1273                 :         {
    1274              11 :             int  nLinkageType=0, nEntityNum=0, nMSLink = 0;
    1275              11 :             CPLAssert( nLinkSize > 4 );
    1276                 : 
    1277              17 :             if( psElement->attr_data[nAttrOffset+0] == 0x00
    1278               3 :                 && (psElement->attr_data[nAttrOffset+1] == 0x00
    1279               0 :                     || psElement->attr_data[nAttrOffset+1] == 0x80) )
    1280                 :             {
    1281               3 :                 nLinkageType = DGNLT_DMRS;
    1282               3 :                 nEntityNum = psElement->attr_data[nAttrOffset+2] 
    1283               3 :                     + psElement->attr_data[nAttrOffset+3] * 256;
    1284               3 :                 nMSLink = psElement->attr_data[nAttrOffset+4] 
    1285               3 :                     + psElement->attr_data[nAttrOffset+5] * 256
    1286               6 :                     + psElement->attr_data[nAttrOffset+6] * 65536;
    1287                 :             }
    1288                 :             else
    1289               8 :                 nLinkageType = psElement->attr_data[nAttrOffset+2] 
    1290               8 :                     + psElement->attr_data[nAttrOffset+3] * 256;
    1291                 : 
    1292                 :             // Possibly an external database linkage?
    1293              11 :             if( nLinkSize == 16 && nLinkageType != DGNLT_SHAPE_FILL )
    1294                 :             {
    1295               0 :                 nEntityNum = psElement->attr_data[nAttrOffset+6] 
    1296               0 :                     + psElement->attr_data[nAttrOffset+7] * 256;
    1297               0 :                 nMSLink = psElement->attr_data[nAttrOffset+8] 
    1298               0 :                     + psElement->attr_data[nAttrOffset+9] * 256
    1299               0 :                     + psElement->attr_data[nAttrOffset+10] * 65536
    1300               0 :                     + psElement->attr_data[nAttrOffset+11] * 65536 * 256;
    1301                 :                 
    1302                 :             }
    1303                 : 
    1304              11 :             if( pnLinkageType != NULL )
    1305               5 :                 *pnLinkageType = nLinkageType;
    1306              11 :             if( pnEntityNum != NULL )
    1307               5 :                 *pnEntityNum = nEntityNum;
    1308              11 :             if( pnMSLink != NULL )
    1309               5 :                 *pnMSLink = nMSLink;
    1310              11 :             if( pnLength != NULL )
    1311               5 :                 *pnLength = nLinkSize;
    1312                 : 
    1313              11 :             return psElement->attr_data + nAttrOffset;
    1314                 :         }
    1315                 :     }
    1316                 :              
    1317              91 :     return NULL;
    1318                 : }
    1319                 : 
    1320                 : /************************************************************************/
    1321                 : /*                         DGNRotationToQuat()                          */
    1322                 : /*                                                                      */
    1323                 : /*      Compute a quaternion for a given Z rotation.                    */
    1324                 : /************************************************************************/
    1325                 : 
    1326               0 : void DGNRotationToQuaternion( double dfRotation, int *panQuaternion )
    1327                 : 
    1328                 : {
    1329               0 :     double dfRadianRot = (dfRotation / 180.0)  * PI;
    1330                 : 
    1331               0 :     panQuaternion[0] = (int) (cos(-dfRadianRot/2.0) * 2147483647);
    1332               0 :     panQuaternion[1] = 0;
    1333               0 :     panQuaternion[2] = 0;
    1334               0 :     panQuaternion[3] = (int) (sin(-dfRadianRot/2.0) * 2147483647);
    1335               0 : }
    1336                 : 
    1337                 : /************************************************************************/
    1338                 : /*                         DGNQuaternionToMatrix()                      */
    1339                 : /*                                                                      */
    1340                 : /*      Compute a rotation matrix for a given quaternion                */
    1341                 : /* FIXME: Write documentation on how to use this matrix                 */
    1342                 : /* (i.e. things like row/column major, OpenGL style or not)             */
    1343                 : /* kintel 20030819                                                      */
    1344                 : /************************************************************************/
    1345                 : 
    1346               0 : void DGNQuaternionToMatrix( int *quat, float *mat )
    1347                 : {
    1348                 :   double q[4];
    1349                 : 
    1350               0 :   q[0] = 1.0 * quat[1] / (1<<31);
    1351               0 :   q[1] = 1.0 * quat[2] / (1<<31);
    1352               0 :   q[2] = 1.0 * quat[3] / (1<<31);
    1353               0 :   q[3] = 1.0 * quat[0] / (1<<31);
    1354                 : 
    1355               0 :   mat[0*3+0] = (float) (q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]);
    1356               0 :   mat[0*3+1] = (float) (2 * (q[2]*q[3] + q[0]*q[1]));
    1357               0 :   mat[0*3+2] = (float) (2 * (q[0]*q[2] - q[1]*q[3]));
    1358               0 :   mat[1*3+0] = (float) (2 * (q[0]*q[1] - q[2]*q[3]));
    1359               0 :   mat[1*3+1] = (float) (-q[0]*q[0] + q[1]*q[1] - q[2]*q[2] + q[3]*q[3]);
    1360               0 :   mat[1*3+2] = (float) (2 * (q[0]*q[3] + q[1]*q[2]));
    1361               0 :   mat[2*3+0] = (float) (2 * (q[0]*q[2] + q[1]*q[3])); 
    1362               0 :   mat[2*3+1] = (float) (2 * (q[1]*q[2] - q[0]*q[3]));
    1363               0 :   mat[2*3+2] = (float) (-q[0]*q[0] - q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
    1364               0 : }
    1365                 : 
    1366                 : /************************************************************************/
    1367                 : /*                  DGNTransformPointWithQuaternion()                   */
    1368                 : /************************************************************************/
    1369                 : 
    1370               0 : void DGNTransformPointWithQuaternionVertex( int *quat, DGNPoint *v1, DGNPoint *v2 )
    1371                 : {
    1372                 : 
    1373                 : /* ==================================================================== */
    1374                 : /*      Original code provided by kintel 20030819, but assumed to be    */
    1375                 : /*      incomplete.                                                     */
    1376                 : /* ==================================================================== */
    1377                 : 
    1378                 : #ifdef notdef
    1379                 :     See below for sketched implementation. kintel 20030819.
    1380                 :                                float x,y,z,w;
    1381                 :     // FIXME: Convert quat to x,y,z,w
    1382                 :     v2.x = w*w*v1.x + 2*y*w*v1.z - 2*z*w*v1.y + x*x*v1.x + 2*y*x*v1.y + 2*z*x*v1.z - z*z*v1.x - y*y*v1.x; 
    1383                 :     v2.y = 2*x*y*v1.x + y*y*v1.y + 2*z*y*v1.z + 2*w*z*v1.x - z*z*v1.y + w*w*v1.y - 2*x*w*v1.z - x*x*v1.y; 
    1384                 :     v2.z = 2*x*z*v1.x + 2*y*z*v1.y + z*z*v1.z - 2*w*y*v1.x - y*y*v1.z + 2*w*x*v1.y - x*x*v1.z + w*w*v1.z;
    1385                 : #endif
    1386                 : 
    1387                 : /* ==================================================================== */
    1388                 : /*      Impelementation provided by Peggy Jung - 2004/03/05.            */
    1389                 : /*      peggy.jung at moskito-gis dot de.  I haven't tested it.         */
    1390                 : /* ==================================================================== */
    1391                 : 
    1392                 : /*  Version: 0.1                                 Datum: 26.01.2004
    1393                 :  
    1394                 : IN:
    1395                 : x,y,z               // DGNPoint &v1
    1396                 : quat[]              // 
    1397                 :  
    1398                 : OUT:
    1399                 : newX, newY, newZ    // DGNPoint &v2
    1400                 : 
    1401                 : A u t o r  :  Peggy Jung
    1402                 : */
    1403                 : /*
    1404                 :     double ROT[12];  //rotation matrix for a given quaternion
    1405                 :     double xx, xy, xz, xw, yy, yz, yw, zz, zw;
    1406                 :     double a, b, c, d, n, x, y, z;
    1407                 : 
    1408                 :     x = v1->x;
    1409                 :     y = v1->y;
    1410                 :     z = v1->z;
    1411                 :  
    1412                 :     n = sqrt((double)PDP2PC_long(quat[0])*(double)PDP2PC_long(quat[0])+(double)PDP2PC_long(quat[1])*(double)PDP2PC_long(quat[1])+
    1413                 :              (double)PDP2PC_long(quat[2])*(double)PDP2PC_long(quat[2])+(double)PDP2PC_long(quat[3])*(double)PDP2PC_long(quat[3]));
    1414                 :  
    1415                 :     a = (double)PDP2PC_long(quat[0])/n; //w
    1416                 :     b = (double)PDP2PC_long(quat[1])/n; //x
    1417                 :     c = (double)PDP2PC_long(quat[2])/n; //y
    1418                 :     d = (double)PDP2PC_long(quat[3])/n; //z
    1419                 :  
    1420                 :     xx      = b*b;
    1421                 :     xy      = b*c;
    1422                 :     xz      = b*d;
    1423                 :     xw      = b*a;
    1424                 :  
    1425                 :     yy      = c*c;
    1426                 :     yz      = c*d;
    1427                 :     yw      = c*a;
    1428                 :  
    1429                 :     zz      = d*d;
    1430                 :     zw      = d+a;
    1431                 :  
    1432                 :     ROT[0] = 1 - 2 * yy - 2 * zz ;
    1433                 :     ROT[1] =     2 * xy - 2 * zw ;
    1434                 :     ROT[2] =     2 * xz + 2 * yw ;
    1435                 :  
    1436                 :     ROT[4] =     2 * xy + 2 * zw ;
    1437                 :     ROT[5] = 1 - 2 * xx - 2 * zz ;
    1438                 :     ROT[6] =     2 * yz - 2 * xw ;
    1439                 :  
    1440                 :     ROT[8] =     2 * xz - 2 * yw ;
    1441                 :     ROT[9] =     2 * yz + 2 * xw ;
    1442                 :     ROT[10] = 1 - 2 * xx - 2 * yy ;
    1443                 :  
    1444                 :     v2->x = ROT[0]*x + ROT[1]*y + ROT[2]*z;
    1445                 :     v2->y = ROT[4]*x + ROT[5]*y + ROT[6]*z;
    1446                 :     v2->z = ROT[8]*x + ROT[9]*y + ROT[10]*z;
    1447                 : */
    1448               0 : }

Generated by: LCOV version 1.7