LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/ntf - ntf_estlayers.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 666 123 18.5 %
Date: 2010-01-09 Functions: 34 8 23.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: ntf_estlayers.cpp 15637 2008-10-29 16:06:38Z warmerdam $
       3                 :  *
       4                 :  * Project:  NTF Translator
       5                 :  * Purpose:  NTFFileReader methods related to establishing the schemas
       6                 :  *           of features that could occur in this product and the functions
       7                 :  *           for actually performing the NTFRecord to OGRFeature conversion.
       8                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       9                 :  *
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 1999, Frank Warmerdam
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include <stdarg.h>
      33                 : #include "ntf.h"
      34                 : #include "cpl_string.h"
      35                 : 
      36                 : CPL_CVSID("$Id: ntf_estlayers.cpp 15637 2008-10-29 16:06:38Z warmerdam $");
      37                 : 
      38                 : #define MAX_LINK        5000
      39                 : 
      40                 : /************************************************************************/
      41                 : /*                         TranslateCodePoint()                         */
      42                 : /*                                                                      */
      43                 : /*      Used for code point, and code point plus.                       */
      44                 : /************************************************************************/
      45                 : 
      46               0 : static OGRFeature *TranslateCodePoint( NTFFileReader *poReader,
      47                 :                                        OGRNTFLayer *poLayer,
      48                 :                                        NTFRecord **papoGroup )
      49                 : 
      50                 : {
      51               0 :     if( CSLCount((char **) papoGroup) < 2
      52               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
      53               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
      54               0 :         return NULL;
      55                 :         
      56               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
      57                 : 
      58                 :     // POINT_ID
      59               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
      60                 : 
      61                 :     // Geometry
      62               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
      63                 : 
      64                 :     // Attributes
      65               0 :     if( EQUAL(poLayer->GetLayerDefn()->GetName(),"CODE_POINT") )
      66                 :         poReader->ApplyAttributeValues( poFeature, papoGroup,
      67                 :                                         "PC", 1, "PQ", 2, "PR", 3, "TP", 4,
      68                 :                                         "DQ", 5, "RP", 6, "BP", 7, "PD", 8,
      69                 :                                         "MP", 9, "UM", 10, "RV", 11, 
      70               0 :                                         NULL );
      71                 :     else
      72                 :         poReader->ApplyAttributeValues( poFeature, papoGroup,
      73                 :                                         "PC", 1, "PQ", 2, "PR", 3, "TP", 4,
      74                 :                                         "DQ", 5, "RP", 6, "BP", 7, "PD", 8,
      75                 :                                         "MP", 9, "UM", 10, "RV", 11,
      76                 :                                         "RH", 12, "LH", 13, "CC", 14,
      77                 :                                         "DC", 15, "WC", 16, 
      78               0 :                                         NULL );
      79                 : 
      80               0 :     return poFeature;
      81                 : }
      82                 : 
      83                 : /************************************************************************/
      84                 : /*                       TranslateAddressPoint()                        */
      85                 : /************************************************************************/
      86                 : 
      87               0 : static OGRFeature *TranslateAddressPoint( NTFFileReader *poReader,
      88                 :                                           OGRNTFLayer *poLayer,
      89                 :                                           NTFRecord **papoGroup )
      90                 : 
      91                 : {
      92               0 :     if( CSLCount((char **) papoGroup) < 2
      93               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
      94               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
      95               0 :         return NULL;
      96                 :         
      97               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
      98                 : 
      99                 :     // POINT_ID
     100               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     101                 : 
     102                 :     // CHG_TYPE
     103               0 :     poFeature->SetField( 17, papoGroup[0]->GetField( 22, 22 ) );
     104                 : 
     105                 :     // CHG_DATE
     106               0 :     poFeature->SetField( 18, papoGroup[0]->GetField( 23, 28 ) );
     107                 : 
     108                 :     // Geometry
     109               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
     110                 : 
     111                 :     // Attributes
     112                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     113                 :                                     "OA", 1, "ON", 2, "DP", 3, "PB", 4,
     114                 :                                     "SB", 5, "BD", 6, "BN", 7, "DR", 8,
     115                 :                                     "TN", 9, "DD", 10, "DL", 11, "PT", 12,
     116                 :                                     "CN", 13, "PC", 14, "SF", 15, "RV", 16,
     117               0 :                                     NULL );
     118                 : 
     119               0 :     return poFeature;
     120                 : }
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                        TranslateOscarPoint()                         */
     124                 : /*                                                                      */
     125                 : /*      Used for OSCAR Traffic and Asset datasets.                      */
     126                 : /************************************************************************/
     127                 : 
     128               0 : static OGRFeature *TranslateOscarPoint( NTFFileReader *poReader,
     129                 :                                         OGRNTFLayer *poLayer,
     130                 :                                         NTFRecord **papoGroup )
     131                 : 
     132                 : {
     133               0 :     if( CSLCount((char **) papoGroup) < 2
     134               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
     135               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     136               0 :         return NULL;
     137                 :         
     138               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     139                 : 
     140                 :     // POINT_ID
     141               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     142                 : 
     143                 :     // Geometry
     144                 :     int         nGeomId;
     145                 :     
     146                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     147               0 :                                                              &nGeomId));
     148                 : 
     149               0 :     poFeature->SetField( 1, nGeomId );
     150                 : 
     151                 :     // Attributes
     152                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     153                 :                                     "FC", 2, "OD", 3, "JN", 4, "SN", 5,
     154               0 :                                     NULL );
     155                 : 
     156               0 :     return poFeature;
     157                 : }
     158                 : 
     159                 : /************************************************************************/
     160                 : /*                         TranslateOscarLine()                         */
     161                 : /************************************************************************/
     162                 : 
     163               0 : static OGRFeature *TranslateOscarLine( NTFFileReader *poReader,
     164                 :                                        OGRNTFLayer *poLayer,
     165                 :                                        NTFRecord **papoGroup )
     166                 : 
     167                 : {
     168               0 :     if( CSLCount((char **) papoGroup) < 2
     169               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
     170               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     171               0 :         return NULL;
     172                 :         
     173               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     174                 : 
     175                 :     // LINE_ID
     176               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     177                 : 
     178                 :     // Geometry
     179                 :     int         nGeomId;
     180                 :     
     181                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     182               0 :                                                              &nGeomId));
     183                 : 
     184               0 :     poFeature->SetField( 1, nGeomId );
     185                 : 
     186                 :     // Attributes
     187                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     188                 :                                     "FC", 2, "OD", 3, "PN", 4, "LL", 5,
     189                 :                                     "SC", 6, "FW", 7, "RN", 8, "TR", 9,
     190               0 :                                     NULL );
     191                 : 
     192               0 :     return poFeature;
     193                 : }
     194                 : 
     195                 : /************************************************************************/
     196                 : /*                      TranslateOscarRoutePoint()                      */
     197                 : /************************************************************************/
     198                 : 
     199               0 : static OGRFeature *TranslateOscarRoutePoint( NTFFileReader *poReader,
     200                 :                                              OGRNTFLayer *poLayer,
     201                 :                                              NTFRecord **papoGroup )
     202                 : 
     203                 : {
     204               0 :     if( CSLCount((char **) papoGroup) < 2
     205               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
     206               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     207               0 :         return NULL;
     208                 :         
     209               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     210                 : 
     211                 :     // POINT_ID
     212               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     213                 : 
     214                 :     // Geometry
     215                 :     int         nGeomId;
     216                 :     
     217                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     218               0 :                                                              &nGeomId));
     219                 : 
     220               0 :     poFeature->SetField( 1, nGeomId );
     221                 : 
     222                 :     // Attributes
     223                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     224                 :                                     "FC", 2, "OD", 3, "JN", 4, "SN", 5,
     225                 :                                     "NP", 6, "RT", 8,
     226               0 :                                     NULL );
     227                 : 
     228                 :     // PARENT_OSODR
     229                 :     char        **papszTypes, **papszValues;
     230                 : 
     231               0 :     if( poReader->ProcessAttRecGroup( papoGroup, &papszTypes, &papszValues ) )
     232                 :     {
     233               0 :         char    **papszOSODRList = NULL;
     234                 : 
     235               0 :         for( int i = 0; papszTypes != NULL && papszTypes[i] != NULL; i++ )
     236                 :         {
     237               0 :             if( EQUAL(papszTypes[i],"PO") )
     238               0 :                 papszOSODRList = CSLAddString(papszOSODRList,papszValues[i]);
     239                 :         }
     240                 : 
     241               0 :         poFeature->SetField( 7, papszOSODRList );
     242                 :         CPLAssert( CSLCount(papszOSODRList) ==
     243                 :                    poFeature->GetFieldAsInteger( 6 ) );
     244                 : 
     245               0 :         CSLDestroy( papszOSODRList );
     246               0 :         CSLDestroy( papszTypes );
     247               0 :         CSLDestroy( papszValues );
     248                 :     }
     249                 : 
     250               0 :     return poFeature;
     251                 : }
     252                 : 
     253                 : /************************************************************************/
     254                 : /*                      TranslateOscarRouteLine()                       */
     255                 : /************************************************************************/
     256                 : 
     257               0 : static OGRFeature *TranslateOscarRouteLine( NTFFileReader *poReader,
     258                 :                                             OGRNTFLayer *poLayer,
     259                 :                                             NTFRecord **papoGroup )
     260                 : 
     261                 : {
     262               0 :     if( CSLCount((char **) papoGroup) < 2
     263               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
     264               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     265               0 :         return NULL;
     266                 :         
     267               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     268                 : 
     269                 :     // LINE_ID
     270               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     271                 : 
     272                 :     // Geometry
     273                 :     int         nGeomId;
     274                 :     
     275                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     276               0 :                                                              &nGeomId));
     277                 : 
     278               0 :     poFeature->SetField( 1, nGeomId );
     279                 : 
     280                 :     // Attributes
     281                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     282                 :                                     "FC", 2, "OD", 3, "PN", 4, "LL", 5,
     283                 :                                     "RN", 6, "TR", 7, "NP", 8, 
     284               0 :                                     NULL );
     285                 : 
     286                 :     // PARENT_OSODR
     287                 :     char        **papszTypes, **papszValues;
     288                 : 
     289               0 :     if( poReader->ProcessAttRecGroup( papoGroup, &papszTypes, &papszValues ) )
     290                 :     {
     291               0 :         char    **papszOSODRList = NULL;
     292                 : 
     293               0 :         for( int i = 0; papszTypes != NULL && papszTypes[i] != NULL; i++ )
     294                 :         {
     295               0 :             if( EQUAL(papszTypes[i],"PO") )
     296               0 :                 papszOSODRList = CSLAddString(papszOSODRList,papszValues[i]);
     297                 :         }
     298                 : 
     299               0 :         poFeature->SetField( 9, papszOSODRList );
     300                 :         CPLAssert( CSLCount(papszOSODRList) ==
     301                 :                    poFeature->GetFieldAsInteger( 8 ) );
     302                 : 
     303               0 :         CSLDestroy( papszOSODRList );
     304               0 :         CSLDestroy( papszTypes );
     305               0 :         CSLDestroy( papszValues );
     306                 :     }
     307                 : 
     308               0 :     return poFeature;
     309                 : }
     310                 : 
     311                 : /************************************************************************/
     312                 : /*                       TranslateOscarComment()                        */
     313                 : /************************************************************************/
     314                 : 
     315               0 : static OGRFeature *TranslateOscarComment( NTFFileReader *poReader,
     316                 :                                           OGRNTFLayer *poLayer,
     317                 :                                           NTFRecord **papoGroup )
     318                 : 
     319                 : {
     320               0 :     if( CSLCount((char **) papoGroup) != 1 
     321               0 :         || papoGroup[0]->GetType() != NRT_COMMENT )
     322               0 :         return NULL;
     323                 :         
     324               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     325                 : 
     326                 :     // RECORD_TYPE
     327               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 4 )) );
     328                 : 
     329                 :     // RECORD_ID
     330               0 :     poFeature->SetField( 1, papoGroup[0]->GetField( 5, 17 ) );
     331                 : 
     332                 :     // CHANGE_TYPE
     333               0 :     poFeature->SetField( 2, papoGroup[0]->GetField( 18, 18 ) );
     334                 : 
     335               0 :     return poFeature;
     336                 : }
     337                 : 
     338                 : /************************************************************************/
     339                 : /*                     TranslateOscarNetworkPoint()                     */
     340                 : /************************************************************************/
     341                 : 
     342               0 : static OGRFeature *TranslateOscarNetworkPoint( NTFFileReader *poReader,
     343                 :                                                OGRNTFLayer *poLayer,
     344                 :                                                NTFRecord **papoGroup )
     345                 : 
     346                 : {
     347               0 :     if( CSLCount((char **) papoGroup) < 2
     348               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
     349               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     350               0 :         return NULL;
     351                 :         
     352               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     353                 : 
     354                 :     // POINT_ID
     355               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     356                 : 
     357                 :     // Geometry
     358                 :     int         nGeomId;
     359                 :     
     360                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     361               0 :                                                              &nGeomId));
     362                 : 
     363               0 :     poFeature->SetField( 1, nGeomId );
     364                 : 
     365                 :     // Attributes
     366                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     367                 :                                     "FC", 2, "OD", 3, "JN", 4, "SN", 5,
     368                 :                                     "RT", 6,
     369               0 :                                     NULL );
     370                 : 
     371               0 :     return poFeature;
     372                 : }
     373                 : 
     374                 : /************************************************************************/
     375                 : /*                      TranslateOscarNetworkLine()                     */
     376                 : /************************************************************************/
     377                 : 
     378               0 : static OGRFeature *TranslateOscarNetworkLine( NTFFileReader *poReader,
     379                 :                                               OGRNTFLayer *poLayer,
     380                 :                                               NTFRecord **papoGroup )
     381                 : 
     382                 : {
     383               0 :     if( CSLCount((char **) papoGroup) < 2
     384               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
     385               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     386               0 :         return NULL;
     387                 :         
     388               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     389                 : 
     390                 :     // LINE_ID
     391               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     392                 : 
     393                 :     // Geometry
     394                 :     int         nGeomId;
     395                 :     
     396                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     397               0 :                                                              &nGeomId));
     398                 : 
     399               0 :     poFeature->SetField( 1, nGeomId );
     400                 : 
     401                 :     // Attributes
     402                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     403                 :                                     "FC", 2, "OD", 3, "PN", 4, "LL", 5,
     404                 :                                     "RN", 6, 
     405               0 :                                     NULL );
     406                 : 
     407               0 :     return poFeature;
     408                 : }
     409                 : 
     410                 : /************************************************************************/
     411                 : /*                       TranslateBasedataPoint()                       */
     412                 : /************************************************************************/
     413                 : 
     414               0 : static OGRFeature *TranslateBasedataPoint( NTFFileReader *poReader,
     415                 :                                            OGRNTFLayer *poLayer,
     416                 :                                            NTFRecord **papoGroup )
     417                 : 
     418                 : {
     419               0 :     if( CSLCount((char **) papoGroup) < 2
     420               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
     421               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     422               0 :         return NULL;
     423                 :         
     424               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     425                 : 
     426                 :     // POINT_ID
     427               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     428                 : 
     429                 :     // Geometry
     430                 :     int         nGeomId;
     431                 :     
     432                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     433               0 :                                                              &nGeomId));
     434                 : 
     435                 :     // GEOM_ID
     436               0 :     poFeature->SetField( 1, nGeomId );
     437                 : 
     438                 :     // Attributes
     439                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     440                 :                                     "FC", 2, "PN", 3, "NU", 4, "CM", 5,
     441                 :                                     "UN", 6, "OR", 7,
     442               0 :                                     NULL );
     443                 : 
     444               0 :     return poFeature;
     445                 : }
     446                 : 
     447                 : /************************************************************************/
     448                 : /*                       TranslateBasedataLine()                        */
     449                 : /************************************************************************/
     450                 : 
     451               0 : static OGRFeature *TranslateBasedataLine( NTFFileReader *poReader,
     452                 :                                           OGRNTFLayer *poLayer,
     453                 :                                           NTFRecord **papoGroup )
     454                 : 
     455                 : {
     456               0 :     if( CSLCount((char **) papoGroup) < 2
     457               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
     458               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     459               0 :         return NULL;
     460                 :         
     461               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     462                 : 
     463                 :     // LINE_ID
     464               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     465                 : 
     466                 :     // Geometry
     467                 :     int         nGeomId;
     468                 :     
     469                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     470               0 :                                                              &nGeomId));
     471                 : 
     472                 :     // GEOM_ID
     473               0 :     poFeature->SetField( 2, nGeomId );
     474                 : 
     475                 :     // Attributes
     476                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     477                 :                                     "FC", 1, "PN", 3, "NU", 4, "RB", 5,
     478               0 :                                     NULL );
     479                 : 
     480               0 :     return poFeature;
     481                 : }
     482                 : 
     483                 : /************************************************************************/
     484                 : /*                  TranslateBoundarylineCollection()                   */
     485                 : /************************************************************************/
     486                 : 
     487               0 : static OGRFeature *TranslateBoundarylineCollection( NTFFileReader *poReader,
     488                 :                                                     OGRNTFLayer *poLayer,
     489                 :                                                     NTFRecord **papoGroup )
     490                 : 
     491                 : {
     492               0 :     if( CSLCount((char **) papoGroup) != 2 
     493               0 :         || papoGroup[0]->GetType() != NRT_COLLECT
     494               0 :         || papoGroup[1]->GetType() != NRT_ATTREC )
     495               0 :         return NULL;
     496                 :         
     497               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     498                 : 
     499                 :     // COLL_ID
     500               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     501                 : 
     502                 :     // NUM_PARTS
     503               0 :     int         nNumLinks = atoi(papoGroup[0]->GetField( 9, 12 ));
     504                 :     
     505               0 :     if( nNumLinks > MAX_LINK )
     506                 :     {
     507                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     508               0 :                   "MAX_LINK exceeded in ntf_estlayers.cpp." );
     509               0 :         return poFeature;
     510                 :     }
     511                 :     
     512               0 :     poFeature->SetField( 1, nNumLinks );
     513                 : 
     514                 :     // POLY_ID
     515                 :     int         i, anList[MAX_LINK];
     516                 : 
     517               0 :     for( i = 0; i < nNumLinks; i++ )
     518               0 :         anList[i] = atoi(papoGroup[0]->GetField( 15+i*8, 20+i*8 ));
     519                 : 
     520               0 :     poFeature->SetField( 2, nNumLinks, anList );
     521                 : 
     522                 :     // Attributes
     523                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     524                 :                                     "AI", 3, "OP", 4, "NM", 5,
     525               0 :                                     NULL );
     526                 : 
     527               0 :     return poFeature;
     528                 : }
     529                 : 
     530                 : /************************************************************************/
     531                 : /*                     TranslateBoundarylinePoly()                      */
     532                 : /************************************************************************/
     533                 : 
     534               0 : static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
     535                 :                                               OGRNTFLayer *poLayer,
     536                 :                                               NTFRecord **papoGroup )
     537                 : 
     538                 : {
     539                 : /* ==================================================================== */
     540                 : /*      Traditional POLYGON record groups.                              */
     541                 : /* ==================================================================== */
     542               0 :     if( CSLCount((char **) papoGroup) == 4 
     543               0 :         && papoGroup[0]->GetType() == NRT_POLYGON
     544               0 :         && papoGroup[1]->GetType() == NRT_ATTREC 
     545               0 :         && papoGroup[2]->GetType() == NRT_CHAIN 
     546               0 :         && papoGroup[3]->GetType() == NRT_GEOMETRY )
     547                 :     {
     548                 :         
     549               0 :         OGRFeature      *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     550                 : 
     551                 :         // POLY_ID
     552               0 :         poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     553                 : 
     554                 :         // NUM_PARTS
     555               0 :         int             nNumLinks = atoi(papoGroup[2]->GetField( 9, 12 ));
     556                 :     
     557               0 :         if( nNumLinks > MAX_LINK )
     558                 :         {
     559                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     560               0 :                       "MAX_LINK exceeded in ntf_estlayers.cpp." );
     561               0 :             return poFeature;
     562                 :         }
     563                 :     
     564               0 :         poFeature->SetField( 4, nNumLinks );
     565                 : 
     566                 :         // DIR
     567                 :         int             i, anList[MAX_LINK];
     568                 : 
     569               0 :         for( i = 0; i < nNumLinks; i++ )
     570               0 :             anList[i] = atoi(papoGroup[2]->GetField( 19+i*7, 19+i*7 ));
     571                 : 
     572               0 :         poFeature->SetField( 5, nNumLinks, anList );
     573                 : 
     574                 :         // GEOM_ID_OF_LINK
     575               0 :         for( i = 0; i < nNumLinks; i++ )
     576               0 :             anList[i] = atoi(papoGroup[2]->GetField( 13+i*7, 18+i*7 ));
     577                 : 
     578               0 :         poFeature->SetField( 6, nNumLinks, anList );
     579                 : 
     580                 :         // RingStart
     581               0 :         int     nRingList = 0;
     582               0 :         poFeature->SetField( 7, 1, &nRingList );
     583                 : 
     584                 :         // Attributes
     585                 :         poReader->ApplyAttributeValues( poFeature, papoGroup,
     586                 :                                         "FC", 1, "PI", 2, "HA", 3,
     587               0 :                                         NULL );
     588                 : 
     589                 :         // Read point geometry
     590                 :         poFeature->SetGeometryDirectly(
     591               0 :             poReader->ProcessGeometry(papoGroup[3]));
     592                 : 
     593                 :         // Try to assemble polygon geometry.
     594               0 :         poReader->FormPolygonFromCache( poFeature );
     595                 : 
     596               0 :         return poFeature;
     597                 :     }
     598                 : 
     599                 : /* ==================================================================== */
     600                 : /*      CPOLYGON Group                                                  */
     601                 : /* ==================================================================== */
     602                 : 
     603                 : /* -------------------------------------------------------------------- */
     604                 : /*      First we do validation of the grouping.                         */
     605                 : /* -------------------------------------------------------------------- */
     606                 :     int         iRec;
     607                 :     
     608               0 :     for( iRec = 0;
     609               0 :          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
     610               0 :              && papoGroup[iRec]->GetType() == NRT_POLYGON
     611               0 :              && papoGroup[iRec+1]->GetType() == NRT_CHAIN;
     612                 :          iRec += 2 ) {}
     613                 : 
     614               0 :     if( CSLCount((char **) papoGroup) != iRec + 3 )
     615               0 :         return NULL;
     616                 : 
     617               0 :     if( papoGroup[iRec]->GetType() != NRT_CPOLY
     618               0 :         || papoGroup[iRec+1]->GetType() != NRT_ATTREC
     619               0 :         || papoGroup[iRec+2]->GetType() != NRT_GEOMETRY )
     620               0 :         return NULL;
     621                 : 
     622                 : /* -------------------------------------------------------------------- */
     623                 : /*      Collect the chains for each of the rings, and just aggregate    */
     624                 : /*      these into the master list without any concept of where the     */
     625                 : /*      boundaries are.  The boundary information will be emmitted      */
     626                 : /*      in the RingStart field.                                         */
     627                 : /* -------------------------------------------------------------------- */
     628               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     629               0 :     int         nNumLink = 0;
     630                 :     int         anDirList[MAX_LINK*2], anGeomList[MAX_LINK*2];
     631               0 :     int         anRingStart[MAX_LINK], nRings = 0;
     632                 : 
     633               0 :     for( iRec = 0;
     634               0 :          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
     635               0 :              && papoGroup[iRec]->GetType() == NRT_POLYGON
     636               0 :              && papoGroup[iRec+1]->GetType() == NRT_CHAIN;
     637                 :          iRec += 2 )
     638                 :     {
     639                 :         int             i, nLineCount;
     640                 : 
     641               0 :         nLineCount = atoi(papoGroup[iRec+1]->GetField(9,12));
     642                 : 
     643               0 :         anRingStart[nRings++] = nNumLink;
     644                 :         
     645               0 :         for( i = 0; i < nLineCount && nNumLink < MAX_LINK*2; i++ )
     646                 :         {
     647               0 :             anDirList[nNumLink] =
     648               0 :                 atoi(papoGroup[iRec+1]->GetField( 19+i*7, 19+i*7 ));
     649               0 :             anGeomList[nNumLink] =
     650               0 :                 atoi(papoGroup[iRec+1]->GetField( 13+i*7, 18+i*7 ));
     651               0 :             nNumLink++;
     652                 :         }
     653                 : 
     654               0 :         if( nNumLink == MAX_LINK*2 )
     655                 :         {
     656                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     657               0 :                       "MAX_LINK exceeded in ntf_estlayers.cpp." );
     658                 : 
     659               0 :             delete poFeature;
     660               0 :             return NULL;
     661                 :         }
     662                 :     }
     663                 : 
     664                 :     // NUM_PART
     665               0 :     poFeature->SetField( 4, nNumLink );
     666                 : 
     667                 :     // DIR
     668               0 :     poFeature->SetField( 5, nNumLink, anDirList );
     669                 : 
     670                 :     // GEOM_ID_OF_LINK
     671               0 :     poFeature->SetField( 6, nNumLink, anGeomList );
     672                 : 
     673                 :     // RingStart
     674               0 :     poFeature->SetField( 7, nRings, anRingStart );
     675                 : 
     676                 :     
     677                 : /* -------------------------------------------------------------------- */
     678                 : /*      collect information for whole complex polygon.                  */
     679                 : /* -------------------------------------------------------------------- */
     680                 :     // POLY_ID
     681               0 :     poFeature->SetField( 0, atoi(papoGroup[iRec]->GetField( 3, 8 )) );
     682                 : 
     683                 :     // Attributes
     684                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     685                 :                                     "FC", 1, "PI", 2, "HA", 3,
     686               0 :                                     NULL );
     687                 : 
     688                 :     // point geometry for seed.
     689                 :     poFeature->SetGeometryDirectly(
     690               0 :         poReader->ProcessGeometry(papoGroup[iRec+2]));
     691                 : 
     692                 :     // Try to assemble polygon geometry.
     693               0 :     poReader->FormPolygonFromCache( poFeature );
     694                 : 
     695               0 :     return poFeature;
     696                 : }
     697                 : 
     698                 : /************************************************************************/
     699                 : /*                     TranslateBoundarylineLink()                      */
     700                 : /************************************************************************/
     701                 : 
     702               0 : static OGRFeature *TranslateBoundarylineLink( NTFFileReader *poReader,
     703                 :                                               OGRNTFLayer *poLayer,
     704                 :                                               NTFRecord **papoGroup )
     705                 : 
     706                 : {
     707               0 :     if( CSLCount((char **) papoGroup) != 2 
     708               0 :         || papoGroup[0]->GetType() != NRT_GEOMETRY
     709               0 :         || papoGroup[1]->GetType() != NRT_ATTREC )
     710               0 :         return NULL;
     711                 :         
     712               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     713                 : 
     714                 :     // Geometry
     715                 :     int         nGeomId;
     716                 :     
     717                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[0],
     718               0 :                                                              &nGeomId));
     719                 : 
     720                 :     // GEOM_ID
     721               0 :     poFeature->SetField( 0, nGeomId );
     722                 : 
     723                 :     // Attributes
     724                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     725                 :                                     "FC", 1, "LK", 2, "HW", 3,
     726               0 :                                     NULL );
     727                 : 
     728               0 :     return poFeature;
     729                 : }
     730                 : 
     731                 : /************************************************************************/
     732                 : /*                        TranslateBL2000Poly()                         */
     733                 : /************************************************************************/
     734                 : 
     735               0 : static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
     736                 :                                         OGRNTFLayer *poLayer,
     737                 :                                         NTFRecord **papoGroup )
     738                 : 
     739                 : {
     740                 : /* ==================================================================== */
     741                 : /*      Traditional POLYGON record groups.                              */
     742                 : /* ==================================================================== */
     743               0 :     if( CSLCount((char **) papoGroup) == 3 
     744               0 :         && papoGroup[0]->GetType() == NRT_POLYGON
     745               0 :         && papoGroup[1]->GetType() == NRT_ATTREC 
     746               0 :         && papoGroup[2]->GetType() == NRT_CHAIN  )
     747                 :     {
     748                 :         
     749               0 :         OGRFeature      *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     750                 : 
     751                 :         // POLY_ID
     752               0 :         poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     753                 : 
     754                 :         // NUM_PARTS
     755               0 :         int             nNumLinks = atoi(papoGroup[2]->GetField( 9, 12 ));
     756                 :     
     757               0 :         if( nNumLinks > MAX_LINK )
     758                 :         {
     759                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     760               0 :                       "MAX_LINK exceeded in ntf_estlayers.cpp." );
     761                 : 
     762               0 :             return poFeature;
     763                 :         }
     764                 :     
     765               0 :         poFeature->SetField( 3, nNumLinks );
     766                 : 
     767                 :         // DIR
     768                 :         int             i, anList[MAX_LINK];
     769                 : 
     770               0 :         for( i = 0; i < nNumLinks; i++ )
     771               0 :             anList[i] = atoi(papoGroup[2]->GetField( 19+i*7, 19+i*7 ));
     772                 : 
     773               0 :         poFeature->SetField( 4, nNumLinks, anList );
     774                 : 
     775                 :         // GEOM_ID_OF_LINK
     776               0 :         for( i = 0; i < nNumLinks; i++ )
     777               0 :             anList[i] = atoi(papoGroup[2]->GetField( 13+i*7, 18+i*7 ));
     778                 : 
     779               0 :         poFeature->SetField( 5, nNumLinks, anList );
     780                 : 
     781                 :         // RingStart
     782               0 :         int     nRingList = 0;
     783               0 :         poFeature->SetField( 6, 1, &nRingList );
     784                 : 
     785                 :         // Attributes
     786                 :         poReader->ApplyAttributeValues( poFeature, papoGroup,
     787                 :                                         "PI", 1, "HA", 2,
     788               0 :                                         NULL );
     789                 : 
     790                 :         // Try to assemble polygon geometry.
     791               0 :         poReader->FormPolygonFromCache( poFeature );
     792                 : 
     793               0 :         return poFeature;
     794                 :     }
     795                 : 
     796                 : /* ==================================================================== */
     797                 : /*      CPOLYGON Group                                                  */
     798                 : /* ==================================================================== */
     799                 : 
     800                 : /* -------------------------------------------------------------------- */
     801                 : /*      First we do validation of the grouping.                         */
     802                 : /* -------------------------------------------------------------------- */
     803                 :     int         iRec;
     804                 :     
     805               0 :     for( iRec = 0;
     806               0 :          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
     807               0 :              && papoGroup[iRec]->GetType() == NRT_POLYGON
     808               0 :              && papoGroup[iRec+1]->GetType() == NRT_CHAIN;
     809                 :          iRec += 2 ) {}
     810                 : 
     811               0 :     if( CSLCount((char **) papoGroup) != iRec + 2 )
     812               0 :         return NULL;
     813                 : 
     814               0 :     if( papoGroup[iRec]->GetType() != NRT_CPOLY
     815               0 :         || papoGroup[iRec+1]->GetType() != NRT_ATTREC )
     816               0 :         return NULL;
     817                 : 
     818                 : /* -------------------------------------------------------------------- */
     819                 : /*      Collect the chains for each of the rings, and just aggregate    */
     820                 : /*      these into the master list without any concept of where the     */
     821                 : /*      boundaries are.  The boundary information will be emmitted      */
     822                 : /*      in the RingStart field.                                         */
     823                 : /* -------------------------------------------------------------------- */
     824               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     825               0 :     int         nNumLink = 0;
     826                 :     int         anDirList[MAX_LINK*2], anGeomList[MAX_LINK*2];
     827               0 :     int         anRingStart[MAX_LINK], nRings = 0;
     828                 : 
     829               0 :     for( iRec = 0;
     830               0 :          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
     831               0 :              && papoGroup[iRec]->GetType() == NRT_POLYGON
     832               0 :              && papoGroup[iRec+1]->GetType() == NRT_CHAIN;
     833                 :          iRec += 2 )
     834                 :     {
     835                 :         int             i, nLineCount;
     836                 : 
     837               0 :         nLineCount = atoi(papoGroup[iRec+1]->GetField(9,12));
     838                 : 
     839               0 :         anRingStart[nRings++] = nNumLink;
     840                 :         
     841               0 :         for( i = 0; i < nLineCount && nNumLink < MAX_LINK*2; i++ )
     842                 :         {
     843               0 :             anDirList[nNumLink] =
     844               0 :                 atoi(papoGroup[iRec+1]->GetField( 19+i*7, 19+i*7 ));
     845               0 :             anGeomList[nNumLink] =
     846               0 :                 atoi(papoGroup[iRec+1]->GetField( 13+i*7, 18+i*7 ));
     847               0 :             nNumLink++;
     848                 :         }
     849                 : 
     850               0 :         if( nNumLink == MAX_LINK*2 )
     851                 :         {
     852                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     853               0 :                       "MAX_LINK exceeded in ntf_estlayers.cpp." );
     854                 : 
     855               0 :             delete poFeature;
     856               0 :             return NULL;
     857                 :         }
     858                 :     }
     859                 : 
     860                 :     // NUM_PART
     861               0 :     poFeature->SetField( 3, nNumLink );
     862                 : 
     863                 :     // DIR
     864               0 :     poFeature->SetField( 4, nNumLink, anDirList );
     865                 : 
     866                 :     // GEOM_ID_OF_LINK
     867               0 :     poFeature->SetField( 5, nNumLink, anGeomList );
     868                 : 
     869                 :     // RingStart
     870               0 :     poFeature->SetField( 6, nRings, anRingStart );
     871                 : 
     872                 :     
     873                 : /* -------------------------------------------------------------------- */
     874                 : /*      collect information for whole complex polygon.                  */
     875                 : /* -------------------------------------------------------------------- */
     876                 :     // POLY_ID
     877               0 :     poFeature->SetField( 0, atoi(papoGroup[iRec]->GetField( 3, 8 )) );
     878                 : 
     879                 :     // Attributes
     880                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     881                 :                                     "PI", 1, "HA", 2,
     882               0 :                                     NULL );
     883                 : 
     884                 :     // Try to assemble polygon geometry.
     885               0 :     poReader->FormPolygonFromCache( poFeature );
     886                 : 
     887               0 :     return poFeature;
     888                 : }
     889                 : 
     890                 : /************************************************************************/
     891                 : /*                        TranslateBL2000Link()                         */
     892                 : /************************************************************************/
     893                 : 
     894               0 : static OGRFeature *TranslateBL2000Link( NTFFileReader *poReader,
     895                 :                                         OGRNTFLayer *poLayer,
     896                 :                                         NTFRecord **papoGroup )
     897                 : 
     898                 : {
     899               0 :     if( CSLCount((char **) papoGroup) != 3
     900               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
     901               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY
     902               0 :         || papoGroup[2]->GetType() != NRT_ATTREC )
     903               0 :         return NULL;
     904                 :         
     905               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     906                 : 
     907                 :     // LINE_ID
     908               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     909                 : 
     910                 :     // Geometry
     911                 :     int         nGeomId;
     912                 :     
     913                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
     914               0 :                                                              &nGeomId));
     915                 : 
     916                 :     // GEOM_ID
     917               0 :     poFeature->SetField( 1, nGeomId );
     918                 : 
     919                 :     // Attributes
     920                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     921                 :                                     "FC", 2, "LK", 3, 
     922               0 :                                     NULL );
     923                 : 
     924               0 :     return poFeature;
     925                 : }
     926                 : 
     927                 : /************************************************************************/
     928                 : /*                     TranslateBL2000Collection()                      */
     929                 : /************************************************************************/
     930                 : 
     931               0 : static OGRFeature *TranslateBL2000Collection( NTFFileReader *poReader,
     932                 :                                               OGRNTFLayer *poLayer,
     933                 :                                               NTFRecord **papoGroup )
     934                 : 
     935                 : {
     936               0 :     if( CSLCount((char **) papoGroup) < 2
     937               0 :         || papoGroup[0]->GetType() != NRT_COLLECT
     938               0 :         || papoGroup[1]->GetType() != NRT_ATTREC )
     939               0 :         return NULL;
     940                 :         
     941               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
     942                 : 
     943                 :     // COLL_ID
     944               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
     945                 : 
     946                 :     // NUM_PARTS
     947               0 :     int         nNumLinks = atoi(papoGroup[0]->GetField( 9, 12 ));
     948                 :     
     949               0 :     if( nNumLinks > MAX_LINK )
     950                 :     {
     951                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     952               0 :                   "MAX_LINK exceeded in ntf_estlayers.cpp." );
     953                 : 
     954               0 :         return poFeature;
     955                 :     }
     956                 :     
     957               0 :     poFeature->SetField( 1, nNumLinks );
     958                 : 
     959                 :     // POLY_ID / COLL_ID_REFS
     960                 :     int         i, anList[MAX_LINK], anCollList[MAX_LINK];
     961               0 :     int         nPolys=0, nCollections=0;
     962                 : 
     963               0 :     for( i = 0; i < nNumLinks; i++ )
     964                 :     {
     965               0 :         if( atoi(papoGroup[0]->GetField( 13+i*8, 14+i*8 )) == 34 )
     966               0 :             anCollList[nCollections++] = 
     967               0 :                 atoi(papoGroup[0]->GetField( 15+i*8, 20+i*8 ));
     968                 :         else
     969               0 :             anList[nPolys++] = 
     970               0 :                 atoi(papoGroup[0]->GetField( 15+i*8, 20+i*8 ));
     971                 :     }
     972                 : 
     973               0 :     poFeature->SetField( 2, nPolys, anList );
     974               0 :     poFeature->SetField( 10, nCollections, anCollList );
     975                 : 
     976                 :     // Attributes
     977                 :     // Node that _CODE_DESC values are automatically applied if
     978                 :     // the target fields exist. 
     979                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
     980                 :                                     "AI", 3, "OP", 4, "NM", 5, "TY", 6, 
     981                 :                                     "AC", 7, "NB", 8, "NA", 9,
     982               0 :                                     NULL );
     983                 : 
     984               0 :     return poFeature;
     985                 : }
     986                 : 
     987                 : /************************************************************************/
     988                 : /*                      TranslateMeridianPoint()                        */
     989                 : /************************************************************************/
     990                 : 
     991               0 : static OGRFeature *TranslateMeridianPoint( NTFFileReader *poReader,
     992                 :                                            OGRNTFLayer *poLayer,
     993                 :                                            NTFRecord **papoGroup )
     994                 : 
     995                 : {
     996               0 :     if( CSLCount((char **) papoGroup) < 2
     997               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
     998               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
     999               0 :         return NULL;
    1000                 :         
    1001               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1002                 : 
    1003                 :     // POINT_ID
    1004               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1005                 : 
    1006                 :     // Geometry
    1007                 :     int         nGeomId;
    1008                 :     
    1009                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
    1010               0 :                                                              &nGeomId));
    1011                 : 
    1012                 :     // GEOM_ID
    1013               0 :     poFeature->SetField( 1, nGeomId );
    1014                 : 
    1015                 :     // Attributes
    1016                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1017                 :                                     "FC", 2, "PN", 3, "OS", 4, "JN", 5,
    1018                 :                                     "RT", 6, "SI", 7, "PI", 8, "NM", 9,
    1019                 :                                     "DA", 10, 
    1020               0 :                                     NULL );
    1021                 : 
    1022               0 :     return poFeature;
    1023                 : }
    1024                 : 
    1025                 : /************************************************************************/
    1026                 : /*                       TranslateMeridianLine()                        */
    1027                 : /************************************************************************/
    1028                 : 
    1029               0 : static OGRFeature *TranslateMeridianLine( NTFFileReader *poReader,
    1030                 :                                           OGRNTFLayer *poLayer,
    1031                 :                                           NTFRecord **papoGroup )
    1032                 : 
    1033                 : {
    1034               0 :     if( CSLCount((char **) papoGroup) < 2
    1035               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
    1036               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1037               0 :         return NULL;
    1038                 :         
    1039               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1040                 : 
    1041                 :     // LINE_ID
    1042               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1043                 : 
    1044                 :     // Geometry
    1045                 :     int         nGeomId;
    1046                 :     
    1047                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
    1048               0 :                                                              &nGeomId));
    1049                 : 
    1050                 :     // GEOM_ID
    1051               0 :     poFeature->SetField( 2, nGeomId );
    1052                 : 
    1053                 :     // Attributes
    1054                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1055                 :                                     "FC", 1, "OM", 3, "RN", 4, "TR", 5,
    1056                 :                                     "RI", 6, "LC", 7, "RC", 8, "LD", 9,
    1057                 :                                     "RD", 10, 
    1058               0 :                                     NULL );
    1059                 : 
    1060               0 :     return poFeature;
    1061                 : }
    1062                 : 
    1063                 : /************************************************************************/
    1064                 : /*                      TranslateMeridian2Point()                       */
    1065                 : /************************************************************************/
    1066                 : 
    1067             409 : static OGRFeature *TranslateMeridian2Point( NTFFileReader *poReader,
    1068                 :                                             OGRNTFLayer *poLayer,
    1069                 :                                             NTFRecord **papoGroup )
    1070                 : 
    1071                 : {
    1072            1227 :     if( CSLCount((char **) papoGroup) < 2
    1073             409 :         || papoGroup[0]->GetType() != NRT_POINTREC
    1074             409 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1075               0 :         return NULL;
    1076                 :         
    1077             409 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1078                 : 
    1079                 :     // POINT_ID
    1080             409 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1081                 : 
    1082                 :     // Geometry
    1083                 :     int         nGeomId;
    1084                 :     
    1085                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
    1086             409 :                                                              &nGeomId));
    1087                 : 
    1088                 :     // GEOM_ID
    1089             409 :     poFeature->SetField( 1, nGeomId );
    1090                 : 
    1091                 :     // Attributes
    1092                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1093                 :                                     "FC", 2, "PN", 3, "OD", 4, "PO", 5, 
    1094                 :                                     "JN", 6, "RT", 7, "SN", 8, "SI", 9, 
    1095                 :                                     "PI", 10, "NM", 11, "DA", 12, 
    1096                 :                                     "WA", 13, "HT", 14, "FA", 15,
    1097             409 :                                     NULL );
    1098                 : 
    1099             409 :     return poFeature;
    1100                 : }
    1101                 : 
    1102                 : /************************************************************************/
    1103                 : /*                       TranslateMeridian2Line()                       */
    1104                 : /************************************************************************/
    1105                 : 
    1106             514 : static OGRFeature *TranslateMeridian2Line( NTFFileReader *poReader,
    1107                 :                                            OGRNTFLayer *poLayer,
    1108                 :                                            NTFRecord **papoGroup )
    1109                 : 
    1110                 : {
    1111            1542 :     if( CSLCount((char **) papoGroup) < 2
    1112             514 :         || papoGroup[0]->GetType() != NRT_LINEREC
    1113             514 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1114               0 :         return NULL;
    1115                 :         
    1116             514 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1117                 : 
    1118                 :     // LINE_ID
    1119             514 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1120                 : 
    1121                 :     // Geometry
    1122                 :     int         nGeomId;
    1123                 :     
    1124                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
    1125             514 :                                                              &nGeomId));
    1126                 : 
    1127                 :     // GEOM_ID
    1128             514 :     poFeature->SetField( 2, nGeomId );
    1129                 : 
    1130                 :     // Attributes
    1131                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1132                 :                                     "FC", 1, "OD", 3, "PO", 4, "RN", 5, 
    1133                 :                                     "TR", 6, "PN", 7, "RI", 8, "LC", 9,
    1134                 :                                     "RC", 10, "LD", 11, "RD", 12, "WI", 14,
    1135             514 :                                     NULL );
    1136                 : 
    1137                 : 
    1138             514 :     return poFeature;
    1139                 : }
    1140                 : 
    1141                 : /************************************************************************/
    1142                 : /*                       TranslateStrategiNode()                        */
    1143                 : /*                                                                      */
    1144                 : /*      Also used for Meridian, Oscar and BaseData.GB nodes.            */
    1145                 : /************************************************************************/
    1146                 : 
    1147           11388 : static OGRFeature *TranslateStrategiNode( NTFFileReader *poReader,
    1148                 :                                           OGRNTFLayer *poLayer,
    1149                 :                                           NTFRecord **papoGroup )
    1150                 : 
    1151                 : {
    1152           22776 :     if( CSLCount((char **) papoGroup) != 1 
    1153           11388 :         || papoGroup[0]->GetType() != NRT_NODEREC )
    1154               0 :         return NULL;
    1155                 :         
    1156           11388 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1157                 : 
    1158                 :     // NODE_ID
    1159           11388 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1160                 : 
    1161                 :     // GEOM_ID_OF_POINT
    1162           11388 :     poFeature->SetField( 1, atoi(papoGroup[0]->GetField( 9, 14 )) );
    1163                 : 
    1164                 :     // NUM_LINKS
    1165           11388 :     int         nNumLinks = atoi(papoGroup[0]->GetField( 15, 18 ));
    1166                 :     
    1167           11388 :     if( nNumLinks > MAX_LINK )
    1168                 :     {
    1169                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1170               0 :                   "MAX_LINK exceeded in ntf_estlayers.cpp." );
    1171                 : 
    1172               0 :         return poFeature;
    1173                 :     }
    1174                 :     
    1175           11388 :     poFeature->SetField( 2, nNumLinks );
    1176                 : 
    1177                 :     // DIR
    1178                 :     int         i, anList[MAX_LINK];
    1179                 : 
    1180           41521 :     for( i = 0; i < nNumLinks; i++ )
    1181           30133 :         anList[i] = atoi(papoGroup[0]->GetField( 19+i*12, 19+i*12 ));
    1182                 : 
    1183           11388 :     poFeature->SetField( 3, nNumLinks, anList );
    1184                 : 
    1185                 :     // GEOM_ID_OF_POINT
    1186           41521 :     for( i = 0; i < nNumLinks; i++ )
    1187           30133 :         anList[i] = atoi(papoGroup[0]->GetField( 19+i*12+1, 19+i*12+6 ));
    1188                 : 
    1189           11388 :     poFeature->SetField( 4, nNumLinks, anList );
    1190                 : 
    1191                 :     // LEVEL
    1192           41521 :     for( i = 0; i < nNumLinks; i++ )
    1193           30133 :         anList[i] = atoi(papoGroup[0]->GetField( 19+i*12+11, 19+i*12+11 ));
    1194                 : 
    1195           11388 :     poFeature->SetField( 5, nNumLinks, anList );
    1196                 :     
    1197                 :     // ORIENT (optional)
    1198           11388 :     if( EQUAL(poFeature->GetDefnRef()->GetFieldDefn(6)->GetNameRef(),
    1199                 :               "ORIENT") )
    1200                 :     {
    1201                 :         double  adfList[MAX_LINK];
    1202                 : 
    1203           41521 :         for( i = 0; i < nNumLinks; i++ )
    1204           30133 :             adfList[i] =
    1205           30133 :                 atoi(papoGroup[0]->GetField( 19+i*12+7, 19+i*12+10 )) * 0.1;
    1206                 : 
    1207           11388 :         poFeature->SetField( 6, nNumLinks, adfList );
    1208                 :     }
    1209                 : 
    1210           11388 :     return poFeature;
    1211                 : }
    1212                 : 
    1213                 : /************************************************************************/
    1214                 : /*                       TranslateStrategiText()                        */
    1215                 : /*                                                                      */
    1216                 : /*      Also used for Meridian, BaseData and Generic text.              */
    1217                 : /************************************************************************/
    1218                 : 
    1219            1342 : static OGRFeature *TranslateStrategiText( NTFFileReader *poReader,
    1220                 :                                           OGRNTFLayer *poLayer,
    1221                 :                                           NTFRecord **papoGroup )
    1222                 : 
    1223                 : {
    1224            6710 :     if( CSLCount((char **) papoGroup) < 4
    1225            1342 :         || papoGroup[0]->GetType() != NRT_TEXTREC
    1226            1342 :         || papoGroup[1]->GetType() != NRT_TEXTPOS 
    1227            1342 :         || papoGroup[2]->GetType() != NRT_TEXTREP 
    1228            1342 :         || papoGroup[3]->GetType() != NRT_GEOMETRY )
    1229               0 :         return NULL;
    1230                 :         
    1231            1342 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1232                 : 
    1233                 :     // POINT_ID
    1234            1342 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1235                 : 
    1236                 :     // FONT
    1237            1342 :     poFeature->SetField( 2, atoi(papoGroup[2]->GetField( 9, 12 )) );
    1238                 : 
    1239                 :     // TEXT_HT
    1240            1342 :     poFeature->SetField( 3, atoi(papoGroup[2]->GetField( 13, 15 )) * 0.1 );
    1241                 : 
    1242                 :     // DIG_POSTN
    1243            1342 :     poFeature->SetField( 4, atoi(papoGroup[2]->GetField( 16, 16 )) );
    1244                 : 
    1245                 :     // ORIENT
    1246            1342 :     poFeature->SetField( 5, atoi(papoGroup[2]->GetField( 17, 20 )) * 0.1 );
    1247                 : 
    1248                 :     // TEXT_HT_GROUND
    1249                 :     poFeature->SetField( 7, poFeature->GetFieldAsDouble(3)
    1250            1342 :                          * poReader->GetPaperToGround() );
    1251                 : 
    1252                 :     // Geometry
    1253            1342 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[3]));
    1254                 : 
    1255                 :     // Attributes
    1256                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1257                 :                                     "FC", 1, "TX", 6, "DE", 8,
    1258            1342 :                                     NULL );
    1259                 : 
    1260            1342 :     return poFeature;
    1261                 : }
    1262                 : 
    1263                 : /************************************************************************/
    1264                 : /*                      TranslateStrategiPoint()                        */
    1265                 : /************************************************************************/
    1266                 : 
    1267            9194 : static OGRFeature *TranslateStrategiPoint( NTFFileReader *poReader,
    1268                 :                                            OGRNTFLayer *poLayer,
    1269                 :                                            NTFRecord **papoGroup )
    1270                 : 
    1271                 : {
    1272           27582 :     if( CSLCount((char **) papoGroup) < 2
    1273            9194 :         || papoGroup[0]->GetType() != NRT_POINTREC
    1274            9194 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1275               0 :         return NULL;
    1276                 :         
    1277            9194 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1278                 : 
    1279                 :     // POINT_ID
    1280            9194 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1281                 : 
    1282                 :     // Geometry
    1283                 :     int         nGeomId;
    1284                 :     
    1285                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
    1286            9194 :                                                              &nGeomId));
    1287                 : 
    1288                 :     // GEOM_ID
    1289            9194 :     poFeature->SetField( 10, nGeomId );
    1290                 : 
    1291                 :     // Attributes
    1292                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1293                 :                                     "FC",  1, "PN",  2, "NU",  3, "RB",  4,
    1294                 :                                     "RU",  5, "AN",  6, "AO",  7, "CM",  8,
    1295                 :                                     "UN",  9, "DE", 11, "DN", 12, "FM", 13,
    1296                 :                                     "GS", 14, "HI", 15, "HM", 16, "LO", 17,
    1297                 :                                     "OR", 18, "OW", 19, "RJ", 20, "RL", 21,
    1298                 :                                     "RM", 22, "RQ", 23, "RW", 24, "RZ", 25,
    1299                 :                                     "UE", 26,
    1300            9194 :                                     NULL );
    1301                 : 
    1302            9194 :     return poFeature;
    1303                 : }
    1304                 : 
    1305                 : /************************************************************************/
    1306                 : /*                       TranslateStrategiLine()                        */
    1307                 : /************************************************************************/
    1308                 : 
    1309            8369 : static OGRFeature *TranslateStrategiLine( NTFFileReader *poReader,
    1310                 :                                           OGRNTFLayer *poLayer,
    1311                 :                                           NTFRecord **papoGroup )
    1312                 : 
    1313                 : {
    1314           25107 :     if( CSLCount((char **) papoGroup) < 2
    1315            8369 :         || papoGroup[0]->GetType() != NRT_LINEREC
    1316            8369 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1317               0 :         return NULL;
    1318                 :         
    1319            8369 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1320                 : 
    1321                 :     // LINE_ID
    1322            8369 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1323                 : 
    1324                 :     // Geometry
    1325                 :     int         nGeomId;
    1326                 :     
    1327                 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
    1328            8369 :                                                              &nGeomId));
    1329                 : 
    1330                 :     // GEOM_ID
    1331            8369 :     poFeature->SetField( 3, nGeomId );
    1332                 : 
    1333                 :     // Attributes
    1334                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1335                 :                                     "FC",   1, "PN",  2, "DE",  4, "FE",  5,
    1336                 :                                     "FF",   6, "FI",  7, "FM",  8, "FP",  9,
    1337                 :                                     "FR",  10, "FT", 11, "GS", 12, "NU", 13,
    1338                 :                                     "TX", 14,
    1339            8369 :                                     NULL );
    1340                 : 
    1341            8369 :     return poFeature;
    1342                 : }
    1343                 : 
    1344                 : /************************************************************************/
    1345                 : /*                      TranslateLandrangerPoint()                      */
    1346                 : /************************************************************************/
    1347                 : 
    1348               0 : static OGRFeature *TranslateLandrangerPoint( NTFFileReader *poReader,
    1349                 :                                              OGRNTFLayer *poLayer,
    1350                 :                                              NTFRecord **papoGroup )
    1351                 : 
    1352                 : {
    1353               0 :     if( CSLCount((char **) papoGroup) != 2
    1354               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
    1355               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1356               0 :         return NULL;
    1357                 :         
    1358               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1359                 : 
    1360                 :     // POINT_ID
    1361               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1362                 : 
    1363                 :     // FEAT_CODE
    1364               0 :     poFeature->SetField( 1, papoGroup[0]->GetField( 17, 20 ) );
    1365                 : 
    1366                 :     // HEIGHT
    1367               0 :     poFeature->SetField( 2, atoi(papoGroup[0]->GetField( 11, 16 )) );
    1368                 :     
    1369                 :     // Geometry
    1370               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
    1371                 : 
    1372               0 :     return poFeature;
    1373                 : }
    1374                 : 
    1375                 : /************************************************************************/
    1376                 : /*                      TranslateLandrangerLine()                       */
    1377                 : /************************************************************************/
    1378                 : 
    1379               0 : static OGRFeature *TranslateLandrangerLine( NTFFileReader *poReader,
    1380                 :                                             OGRNTFLayer *poLayer,
    1381                 :                                             NTFRecord **papoGroup )
    1382                 : 
    1383                 : {
    1384               0 :     if( CSLCount((char **) papoGroup) != 2
    1385               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
    1386               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1387               0 :         return NULL;
    1388                 :         
    1389               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1390                 : 
    1391                 :     // LINE_ID
    1392               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1393                 : 
    1394                 :     // FEAT_CODE
    1395               0 :     poFeature->SetField( 1, papoGroup[0]->GetField( 17, 20 ) );
    1396                 : 
    1397                 :     // HEIGHT
    1398               0 :     poFeature->SetField( 2, atoi(papoGroup[0]->GetField( 11, 16 )) );
    1399                 : 
    1400                 :     // Geometry
    1401               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
    1402                 : 
    1403               0 :     return poFeature;
    1404                 : }
    1405                 : 
    1406                 : /************************************************************************/
    1407                 : /*                       TranslateProfilePoint()                        */
    1408                 : /************************************************************************/
    1409                 : 
    1410               0 : static OGRFeature *TranslateProfilePoint( NTFFileReader *poReader,
    1411                 :                                           OGRNTFLayer *poLayer,
    1412                 :                                           NTFRecord **papoGroup )
    1413                 : 
    1414                 : {
    1415               0 :     if( CSLCount((char **) papoGroup) < 2 
    1416               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
    1417               0 :         || (papoGroup[1]->GetType() != NRT_GEOMETRY
    1418               0 :             && papoGroup[1]->GetType() != NRT_GEOMETRY3D) )
    1419               0 :         return NULL;
    1420                 :         
    1421               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1422                 : 
    1423                 :     // POINT_ID
    1424               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1425                 : 
    1426                 :     // FEAT_CODE
    1427               0 :     poFeature->SetField( 1, papoGroup[0]->GetField( 17, 20 ) );
    1428                 : 
    1429                 :     // Geometry
    1430               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
    1431                 : 
    1432                 :     // Attributes 
    1433                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1434                 :                                     "HT", 2,
    1435               0 :                                     NULL );
    1436                 : 
    1437                 :     // Set HEIGHT/elevation
    1438               0 :     OGRPoint    *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
    1439                 :     
    1440               0 :     if( poPoint != NULL && poPoint->getCoordinateDimension() == 3 )
    1441                 :     {
    1442               0 :         poFeature->SetField( 2, poPoint->getZ() );
    1443                 :     }
    1444               0 :     else if( poPoint != NULL )
    1445                 :     {
    1446               0 :         poFeature->SetField( 2, poFeature->GetFieldAsDouble(2) * 0.01 );
    1447               0 :         poPoint->setZ( poFeature->GetFieldAsDouble(2) );
    1448                 :     }
    1449                 :     
    1450               0 :     return poFeature;
    1451                 : }
    1452                 : 
    1453                 : /************************************************************************/
    1454                 : /*                      TranslateProfileLine()                          */
    1455                 : /************************************************************************/
    1456                 : 
    1457               0 : static OGRFeature *TranslateProfileLine( NTFFileReader *poReader,
    1458                 :                                          OGRNTFLayer *poLayer,
    1459                 :                                          NTFRecord **papoGroup )
    1460                 : 
    1461                 : {
    1462               0 :     if( CSLCount((char **) papoGroup) < 2
    1463               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
    1464               0 :         || (papoGroup[1]->GetType() != NRT_GEOMETRY
    1465               0 :             && papoGroup[1]->GetType() != NRT_GEOMETRY3D) )
    1466               0 :         return NULL;
    1467                 :         
    1468               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1469                 : 
    1470                 :     // LINE_ID
    1471               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1472                 : 
    1473                 :     // FEAT_CODE
    1474               0 :     poFeature->SetField( 1, papoGroup[0]->GetField( 17, 20 ) );
    1475                 : 
    1476                 :     // Geometry
    1477               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
    1478                 : 
    1479                 :     // Attributes 
    1480                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1481                 :                                     "HT", 2,
    1482               0 :                                     NULL );
    1483                 :     
    1484                 :     // Set HEIGHT/elevation
    1485               0 :     OGRLineString *poLine = (OGRLineString *) poFeature->GetGeometryRef();
    1486                 :     
    1487               0 :     poFeature->SetField( 2, poFeature->GetFieldAsDouble(2) * 0.01 );
    1488               0 :     if( poLine != NULL && poLine->getCoordinateDimension() == 2 )
    1489                 :     {
    1490               0 :         for( int i = 0; i < poLine->getNumPoints(); i++ )
    1491                 :         {
    1492                 :             poLine->setPoint( i, poLine->getX(i), poLine->getY(i),
    1493               0 :                               poFeature->GetFieldAsDouble(2) );
    1494                 :         }
    1495                 :     }
    1496               0 :     else if( poLine != NULL )
    1497                 :     {
    1498               0 :         double  dfAccum = 0.0;
    1499                 :         
    1500               0 :         for( int i = 0; i < poLine->getNumPoints(); i++ )
    1501                 :         {
    1502               0 :             dfAccum += poLine->getZ(i);
    1503                 :         }
    1504               0 :         poFeature->SetField( 2, dfAccum / poLine->getNumPoints() );
    1505                 :     }
    1506                 :     
    1507               0 :     return poFeature;
    1508                 : }
    1509                 : 
    1510                 : /************************************************************************/
    1511                 : /*                      TranslateLandlinePoint()                        */
    1512                 : /************************************************************************/
    1513                 : 
    1514               0 : static OGRFeature *TranslateLandlinePoint( NTFFileReader *poReader,
    1515                 :                                            OGRNTFLayer *poLayer,
    1516                 :                                            NTFRecord **papoGroup )
    1517                 : 
    1518                 : {
    1519               0 :     if( CSLCount((char **) papoGroup) < 2
    1520               0 :         || papoGroup[0]->GetType() != NRT_POINTREC
    1521               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1522               0 :         return NULL;
    1523                 :         
    1524               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1525                 : 
    1526                 :     // POINT_ID
    1527               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1528                 : 
    1529                 :     // FEAT_CODE
    1530               0 :     poFeature->SetField( 1, papoGroup[0]->GetField( 17, 20 ) );
    1531                 : 
    1532                 :     // ORIENT
    1533               0 :     poFeature->SetField( 2, atoi(papoGroup[0]->GetField( 11, 16 )) * 0.1 );
    1534                 : 
    1535                 :     // DISTANCE
    1536                 :     poReader->ApplyAttributeValues( poFeature, papoGroup,
    1537                 :                                     "DT", 3,
    1538               0 :                                     NULL );
    1539                 : 
    1540                 :     // Geometry
    1541               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
    1542                 : 
    1543                 :     // CHG_DATE (optional)
    1544               0 :     if( poFeature->GetFieldIndex("CHG_DATE") == 4 )
    1545                 :     {
    1546               0 :         poFeature->SetField( 4, papoGroup[0]->GetField( 23, 28 ) );
    1547                 :     }
    1548                 : 
    1549                 :     // CHG_TYPE (optional)
    1550               0 :     if( poFeature->GetFieldIndex("CHG_TYPE") == 5 )
    1551                 :     {
    1552               0 :         poFeature->SetField( 5, papoGroup[0]->GetField( 22, 22 ) );
    1553                 :     }
    1554                 : 
    1555               0 :     return poFeature;
    1556                 : }
    1557                 : 
    1558                 : /************************************************************************/
    1559                 : /*                       TranslateLandlineLine()                        */
    1560                 : /************************************************************************/
    1561                 : 
    1562               0 : static OGRFeature *TranslateLandlineLine( NTFFileReader *poReader,
    1563                 :                                           OGRNTFLayer *poLayer,
    1564                 :                                           NTFRecord **papoGroup )
    1565                 : 
    1566                 : {
    1567               0 :     if( CSLCount((char **) papoGroup) != 2
    1568               0 :         || papoGroup[0]->GetType() != NRT_LINEREC
    1569               0 :         || papoGroup[1]->GetType() != NRT_GEOMETRY )
    1570               0 :         return NULL;
    1571                 :         
    1572               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1573                 : 
    1574                 :     // LINE_ID
    1575               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1576                 : 
    1577                 :     // FEAT_CODE
    1578               0 :     poFeature->SetField( 1, papoGroup[0]->GetField( 17, 20 ) );
    1579                 : 
    1580                 :     // Geometry
    1581               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
    1582                 : 
    1583                 :     // CHG_DATE (optional)
    1584               0 :     if( poFeature->GetFieldIndex("CHG_DATE") == 2 )
    1585                 :     {
    1586               0 :         poFeature->SetField( 2, papoGroup[0]->GetField( 23, 28 ) );
    1587                 :     }
    1588                 : 
    1589                 :     // CHG_TYPE (optional)
    1590               0 :     if( poFeature->GetFieldIndex("CHG_TYPE") == 3 )
    1591                 :     {
    1592               0 :         poFeature->SetField( 3, papoGroup[0]->GetField( 22, 22 ) );
    1593                 :     }
    1594               0 :     return poFeature;
    1595                 : }
    1596                 : 
    1597                 : /************************************************************************/
    1598                 : /*                       TranslateLandlineName()                        */
    1599                 : /************************************************************************/
    1600                 : 
    1601               0 : static OGRFeature *TranslateLandlineName( NTFFileReader *poReader,
    1602                 :                                           OGRNTFLayer *poLayer,
    1603                 :                                           NTFRecord **papoGroup )
    1604                 : 
    1605                 : {
    1606               0 :     if( CSLCount((char **) papoGroup) != 3 
    1607               0 :         || papoGroup[0]->GetType() != NRT_NAMEREC
    1608               0 :         || papoGroup[1]->GetType() != NRT_NAMEPOSTN
    1609               0 :         || papoGroup[2]->GetType() != NRT_GEOMETRY )
    1610               0 :         return NULL;
    1611                 :         
    1612               0 :     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
    1613                 :         
    1614                 :     // NAME_ID
    1615               0 :     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
    1616                 :         
    1617                 :     // TEXT_CODE
    1618               0 :     poFeature->SetField( 1, papoGroup[0]->GetField( 9, 12 ) );
    1619                 :         
    1620                 :     // TEXT
    1621               0 :     int         nNumChar = atoi(papoGroup[0]->GetField(13,14));
    1622               0 :     poFeature->SetField( 2, papoGroup[0]->GetField( 15, 15+nNumChar-1) );
    1623                 :     
    1624                 :     // FONT
    1625               0 :     poFeature->SetField( 3, atoi(papoGroup[1]->GetField( 3, 6 )) );
    1626                 : 
    1627                 :     // TEXT_HT
    1628               0 :     poFeature->SetField( 4, atoi(papoGroup[1]->GetField(7,9)) * 0.1 );
    1629                 :         
    1630                 :     // DIG_POSTN
    1631               0 :     poFeature->SetField( 5, atoi(papoGroup[1]->GetField(10,10)) );
    1632                 :         
    1633                 :     // ORIENT
    1634               0 :     poFeature->SetField( 6, atof(papoGroup[1]->GetField( 11, 14 )) * 0.1 );
    1635                 : 
    1636                 :     // TEXT_HT_GROUND
    1637                 :     poFeature->SetField( 7, poFeature->GetFieldAsDouble(4)
    1638               0 :                          * poReader->GetPaperToGround() );
    1639                 : 
    1640                 :     // CHG_DATE (optional)
    1641               0 :     if( poFeature->GetFieldIndex("CHG_DATE") == 7 )
    1642                 :     {
    1643               0 :         poFeature->SetField( 8, papoGroup[0]->GetField( 15+nNumChar+2,
    1644               0 :                                                         15+nNumChar+2+5) );
    1645                 :     }
    1646                 : 
    1647                 :     // CHG_TYPE (optional)
    1648               0 :     if( poFeature->GetFieldIndex("CHG_TYPE") == 9 )
    1649                 :     {
    1650               0 :         poFeature->SetField( 9, papoGroup[0]->GetField( 15+nNumChar+1, 
    1651               0 :                                                         15+nNumChar+1 ) );
    1652                 :     }
    1653                 : 
    1654                 :     // Geometry
    1655               0 :     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[2]));
    1656                 : 
    1657               0 :     return poFeature;
    1658                 : }
    1659                 : 
    1660                 : /************************************************************************/
    1661                 : /*                           EstablishLayer()                           */
    1662                 : /*                                                                      */
    1663                 : /*      Establish one layer based on a simplified description of the    */
    1664                 : /*      fields to be present.                                           */
    1665                 : /************************************************************************/
    1666                 : 
    1667               8 : void NTFFileReader::EstablishLayer( const char * pszLayerName,
    1668                 :                                     OGRwkbGeometryType eGeomType,
    1669                 :                                     NTFFeatureTranslator pfnTranslator,
    1670                 :                                     int nLeadRecordType,
    1671                 :                                     NTFGenericClass *poClass,
    1672                 :                                     ... )
    1673                 : 
    1674                 : {
    1675                 :     va_list     hVaArgs;
    1676                 :     OGRFeatureDefn *poDefn;
    1677                 :     OGRNTFLayer         *poLayer;
    1678                 : 
    1679                 : /* -------------------------------------------------------------------- */
    1680                 : /*      Does this layer already exist?  If so, we do nothing            */
    1681                 : /*      ... note that we don't check the definition.                    */
    1682                 : /* -------------------------------------------------------------------- */
    1683               8 :     poLayer = poDS->GetNamedLayer(pszLayerName);
    1684                 : 
    1685                 : /* ==================================================================== */
    1686                 : /*      Create a new layer matching the request if we don't aleady      */
    1687                 : /*      have one.                                                       */
    1688                 : /* ==================================================================== */
    1689               8 :     if( poLayer == NULL )
    1690                 :     {
    1691                 : /* -------------------------------------------------------------------- */
    1692                 : /*      Create a new feature definition.                                */
    1693                 : /* -------------------------------------------------------------------- */
    1694               8 :         poDefn = new OGRFeatureDefn( pszLayerName );
    1695               8 :         poDefn->SetGeomType( eGeomType );
    1696               8 :         poDefn->Reference();
    1697                 : 
    1698                 : /* -------------------------------------------------------------------- */
    1699                 : /*      Fetch definitions of each field in turn.                        */
    1700                 : /* -------------------------------------------------------------------- */
    1701               8 :         va_start(hVaArgs, poClass);
    1702             102 :         while( TRUE )
    1703                 :         {
    1704             110 :             const char  *pszFieldName = va_arg(hVaArgs, const char *);
    1705                 :             OGRFieldType     eType;
    1706                 :             int          nWidth, nPrecision;
    1707                 :             
    1708             110 :             if( pszFieldName == NULL )
    1709                 :                 break;
    1710                 :             
    1711             102 :             eType = (OGRFieldType) va_arg(hVaArgs, int);
    1712             102 :             nWidth = va_arg(hVaArgs, int);
    1713             102 :             nPrecision = va_arg(hVaArgs, int);
    1714                 :             
    1715             102 :             OGRFieldDefn         oFieldDefn( pszFieldName, eType );
    1716             102 :             oFieldDefn.SetWidth( nWidth );
    1717             102 :             oFieldDefn.SetPrecision( nPrecision );
    1718                 :             
    1719             102 :             poDefn->AddFieldDefn( &oFieldDefn );
    1720                 :         }
    1721                 :         
    1722               8 :         va_end(hVaArgs);
    1723                 : 
    1724                 : /* -------------------------------------------------------------------- */
    1725                 : /*      Add attributes collected in the generic class survey.           */
    1726                 : /* -------------------------------------------------------------------- */
    1727               8 :         if( poClass != NULL )
    1728                 :         {
    1729               0 :             for( int iGAtt = 0; iGAtt < poClass->nAttrCount; iGAtt++ )
    1730                 :             {
    1731               0 :                 const char      *pszFormat = poClass->papszAttrFormats[iGAtt];
    1732               0 :                 OGRFieldDefn    oFieldDefn( poClass->papszAttrNames[iGAtt],
    1733               0 :                                             OFTInteger );
    1734                 : 
    1735               0 :                 if( EQUALN(pszFormat,"I",1) )
    1736                 :                 {
    1737               0 :                     oFieldDefn.SetType( OFTInteger );
    1738               0 :                     oFieldDefn.SetWidth( poClass->panAttrMaxWidth[iGAtt] );
    1739                 :                 }
    1740               0 :                 else if( EQUALN(pszFormat,"D",1)
    1741                 :                          || EQUALN(pszFormat,"A",1) )
    1742                 :                 {
    1743               0 :                     oFieldDefn.SetType( OFTString );
    1744               0 :                     oFieldDefn.SetWidth( poClass->panAttrMaxWidth[iGAtt] );
    1745                 :                 }
    1746               0 :                 else if( EQUALN(pszFormat,"R",1) )
    1747                 :                 {
    1748               0 :                     oFieldDefn.SetType( OFTReal );
    1749               0 :                     oFieldDefn.SetWidth( poClass->panAttrMaxWidth[iGAtt]+1 );
    1750               0 :                     if( pszFormat[2] == ',' )
    1751               0 :                         oFieldDefn.SetPrecision(atoi(pszFormat+3));
    1752               0 :                     else if( pszFormat[3] == ',' )
    1753               0 :                         oFieldDefn.SetPrecision(atoi(pszFormat+4));
    1754                 :                 }
    1755                 : 
    1756               0 :                 poDefn->AddFieldDefn( &oFieldDefn );
    1757                 : 
    1758                 :                 /* 
    1759                 :                 ** If this field can appear multiple times, create an
    1760                 :                 ** additional attribute to hold lists of values.  This
    1761                 :                 ** is always created as a variable length string field.
    1762                 :                 */
    1763               0 :                 if( poClass->pabAttrMultiple[iGAtt] )
    1764                 :                 {
    1765                 :                     char szName[128];
    1766                 : 
    1767                 :                     sprintf( szName, "%s_LIST", 
    1768               0 :                              poClass->papszAttrNames[iGAtt] );
    1769                 : 
    1770               0 :                     OGRFieldDefn oFieldDefnL( szName, OFTString );
    1771                 : 
    1772               0 :                     poDefn->AddFieldDefn( &oFieldDefnL );
    1773                 :                 }
    1774                 :             }
    1775                 :         }
    1776                 : 
    1777                 : /* -------------------------------------------------------------------- */
    1778                 : /*      Add the TILE_REF attribute.                                     */
    1779                 : /* -------------------------------------------------------------------- */
    1780               8 :         OGRFieldDefn     oTileID( "TILE_REF", OFTString );
    1781                 : 
    1782               8 :         oTileID.SetWidth( 10 );
    1783                 : 
    1784               8 :         poDefn->AddFieldDefn( &oTileID );
    1785                 :             
    1786                 : /* -------------------------------------------------------------------- */
    1787                 : /*      Create the layer, and give over to the data source object to    */
    1788                 : /*      maintain.                                                       */
    1789                 : /* -------------------------------------------------------------------- */
    1790               8 :         poLayer = new OGRNTFLayer( poDS, poDefn, pfnTranslator );
    1791                 : 
    1792              16 :         poDS->AddLayer( poLayer );
    1793                 :     }
    1794                 : 
    1795                 : /* -------------------------------------------------------------------- */
    1796                 : /*      Register this translator with this file reader for handling     */
    1797                 : /*      the indicate record type.                                       */
    1798                 : /* -------------------------------------------------------------------- */
    1799               8 :     apoTypeTranslation[nLeadRecordType] = poLayer;
    1800               8 : }
    1801                 : 
    1802                 : /************************************************************************/
    1803                 : /*                          EstablishLayers()                           */
    1804                 : /*                                                                      */
    1805                 : /*      This method is responsible for creating any missing             */
    1806                 : /*      OGRNTFLayers needed for the current product based on the        */
    1807                 : /*      product name.                                                   */
    1808                 : /*                                                                      */
    1809                 : /*      NOTE: Any changes to the order of attribute fields in the       */
    1810                 : /*      following EstablishLayer() calls must also result in updates    */
    1811                 : /*      to the translate functions.  Changes of names, widths and to    */
    1812                 : /*      some extent types can be done without side effects.             */
    1813                 : /************************************************************************/
    1814                 : 
    1815               2 : void NTFFileReader::EstablishLayers()
    1816                 : 
    1817                 : {
    1818               2 :     if( poDS == NULL || fp == NULL )
    1819               0 :         return;
    1820                 : 
    1821               2 :     if( GetProductId() == NPC_LANDLINE )
    1822                 :     {
    1823                 :         EstablishLayer( "LANDLINE_POINT", wkbPoint,
    1824                 :                         TranslateLandlinePoint, NRT_POINTREC, NULL,
    1825                 :                         "POINT_ID", OFTInteger, 6, 0,
    1826                 :                         "FEAT_CODE", OFTString, 4, 0,
    1827                 :                         "ORIENT", OFTReal, 5, 1,
    1828                 :                         "DISTANCE", OFTReal, 6, 3,
    1829               0 :                         NULL );
    1830                 :                         
    1831                 :         EstablishLayer( "LANDLINE_LINE", wkbLineString,
    1832                 :                         TranslateLandlineLine, NRT_LINEREC, NULL,
    1833                 :                         "LINE_ID", OFTInteger, 6, 0,
    1834                 :                         "FEAT_CODE", OFTString, 4, 0,
    1835               0 :                         NULL );
    1836                 :                         
    1837                 :         EstablishLayer( "LANDLINE_NAME", wkbPoint,
    1838                 :                         TranslateLandlineName, NRT_NAMEREC, NULL,
    1839                 :                         "NAME_ID", OFTInteger, 6, 0,
    1840                 :                         "TEXT_CODE", OFTString, 4, 0,
    1841                 :                         "TEXT", OFTString, 0, 0,
    1842                 :                         "FONT", OFTInteger, 4, 0,
    1843                 :                         "TEXT_HT", OFTReal, 4, 1,
    1844                 :                         "DIG_POSTN", OFTInteger, 1, 0,
    1845                 :                         "ORIENT", OFTReal, 5, 1,
    1846                 :                         "TEXT_HT_GROUND", OFTReal, 10, 3,
    1847               0 :                         NULL );
    1848                 :     }
    1849               2 :     else if( GetProductId() == NPC_LANDLINE99 )
    1850                 :     {
    1851                 :         EstablishLayer( "LANDLINE99_POINT", wkbPoint,
    1852                 :                         TranslateLandlinePoint, NRT_POINTREC, NULL,
    1853                 :                         "POINT_ID", OFTInteger, 6, 0,
    1854                 :                         "FEAT_CODE", OFTString, 4, 0,
    1855                 :                         "ORIENT", OFTReal, 5, 1,
    1856                 :                         "DISTANCE", OFTReal, 6, 3,
    1857                 :                         "CHG_DATE", OFTString, 6, 0, 
    1858                 :                         "CHG_TYPE", OFTString, 1, 0, 
    1859               0 :                         NULL );
    1860                 :                         
    1861                 :         EstablishLayer( "LANDLINE99_LINE", wkbLineString,
    1862                 :                         TranslateLandlineLine, NRT_LINEREC, NULL,
    1863                 :                         "LINE_ID", OFTInteger, 6, 0,
    1864                 :                         "FEAT_CODE", OFTString, 4, 0,
    1865                 :                         "CHG_DATE", OFTString, 6, 0, 
    1866                 :                         "CHG_TYPE", OFTString, 1, 0, 
    1867               0 :                         NULL );
    1868                 :                         
    1869                 :         EstablishLayer( "LANDLINE99_NAME", wkbPoint,
    1870                 :                         TranslateLandlineName, NRT_NAMEREC, NULL,
    1871                 :                         "NAME_ID", OFTInteger, 6, 0,
    1872                 :                         "TEXT_CODE", OFTString, 4, 0,
    1873                 :                         "TEXT", OFTString, 0, 0,
    1874                 :                         "FONT", OFTInteger, 4, 0,
    1875                 :                         "TEXT_HT", OFTReal, 4, 1,
    1876                 :                         "DIG_POSTN", OFTInteger, 1, 0,
    1877                 :                         "ORIENT", OFTReal, 5, 1,
    1878                 :                         "TEXT_HT_GROUND", OFTReal, 10, 3,
    1879                 :                         "CHG_DATE", OFTString, 6, 0,
    1880                 :                         "CHG_TYPE", OFTString, 1, 0, 
    1881               0 :                         NULL );
    1882                 :     }
    1883               2 :     else if( GetProductId() == NPC_LANDRANGER_CONT )
    1884                 :     {
    1885                 :         EstablishLayer( "PANORAMA_POINT", wkbPoint,
    1886                 :                         TranslateLandrangerPoint, NRT_POINTREC, NULL,
    1887                 :                         "POINT_ID", OFTInteger, 6, 0,
    1888                 :                         "FEAT_CODE", OFTString, 4, 0,
    1889                 :                         "HEIGHT", OFTReal, 7, 2,
    1890               0 :                         NULL );
    1891                 :                         
    1892                 :         EstablishLayer( "PANORAMA_CONTOUR", wkbLineString,
    1893                 :                         TranslateLandrangerLine, NRT_LINEREC, NULL,
    1894                 :                         "LINE_ID", OFTInteger, 6, 0,
    1895                 :                         "FEAT_CODE", OFTString, 4, 0,
    1896                 :                         "HEIGHT", OFTReal, 7, 2,
    1897               0 :                         NULL );
    1898                 :     }
    1899               2 :     else if( GetProductId() == NPC_LANDFORM_PROFILE_CONT )
    1900                 :     {
    1901                 :         EstablishLayer( "PROFILE_POINT", wkbPoint25D,
    1902                 :                         TranslateProfilePoint, NRT_POINTREC, NULL,
    1903                 :                         "POINT_ID", OFTInteger, 6, 0,
    1904                 :                         "FEAT_CODE", OFTString, 4, 0,
    1905                 :                         "HEIGHT", OFTReal, 7, 2,
    1906               0 :                         NULL );
    1907                 :                         
    1908                 :         EstablishLayer( "PROFILE_LINE", wkbLineString25D,
    1909                 :                         TranslateProfileLine, NRT_LINEREC, NULL,
    1910                 :                         "LINE_ID", OFTInteger, 6, 0,
    1911                 :                         "FEAT_CODE", OFTString, 4, 0,
    1912                 :                         "HEIGHT", OFTReal, 7, 2,
    1913               0 :                         NULL );
    1914                 :     }
    1915               2 :     else if( GetProductId() == NPC_STRATEGI )
    1916                 :     {
    1917                 :         EstablishLayer( "STRATEGI_POINT", wkbPoint,
    1918                 :                         TranslateStrategiPoint, NRT_POINTREC, NULL,
    1919                 :                         "POINT_ID", OFTInteger, 6, 0,
    1920                 :                         "FEAT_CODE", OFTString, 4, 0,
    1921                 :                         "PROPER_NAME", OFTString, 0, 0, 
    1922                 :                         "FEATURE_NUMBER", OFTString, 0, 0, 
    1923                 :                         "RB", OFTString, 1, 0, 
    1924                 :                         "RU", OFTString, 1, 0, 
    1925                 :                         "AN", OFTString, 0, 0, 
    1926                 :                         "AO", OFTString, 0, 0, 
    1927                 :                         "COUNTY_NAME", OFTString, 0, 0, 
    1928                 :                         "UNITARY_NAME", OFTString, 0, 0, 
    1929                 :                         "GEOM_ID", OFTInteger, 6, 0,
    1930                 :                         "DATE", OFTInteger, 8, 0,
    1931                 :                         "DISTRICT_NAME", OFTString, 0, 0,
    1932                 :                         "FEATURE_NAME", OFTString, 0, 0,
    1933                 :                         "GIS", OFTString, 0, 0,
    1934                 :                         "HEIGHT_IMPERIAL", OFTInteger, 4, 0,
    1935                 :                         "HEIGHT_METRIC", OFTInteger, 4, 0,
    1936                 :                         "LOCATION", OFTInteger, 1, 0,
    1937                 :                         "ORIENTATION", OFTReal, 4, 1,
    1938                 :                         "OWNER", OFTString, 0, 0,
    1939                 :                         "RESTRICTION_NORTH", OFTString, 0, 0,
    1940                 :                         "RESTRICTION_SOUTH", OFTString, 0, 0,
    1941                 :                         "RESTRICTION_EAST", OFTString, 0, 0,
    1942                 :                         "RESTRICTION_WEST", OFTString, 0, 0,
    1943                 :                         "RESTRICTION_CLOCKWISE", OFTString, 0, 0,
    1944                 :                         "RESTRICTION_ANTICLOCKWISE", OFTString, 0, 0,
    1945                 :                         "USAGE", OFTInteger, 1, 0,
    1946               1 :                         NULL );
    1947                 :         
    1948                 :         EstablishLayer( "STRATEGI_LINE", wkbLineString,
    1949                 :                         TranslateStrategiLine, NRT_LINEREC, NULL,
    1950                 :                         "LINE_ID", OFTInteger, 6, 0,
    1951                 :                         "FEAT_CODE", OFTString, 4, 0,
    1952                 :                         "PROPER_NAME", OFTString, 0, 0,
    1953                 :                         "GEOM_ID", OFTInteger, 6, 0,
    1954                 :                         "DATE", OFTInteger, 8, 0,
    1955                 :                         "FERRY_ACCESS", OFTString, 0, 0,
    1956                 :                         "FERRY_FROM", OFTString, 0, 0,
    1957                 :                         "FERRY_TIME", OFTString, 0, 0,
    1958                 :                         "FEATURE_NAME", OFTString, 0, 0,
    1959                 :                         "FERRY_TYPE", OFTString, 0, 0,
    1960                 :                         "FERRY_RESTRICTIONS", OFTString, 0, 0,
    1961                 :                         "FERRY_TO", OFTString, 0, 0,
    1962                 :                         "GIS", OFTString, 0, 0,
    1963                 :                         "FEATURE_NUMBER", OFTString, 0, 0, 
    1964               1 :                         NULL );
    1965                 : 
    1966                 :         EstablishLayer( "STRATEGI_TEXT", wkbPoint,
    1967                 :                         TranslateStrategiText, NRT_TEXTREC, NULL,
    1968                 :                         "TEXT_ID", OFTInteger, 6, 0,
    1969                 :                         "FEAT_CODE", OFTString, 4, 0,
    1970                 :                         "FONT", OFTInteger, 4, 0,
    1971                 :                         "TEXT_HT", OFTReal, 5, 1,
    1972                 :                         "DIG_POSTN", OFTInteger, 1, 0, 
    1973                 :                         "ORIENT", OFTReal, 5, 1,
    1974                 :                         "TEXT", OFTString, 0, 0, 
    1975                 :                         "TEXT_HT_GROUND", OFTReal, 10, 3,
    1976                 :                         "DATE", OFTInteger, 8, 0,
    1977               1 :                         NULL );
    1978                 : 
    1979                 :         EstablishLayer( "STRATEGI_NODE", wkbNone,
    1980                 :                         TranslateStrategiNode, NRT_NODEREC, NULL,
    1981                 :                         "NODE_ID", OFTInteger, 6, 0,
    1982                 :                         "GEOM_ID_OF_POINT", OFTInteger, 6, 0,
    1983                 :                         "NUM_LINKS", OFTInteger, 4, 0,
    1984                 :                         "DIR", OFTIntegerList, 1, 0,
    1985                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    1986                 :                         "LEVEL", OFTIntegerList, 1, 0,
    1987                 :                         "ORIENT", OFTRealList, 5, 1,
    1988               1 :                         NULL );
    1989                 :     }
    1990               1 :     else if( GetProductId() == NPC_MERIDIAN )
    1991                 :     {
    1992                 :         EstablishLayer( "MERIDIAN_POINT", wkbPoint,
    1993                 :                         TranslateMeridianPoint, NRT_POINTREC, NULL,
    1994                 :                         "POINT_ID", OFTInteger, 6, 0,
    1995                 :                         "GEOM_ID", OFTInteger, 6, 0,
    1996                 :                         "FEAT_CODE", OFTString, 4, 0,
    1997                 :                         "PROPER_NAME", OFTString, 0, 0, 
    1998                 :                         "OSMDR", OFTString, 13, 0,
    1999                 :                         "JUNCTION_NAME", OFTString, 0, 0,
    2000                 :                         "ROUNDABOUT", OFTString, 1, 0,
    2001                 :                         "STATION_ID", OFTString, 13, 0,
    2002                 :                         "GLOBAL_ID", OFTInteger, 6, 0, 
    2003                 :                         "ADMIN_NAME", OFTString, 0, 0, 
    2004                 :                         "DA_DLUA_ID", OFTString, 13, 0, 
    2005               0 :                         NULL );
    2006                 :         
    2007                 :         EstablishLayer( "MERIDIAN_LINE", wkbLineString,
    2008                 :                         TranslateMeridianLine, NRT_LINEREC, NULL,
    2009                 :                         "LINE_ID", OFTInteger, 6, 0,
    2010                 :                         "FEAT_CODE", OFTString, 4, 0,
    2011                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2012                 :                         "OSMDR", OFTString, 13, 0, 
    2013                 :                         "ROAD_NUM", OFTString, 0, 0, 
    2014                 :                         "TRUNK_ROAD", OFTString, 1, 0, 
    2015                 :                         "RAIL_ID", OFTString, 13, 0, 
    2016                 :                         "LEFT_COUNTY", OFTInteger, 6, 0, 
    2017                 :                         "RIGHT_COUNTY", OFTInteger, 6, 0, 
    2018                 :                         "LEFT_DISTRICT", OFTInteger, 6, 0, 
    2019                 :                         "RIGHT_DISTRICT", OFTInteger, 6, 0, 
    2020               0 :                         NULL );
    2021                 : 
    2022                 :         EstablishLayer( "MERIDIAN_TEXT", wkbPoint,
    2023                 :                         TranslateStrategiText, NRT_TEXTREC, NULL,
    2024                 :                         "TEXT_ID", OFTInteger, 6, 0,
    2025                 :                         "FEAT_CODE", OFTString, 4, 0,
    2026                 :                         "FONT", OFTInteger, 4, 0,
    2027                 :                         "TEXT_HT", OFTReal, 5, 1,
    2028                 :                         "DIG_POSTN", OFTInteger, 1, 0, 
    2029                 :                         "ORIENT", OFTReal, 5, 1,
    2030                 :                         "TEXT", OFTString, 0, 0, 
    2031                 :                         "TEXT_HT_GROUND", OFTReal, 10, 3,
    2032               0 :                         NULL );
    2033                 : 
    2034                 :         EstablishLayer( "MERIDIAN_NODE", wkbNone,
    2035                 :                         TranslateStrategiNode, NRT_NODEREC, NULL,
    2036                 :                         "NODE_ID", OFTInteger, 6, 0,
    2037                 :                         "GEOM_ID_OF_POINT", OFTInteger, 6, 0,
    2038                 :                         "NUM_LINKS", OFTInteger, 4, 0,
    2039                 :                         "DIR", OFTIntegerList, 1, 0,
    2040                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    2041                 :                         "LEVEL", OFTIntegerList, 1, 0,
    2042                 :                         "ORIENT", OFTRealList, 5, 1,
    2043               0 :                         NULL );
    2044                 :     }
    2045               1 :     else if( GetProductId() == NPC_MERIDIAN2 )
    2046                 :     {
    2047                 :         EstablishLayer( "MERIDIAN2_POINT", wkbPoint,
    2048                 :                         TranslateMeridian2Point, NRT_POINTREC, NULL,
    2049                 :                         "POINT_ID", OFTInteger, 6, 0,
    2050                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2051                 :                         "FEAT_CODE", OFTString, 4, 0,
    2052                 :                         "PROPER_NAME", OFTString, 0, 0, 
    2053                 :                         "OSODR", OFTString, 13, 0,
    2054                 :                         "PARENT_OSODR", OFTString, 13, 0,
    2055                 :                         "JUNCTION_NAME", OFTString, 0, 0,
    2056                 :                         "ROUNDABOUT", OFTString, 1, 0,
    2057                 :                         "SETTLEMENT_NAME", OFTString, 0, 0,
    2058                 :                         "STATION_ID", OFTString, 13, 0,
    2059                 :                         "GLOBAL_ID", OFTInteger, 6, 0, 
    2060                 :                         "ADMIN_NAME", OFTString, 0, 0, 
    2061                 :                         "DA_DLUA_ID", OFTString, 13, 0, 
    2062                 :                         "WATER_AREA", OFTString, 13, 0, 
    2063                 :                         "HEIGHT", OFTInteger, 8, 0,
    2064                 :                         "FOREST_ID", OFTString, 13, 0,
    2065               1 :                         NULL );
    2066                 :         
    2067                 :         EstablishLayer( "MERIDIAN2_LINE", wkbLineString,
    2068                 :                         TranslateMeridian2Line, NRT_LINEREC, NULL,
    2069                 :                         "LINE_ID", OFTInteger, 6, 0,
    2070                 :                         "FEAT_CODE", OFTString, 4, 0,
    2071                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2072                 :                         "OSODR", OFTString, 13, 0, 
    2073                 :                         "PARENT_OSODR", OFTString, 13, 0,
    2074                 :                         "ROAD_NUM", OFTString, 0, 0, 
    2075                 :                         "TRUNK_ROAD", OFTString, 1, 0, 
    2076                 :                         "PROPER_NAME", OFTString, 0, 0, 
    2077                 :                         "RAIL_ID", OFTString, 13, 0, 
    2078                 :                         "LEFT_COUNTY", OFTInteger, 6, 0, 
    2079                 :                         "RIGHT_COUNTY", OFTInteger, 6, 0, 
    2080                 :                         "LEFT_DISTRICT", OFTInteger, 6, 0, 
    2081                 :                         "RIGHT_DISTRICT", OFTInteger, 6, 0, 
    2082                 :                         "WATER_LINK_ID", OFTString, 13, 0, 
    2083               1 :                         NULL );
    2084                 : 
    2085                 :         EstablishLayer( "MERIDIAN2_TEXT", wkbPoint,
    2086                 :                         TranslateStrategiText, NRT_TEXTREC, NULL,
    2087                 :                         "TEXT_ID", OFTInteger, 6, 0,
    2088                 :                         "FEAT_CODE", OFTString, 4, 0,
    2089                 :                         "FONT", OFTInteger, 4, 0,
    2090                 :                         "TEXT_HT", OFTReal, 5, 1,
    2091                 :                         "DIG_POSTN", OFTInteger, 1, 0, 
    2092                 :                         "ORIENT", OFTReal, 5, 1,
    2093                 :                         "TEXT", OFTString, 0, 0, 
    2094                 :                         "TEXT_HT_GROUND", OFTReal, 10, 3,
    2095               1 :                         NULL );
    2096                 : 
    2097                 :         EstablishLayer( "MERIDIAN2_NODE", wkbNone,
    2098                 :                         TranslateStrategiNode, NRT_NODEREC, NULL,
    2099                 :                         "NODE_ID", OFTInteger, 6, 0,
    2100                 :                         "GEOM_ID_OF_POINT", OFTInteger, 6, 0,
    2101                 :                         "NUM_LINKS", OFTInteger, 4, 0,
    2102                 :                         "DIR", OFTIntegerList, 1, 0,
    2103                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    2104                 :                         "LEVEL", OFTIntegerList, 1, 0,
    2105                 :                         "ORIENT", OFTRealList, 5, 1,
    2106               1 :                         NULL );
    2107                 :     }
    2108               0 :     else if( GetProductId() == NPC_BOUNDARYLINE )
    2109                 :     {
    2110                 :         EstablishLayer( "BOUNDARYLINE_LINK", wkbLineString,
    2111                 :                         TranslateBoundarylineLink, NRT_GEOMETRY, NULL,
    2112                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2113                 :                         "FEAT_CODE", OFTString, 4, 0,
    2114                 :                         "GLOBAL_LINK_ID", OFTInteger, 10, 0,
    2115                 :                         "HWM_FLAG", OFTInteger, 1, 0, 
    2116               0 :                         NULL );
    2117                 : 
    2118                 :         EstablishLayer( "BOUNDARYLINE_POLY", 
    2119                 :                         bCacheLines ? wkbPolygon : wkbPoint,
    2120                 :                         TranslateBoundarylinePoly, NRT_POLYGON, NULL,
    2121                 :                         "POLY_ID", OFTInteger, 6, 0,
    2122                 :                         "FEAT_CODE", OFTString, 4, 0,
    2123                 :                         "GLOBAL_SEED_ID", OFTInteger, 6, 0,
    2124                 :                         "HECTARES", OFTReal, 9, 3,
    2125                 :                         "NUM_PARTS", OFTInteger, 4, 0, 
    2126                 :                         "DIR", OFTIntegerList, 1, 0,
    2127                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    2128                 :                         "RingStart", OFTIntegerList, 6, 0,
    2129               0 :                         NULL );
    2130                 : 
    2131                 :         EstablishLayer( "BOUNDARYLINE_COLLECTIONS", wkbNone,
    2132                 :                         TranslateBoundarylineCollection, NRT_COLLECT, NULL,
    2133                 :                         "COLL_ID", OFTInteger, 6, 0,
    2134                 :                         "NUM_PARTS", OFTInteger, 4, 0,
    2135                 :                         "POLY_ID", OFTIntegerList, 6, 0,
    2136                 :                         "ADMIN_AREA_ID", OFTInteger, 6, 0, 
    2137                 :                         "OPCS_CODE", OFTString, 6, 0,
    2138                 :                         "ADMIN_NAME", OFTString, 0, 0,
    2139               0 :                         NULL );
    2140                 :     }
    2141               0 :     else if( GetProductId() == NPC_BL2000 )
    2142                 :     {
    2143                 :         EstablishLayer( "BL2000_LINK", wkbLineString,
    2144                 :                         TranslateBL2000Link, NRT_LINEREC, NULL,
    2145                 :                         "LINE_ID", OFTInteger, 6, 0,
    2146                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2147                 :                         "FEAT_CODE", OFTString, 4, 0,
    2148                 :                         "GLOBAL_LINK_ID", OFTInteger, 10, 0,
    2149               0 :                         NULL );
    2150                 :         EstablishLayer( "BL2000_POLY", 
    2151                 :                         bCacheLines ? wkbPolygon : wkbNone,
    2152                 :                         TranslateBL2000Poly, NRT_POLYGON, NULL,
    2153                 :                         "POLY_ID", OFTInteger, 6, 0,
    2154                 :                         "GLOBAL_SEED_ID", OFTInteger, 6, 0,
    2155                 :                         "HECTARES", OFTReal, 12, 3,
    2156                 :                         "NUM_PARTS", OFTInteger, 4, 0, 
    2157                 :                         "DIR", OFTIntegerList, 1, 0,
    2158                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    2159                 :                         "RingStart", OFTIntegerList, 6, 0,
    2160               0 :                         NULL );
    2161               0 :         if( poDS->GetOption("CODELIST") != NULL 
    2162                 :             && EQUAL(poDS->GetOption("CODELIST"),"ON") )
    2163                 :             EstablishLayer( "BL2000_COLLECTIONS", wkbNone,
    2164                 :                             TranslateBL2000Collection, NRT_COLLECT, NULL,
    2165                 :                             "COLL_ID", OFTInteger, 6, 0,
    2166                 :                             "NUM_PARTS", OFTInteger, 4, 0,
    2167                 :                             "POLY_ID", OFTIntegerList, 6, 0,
    2168                 :                             "ADMIN_AREA_ID", OFTInteger, 6, 0, 
    2169                 :                             "CENSUS_CODE", OFTString, 7, 0,
    2170                 :                             "ADMIN_NAME", OFTString, 0, 0,
    2171                 :                             "AREA_TYPE", OFTString, 2, 0,
    2172                 :                             "AREA_CODE", OFTString, 3, 0,
    2173                 :                             "NON_TYPE_CODE", OFTString, 3, 0,
    2174                 :                             "NON_INLAND_AREA", OFTReal, 12, 3,
    2175                 :                             "COLL_ID_REFS", OFTIntegerList, 6, 0,
    2176                 :                             "AREA_TYPE_DESC", OFTString, 0, 0,
    2177                 :                             "AREA_CODE_DESC", OFTString, 0, 0,
    2178                 :                             "NON_TYPE_CODE_DESC", OFTString, 0, 0,
    2179               0 :                             NULL );
    2180                 :         else
    2181                 :             EstablishLayer( "BL2000_COLLECTIONS", wkbNone,
    2182                 :                             TranslateBL2000Collection, NRT_COLLECT, NULL,
    2183                 :                             "COLL_ID", OFTInteger, 6, 0,
    2184                 :                             "NUM_PARTS", OFTInteger, 4, 0,
    2185                 :                             "POLY_ID", OFTIntegerList, 6, 0,
    2186                 :                             "ADMIN_AREA_ID", OFTInteger, 6, 0, 
    2187                 :                             "CENSUS_CODE", OFTString, 7, 0,
    2188                 :                             "ADMIN_NAME", OFTString, 0, 0,
    2189                 :                             "AREA_TYPE", OFTString, 2, 0,
    2190                 :                             "AREA_CODE", OFTString, 3, 0,
    2191                 :                             "NON_TYPE_CODE", OFTString, 3, 0,
    2192                 :                             "NON_INLAND_AREA", OFTReal, 12, 3,
    2193                 :                             "COLL_ID_REFS", OFTIntegerList, 6, 0,
    2194               0 :                             NULL );
    2195                 :     }
    2196               0 :     else if( GetProductId() == NPC_BASEDATA )
    2197                 :     {
    2198                 :         EstablishLayer( "BASEDATA_POINT", wkbPoint,
    2199                 :                         TranslateBasedataPoint, NRT_POINTREC, NULL,
    2200                 :                         "POINT_ID", OFTInteger, 6, 0,
    2201                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2202                 :                         "FEAT_CODE", OFTString, 4, 0,
    2203                 :                         "PROPER_NAME", OFTString, 0, 0, 
    2204                 :                         "FEATURE_NUMBER", OFTString, 0, 0, 
    2205                 :                         "COUNTY_NAME", OFTString, 0, 0, 
    2206                 :                         "UNITARY_NAME", OFTString, 0, 0, 
    2207                 :                         "ORIENT", OFTRealList, 5, 1,
    2208               0 :                         NULL );
    2209                 :         
    2210                 :         EstablishLayer( "BASEDATA_LINE", wkbLineString,
    2211                 :                         TranslateBasedataLine, NRT_LINEREC, NULL,
    2212                 :                         "LINE_ID", OFTInteger, 6, 0,
    2213                 :                         "FEAT_CODE", OFTString, 4, 0,
    2214                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2215                 :                         "PROPER_NAME", OFTString, 0, 0, 
    2216                 :                         "FEATURE_NUMBER", OFTString, 0, 0, 
    2217                 :                         "RB", OFTString, 1, 0, 
    2218               0 :                         NULL );
    2219                 : 
    2220                 :         EstablishLayer( "BASEDATA_TEXT", wkbPoint,
    2221                 :                         TranslateStrategiText, NRT_TEXTREC, NULL,
    2222                 :                         "TEXT_ID", OFTInteger, 6, 0,
    2223                 :                         "FEAT_CODE", OFTString, 4, 0,
    2224                 :                         "FONT", OFTInteger, 4, 0,
    2225                 :                         "TEXT_HT", OFTReal, 5, 1,
    2226                 :                         "DIG_POSTN", OFTInteger, 1, 0, 
    2227                 :                         "ORIENT", OFTReal, 5, 1,
    2228                 :                         "TEXT", OFTString, 0, 0, 
    2229                 :                         "TEXT_HT_GROUND", OFTReal, 10, 3,
    2230               0 :                         NULL );
    2231                 : 
    2232                 :         EstablishLayer( "BASEDATA_NODE", wkbNone,
    2233                 :                         TranslateStrategiNode, NRT_NODEREC, NULL,
    2234                 :                         "NODE_ID", OFTInteger, 6, 0,
    2235                 :                         "GEOM_ID_OF_POINT", OFTInteger, 6, 0,
    2236                 :                         "NUM_LINKS", OFTInteger, 4, 0,
    2237                 :                         "DIR", OFTIntegerList, 1, 0,
    2238                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    2239                 :                         "LEVEL", OFTIntegerList, 1, 0,
    2240                 :                         "ORIENT", OFTRealList, 5, 1,
    2241               0 :                         NULL );
    2242                 :     }
    2243               0 :     else if( GetProductId() == NPC_OSCAR_ASSET
    2244                 :              || GetProductId() == NPC_OSCAR_TRAFFIC )
    2245                 :     {
    2246                 :         EstablishLayer( "OSCAR_POINT", wkbPoint,
    2247                 :                         TranslateOscarPoint, NRT_POINTREC, NULL,
    2248                 :                         "POINT_ID", OFTInteger, 6, 0,
    2249                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2250                 :                         "FEAT_CODE", OFTString, 4, 0,
    2251                 :                         "OSODR", OFTString, 13, 0,
    2252                 :                         "JUNCTION_NAME", OFTString, 0, 0,
    2253                 :                         "SETTLE_NAME", OFTString, 0, 0,
    2254               0 :                         NULL );
    2255                 :         
    2256                 :         EstablishLayer( "OSCAR_LINE", wkbLineString,
    2257                 :                         TranslateOscarLine, NRT_LINEREC, NULL,
    2258                 :                         "LINE_ID", OFTInteger, 6, 0,
    2259                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2260                 :                         "FEAT_CODE", OFTString, 4, 0,
    2261                 :                         "OSODR", OFTString, 13, 0,
    2262                 :                         "PROPER_NAME", OFTString, 0, 0,
    2263                 :                         "LINE_LENGTH", OFTInteger, 5, 0,
    2264                 :                         "SOURCE", OFTString, 1, 0,
    2265                 :                         "FORM_OF_WAY", OFTString, 1, 0,
    2266                 :                         "ROAD_NUM", OFTString, 0, 0,
    2267                 :                         "TRUNK_ROAD", OFTString, 1, 0, 
    2268               0 :                         NULL );
    2269                 : 
    2270                 :         EstablishLayer( "OSCAR_NODE", wkbNone,
    2271                 :                         TranslateStrategiNode, NRT_NODEREC, NULL,
    2272                 :                         "NODE_ID", OFTInteger, 6, 0,
    2273                 :                         "GEOM_ID_OF_POINT", OFTInteger, 6, 0,
    2274                 :                         "NUM_LINKS", OFTInteger, 4, 0,
    2275                 :                         "DIR", OFTIntegerList, 1, 0,
    2276                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    2277                 :                         "LEVEL", OFTIntegerList, 1, 0,
    2278               0 :                         NULL );
    2279                 : 
    2280                 :         EstablishLayer( "OSCAR_COMMENT", wkbNone,
    2281                 :                         TranslateOscarComment, NRT_COMMENT, NULL,
    2282                 :                         "RECORD_TYPE", OFTInteger, 2, 0,
    2283                 :                         "RECORD_ID", OFTString, 13, 0,
    2284                 :                         "CHANGE_TYPE", OFTString, 1, 0,
    2285               0 :                         NULL );
    2286                 :     }
    2287               0 :     else if( GetProductId() == NPC_OSCAR_ROUTE )
    2288                 :     {
    2289                 :         EstablishLayer( "OSCAR_ROUTE_POINT", wkbPoint,
    2290                 :                         TranslateOscarRoutePoint, NRT_POINTREC, NULL,
    2291                 :                         "POINT_ID", OFTInteger, 6, 0,
    2292                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2293                 :                         "FEAT_CODE", OFTString, 4, 0,
    2294                 :                         "OSODR", OFTString, 13, 0,
    2295                 :                         "JUNCTION_NAME", OFTString, 0, 0,
    2296                 :                         "SETTLE_NAME", OFTString, 0, 0,
    2297                 :                         "NUM_PARENTS", OFTInteger, 2, 0,
    2298                 :                         "PARENT_OSODR", OFTStringList, 13, 0,
    2299                 :                         "ROUNDABOUT", OFTString, 1, 0,
    2300               0 :                         NULL );
    2301                 :         
    2302                 :         EstablishLayer( "OSCAR_ROUTE_LINE", wkbLineString,
    2303                 :                         TranslateOscarRouteLine, NRT_LINEREC, NULL,
    2304                 :                         "LINE_ID", OFTInteger, 6, 0,
    2305                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2306                 :                         "FEAT_CODE", OFTString, 4, 0,
    2307                 :                         "OSODR", OFTString, 13, 0,
    2308                 :                         "PROPER_NAME", OFTString, 0, 0,
    2309                 :                         "LINE_LENGTH", OFTInteger, 5, 0,
    2310                 :                         "ROAD_NUM", OFTString, 0, 0,
    2311                 :                         "TRUNK_ROAD", OFTString, 1, 0, 
    2312                 :                         "NUM_PARENTS", OFTInteger, 2, 0,
    2313                 :                         "PARENT_OSODR", OFTStringList, 13, 0,
    2314               0 :                         NULL );
    2315                 : 
    2316                 :         EstablishLayer( "OSCAR_ROUTE_NODE", wkbNone,
    2317                 :                         TranslateStrategiNode, NRT_NODEREC, NULL,
    2318                 :                         "NODE_ID", OFTInteger, 6, 0,
    2319                 :                         "GEOM_ID_OF_POINT", OFTInteger, 6, 0,
    2320                 :                         "NUM_LINKS", OFTInteger, 4, 0,
    2321                 :                         "DIR", OFTIntegerList, 1, 0,
    2322                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    2323                 :                         "LEVEL", OFTIntegerList, 1, 0,
    2324               0 :                         NULL );
    2325                 : 
    2326                 :         EstablishLayer( "OSCAR_COMMENT", wkbNone,
    2327                 :                         TranslateOscarComment, NRT_COMMENT, NULL,
    2328                 :                         "RECORD_TYPE", OFTInteger, 2, 0,
    2329                 :                         "RECORD_ID", OFTString, 13, 0,
    2330                 :                         "CHANGE_TYPE", OFTString, 1, 0,
    2331               0 :                         NULL );
    2332                 :     }
    2333               0 :     else if( GetProductId() == NPC_OSCAR_NETWORK )
    2334                 :     {
    2335                 :         EstablishLayer( "OSCAR_NETWORK_POINT", wkbPoint,
    2336                 :                         TranslateOscarNetworkPoint, NRT_POINTREC, NULL,
    2337                 :                         "POINT_ID", OFTInteger, 6, 0,
    2338                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2339                 :                         "FEAT_CODE", OFTString, 4, 0,
    2340                 :                         "OSODR", OFTString, 13, 0,
    2341                 :                         "JUNCTION_NAME", OFTString, 0, 0,
    2342                 :                         "SETTLE_NAME", OFTString, 0, 0,
    2343                 :                         "ROUNDABOUT", OFTString, 1, 0,
    2344               0 :                         NULL );
    2345                 :         
    2346                 :         EstablishLayer( "OSCAR_NETWORK_LINE", wkbLineString,
    2347                 :                         TranslateOscarNetworkLine, NRT_LINEREC, NULL,
    2348                 :                         "LINE_ID", OFTInteger, 6, 0,
    2349                 :                         "GEOM_ID", OFTInteger, 6, 0,
    2350                 :                         "FEAT_CODE", OFTString, 4, 0,
    2351                 :                         "OSODR", OFTString, 13, 0,
    2352                 :                         "PROPER_NAME", OFTString, 0, 0,
    2353                 :                         "LINE_LENGTH", OFTInteger, 5, 0,
    2354                 :                         "ROAD_NUM", OFTString, 0, 0,
    2355               0 :                         NULL );
    2356                 : 
    2357                 :         EstablishLayer( "OSCAR_NETWORK_NODE", wkbNone,
    2358                 :                         TranslateStrategiNode, NRT_NODEREC, NULL,
    2359                 :                         "NODE_ID", OFTInteger, 6, 0,
    2360                 :                         "GEOM_ID_OF_POINT", OFTInteger, 6, 0,
    2361                 :                         "NUM_LINKS", OFTInteger, 4, 0,
    2362                 :                         "DIR", OFTIntegerList, 1, 0,
    2363                 :                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
    2364                 :                         "LEVEL", OFTIntegerList, 1, 0,
    2365               0 :                         NULL );
    2366                 : 
    2367                 :         EstablishLayer( "OSCAR_COMMENT", wkbNone,
    2368                 :                         TranslateOscarComment, NRT_COMMENT, NULL,
    2369                 :                         "RECORD_TYPE", OFTInteger, 2, 0,
    2370                 :                         "RECORD_ID", OFTString, 13, 0,
    2371                 :                         "CHANGE_TYPE", OFTString, 1, 0,
    2372               0 :                         NULL );
    2373                 :     }
    2374               0 :     else if( GetProductId() == NPC_ADDRESS_POINT )
    2375                 :     {
    2376                 :         EstablishLayer( "ADDRESS_POINT", wkbPoint,
    2377                 :                         TranslateAddressPoint, NRT_POINTREC, NULL,
    2378                 :                         "POINT_ID", OFTInteger, 6, 0,
    2379                 :                         "OSAPR", OFTString, 18, 0,
    2380                 :                         "ORGANISATION_NAME", OFTString, 0, 0,
    2381                 :                         "DEPARTMENT_NAME", OFTString, 0, 0,
    2382                 :                         "PO_BOX", OFTString, 6, 0,
    2383                 :                         "SUBBUILDING_NAME", OFTString, 0, 0,
    2384                 :                         "BUILDING_NAME", OFTString, 0, 0,
    2385                 :                         "BUILDING_NUMBER", OFTInteger, 4, 0,
    2386                 :                         "DEPENDENT_THOROUGHFARE_NAME", OFTString, 0, 0,
    2387                 :                         "THOROUGHFARE_NAME", OFTString, 0, 0,
    2388                 :                         "DOUBLE_DEPENDENT_LOCALITY_NAME", OFTString, 0, 0,
    2389                 :                         "DEPENDENT_LOCALITY_NAME", OFTString, 0, 0,
    2390                 :                         "POST_TOWN_NAME", OFTString, 0, 0,
    2391                 :                         "COUNTY_NAME", OFTString, 0, 0,
    2392                 :                         "POSTCODE", OFTString, 7, 0,
    2393                 :                         "STATUS_FLAG", OFTString, 4, 0,
    2394                 :                         "RM_VERSION_DATE", OFTString, 8, 0,
    2395                 :                         "CHG_TYPE", OFTString, 1, 0,
    2396                 :                         "CHG_DATE", OFTString, 6, 0, 
    2397               0 :                         NULL );
    2398                 :     }
    2399               0 :     else if( GetProductId() == NPC_CODE_POINT )
    2400                 :     {
    2401                 :         EstablishLayer( "CODE_POINT", wkbPoint,
    2402                 :                         TranslateCodePoint, NRT_POINTREC, NULL,
    2403                 :                         "POINT_ID", OFTInteger, 6, 0,
    2404                 :                         "UNIT_POSTCODE", OFTString, 7, 0,
    2405                 :                         "POSITIONAL_QUALITY", OFTInteger, 1, 0,
    2406                 :                         "PO_BOX_INDICATOR", OFTString, 1, 0,
    2407                 :                         "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2408                 :                         "DELIVERY_POINTS", OFTInteger, 3, 0, 
    2409                 :                         "DOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2410                 :                         "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2411                 :                         "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2412                 :                         "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0, 
    2413                 :                         "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2414                 :                         "RM_VERSION_DATA", OFTString, 8, 0,
    2415               0 :                         NULL );
    2416                 :     }
    2417               0 :     else if( GetProductId() == NPC_CODE_POINT_PLUS )
    2418                 :     {
    2419                 :         EstablishLayer( "CODE_POINT_PLUS", wkbPoint,
    2420                 :                         TranslateCodePoint, NRT_POINTREC, NULL,
    2421                 :                         "POINT_ID", OFTInteger, 6, 0,
    2422                 :                         "UNIT_POSTCODE", OFTString, 7, 0,
    2423                 :                         "POSITIONAL_QUALITY", OFTInteger, 1, 0,
    2424                 :                         "PO_BOX_INDICATOR", OFTString, 1, 0,
    2425                 :                         "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2426                 :                         "DELIVERY_POINTS", OFTInteger, 3, 0, 
    2427                 :                         "DOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2428                 :                         "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2429                 :                         "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2430                 :                         "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0, 
    2431                 :                         "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0, 
    2432                 :                         "RM_VERSION_DATA", OFTString, 8, 0,
    2433                 :                         "NHS_REGIONAL_HEALTH_AUTHORITY", OFTString, 3, 0,
    2434                 :                         "NHS_HEALTH_AUTHORITY", OFTString, 3, 0,
    2435                 :                         "ADMIN_COUNTY", OFTString, 2, 0,
    2436                 :                         "ADMIN_DISTRICT", OFTString, 2, 0,
    2437                 :                         "ADMIN_WARD", OFTString, 2, 0,
    2438               0 :                         NULL );
    2439                 :     }
    2440                 :     else // generic case
    2441                 :     {
    2442                 :         CPLAssert( GetProductId() == NPC_UNKNOWN );
    2443                 :         
    2444               0 :         poDS->WorkupGeneric( this );
    2445                 :     }
    2446                 : }

Generated by: LCOV version 1.7