LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/tiger - tigercompletechain.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 211 152 72.0 %
Date: 2011-12-18 Functions: 11 8 72.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: tigercompletechain.cpp 22961 2011-08-20 17:09:59Z rouault $
       3                 :  *
       4                 :  * Project:  TIGER/Line Translator
       5                 :  * Purpose:  Implements TigerCompleteChain, providing access to RT1 and
       6                 :  *           related files.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 1999, Frank Warmerdam
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "ogr_tiger.h"
      32                 : #include "cpl_conv.h"
      33                 : 
      34                 : CPL_CVSID("$Id: tigercompletechain.cpp 22961 2011-08-20 17:09:59Z rouault $");
      35                 : 
      36                 : static const TigerFieldInfo rt1_2002_fields[] = {
      37                 :   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
      38                 :   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
      39                 :   { "TLID",       'R', 'N', OFTInteger,    6,  15,  10,       1,   1,     1 },
      40                 :   { "SIDE1",      'R', 'N', OFTInteger,   16,  16,   1,       1,   1,     1 },
      41                 :   { "SOURCE",     'L', 'A', OFTString,    17,  17,   1,       1,   1,     1 },
      42                 :   { "FEDIRP",     'L', 'A', OFTString,    18,  19,   2,       1,   1,     1 },
      43                 :   { "FENAME",     'L', 'A', OFTString,    20,  49,  30,       1,   1,     1 },
      44                 :   { "FETYPE",     'L', 'A', OFTString,    50,  53,   4,       1,   1,     1 },
      45                 :   { "FEDIRS",     'L', 'A', OFTString,    54,  55,   2,       1,   1,     1 },
      46                 :   { "CFCC",       'L', 'A', OFTString,    56,  58,   3,       1,   1,     1 },
      47                 :   { "FRADDL",     'R', 'A', OFTString,    59,  69,  11,       1,   1,     1 },
      48                 :   { "TOADDL",     'R', 'A', OFTString,    70,  80,  11,       1,   1,     1 },
      49                 :   { "FRADDR",     'R', 'A', OFTString,    81,  91,  11,       1,   1,     1 },
      50                 :   { "TOADDR",     'R', 'A', OFTString,    92, 102,  11,       1,   1,     1 },
      51                 :   { "FRIADDL",    'L', 'A', OFTString,   103, 103,   1,       1,   1,     1 },
      52                 :   { "TOIADDL",    'L', 'A', OFTString,   104, 104,   1,       1,   1,     1 },
      53                 :   { "FRIADDR",    'L', 'A', OFTString,   105, 105,   1,       1,   1,     1 },
      54                 :   { "TOIADDR",    'L', 'A', OFTString,   106, 106,   1,       1,   1,     1 },
      55                 :   { "ZIPL",       'L', 'N', OFTInteger,  107, 111,   5,       1,   1,     1 },
      56                 :   { "ZIPR",       'L', 'N', OFTInteger,  112, 116,   5,       1,   1,     1 },
      57                 :   { "AIANHHFPL",  'L', 'N', OFTInteger,  117, 121,   5,       1,   1,     1 },
      58                 :   { "AIANHHFPR",  'L', 'N', OFTInteger,  122, 126,   5,       1,   1,     1 },
      59                 :   { "AIHHTLIL",   'L', 'A', OFTString,   127, 127,   1,       1,   1,     1 },
      60                 :   { "AIHHTLIR",   'L', 'A', OFTString,   128, 128,   1,       1,   1,     1 },
      61                 :   { "CENSUS1",    'L', 'A', OFTString,   129, 129,   1,       1,   1,     1 },
      62                 :   { "CENSUS2",    'L', 'A', OFTString,   130, 130,   1,       1,   1,     1 },
      63                 :   { "STATEL",     'L', 'N', OFTInteger,  131, 132,   2,       1,   1,     1 },
      64                 :   { "STATER",     'L', 'N', OFTInteger,  133, 134,   2,       1,   1,     1 },
      65                 :   { "COUNTYL",    'L', 'N', OFTInteger,  135, 137,   3,       1,   1,     1 },
      66                 :   { "COUNTYR",    'L', 'N', OFTInteger,  138, 140,   3,       1,   1,     1 },
      67                 : 
      68                 :   { "COUSUBL",    'L', 'N', OFTInteger,  141, 145,   5,       1,   1,     1 },
      69                 :   { "COUSUBR",    'L', 'N', OFTInteger,  146, 150,   5,       1,   1,     1 },
      70                 :   { "SUBMCDL",    'L', 'N', OFTInteger,  151, 155,   5,       1,   1,     1 },
      71                 :   { "SUBMCDR",    'L', 'N', OFTInteger,  156, 160,   5,       1,   1,     1 },
      72                 :   { "PLACEL",     'L', 'N', OFTInteger,  161, 165,   5,       1,   1,     1 },
      73                 :   { "PLACER",     'L', 'N', OFTInteger,  166, 170,   5,       1,   1,     1 },
      74                 :   { "TRACTL",     'L', 'N', OFTInteger,  171, 176,   6,       1,   1,     1 },
      75                 :   { "TRACTR",     'L', 'N', OFTInteger,  177, 182,   6,       1,   1,     1 },
      76                 :   { "BLOCKL",     'L', 'N', OFTInteger,  183, 186,   4,       1,   1,     1 },
      77                 :   { "BLOCKR",     'L', 'N', OFTInteger,  187, 190,   4,       1,   1,     1 }
      78                 : };
      79                 : static const TigerRecordInfo rt1_2002_info =
      80                 :   {
      81                 :     rt1_2002_fields,
      82                 :     sizeof(rt1_2002_fields) / sizeof(TigerFieldInfo),
      83                 :     228
      84                 :   };
      85                 : 
      86                 : static const TigerFieldInfo rt1_fields[] = {
      87                 :   // fieldname    fmt  type OFTType      beg  end   len  bDefine bSet bWrite
      88                 :   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
      89                 :   { "TLID",       'R', 'N', OFTInteger,    6,  15,  10,       1,   1,     1 },
      90                 :   { "SIDE1",      'R', 'N', OFTInteger,   16,  16,   1,       1,   1,     1 },
      91                 :   { "SOURCE",     'L', 'A', OFTString,    17,  17,   1,       1,   1,     1 },
      92                 :   { "FEDIRP",     'L', 'A', OFTString,    18,  19,   2,       1,   1,     1 },
      93                 :   { "FENAME",     'L', 'A', OFTString,    20,  49,  30,       1,   1,     1 },
      94                 :   { "FETYPE",     'L', 'A', OFTString,    50,  53,   4,       1,   1,     1 },
      95                 :   { "FEDIRS",     'L', 'A', OFTString,    54,  55,   2,       1,   1,     1 },
      96                 :   { "CFCC",       'L', 'A', OFTString,    56,  58,   3,       1,   1,     1 },
      97                 :   { "FRADDL",     'R', 'A', OFTString,    59,  69,  11,       1,   1,     1 },
      98                 :   { "TOADDL",     'R', 'A', OFTString,    70,  80,  11,       1,   1,     1 },
      99                 :   { "FRADDR",     'R', 'A', OFTString,    81,  91,  11,       1,   1,     1 },
     100                 :   { "TOADDR",     'R', 'A', OFTString,    92, 102,  11,       1,   1,     1 },
     101                 :   { "FRIADDL",    'L', 'A', OFTInteger,  103, 103,   1,       1,   1,     1 },
     102                 :   { "TOIADDL",    'L', 'A', OFTInteger,  104, 104,   1,       1,   1,     1 },
     103                 :   { "FRIADDR",    'L', 'A', OFTInteger,  105, 105,   1,       1,   1,     1 },
     104                 :   { "TOIADDR",    'L', 'A', OFTInteger,  106, 106,   1,       1,   1,     1 },
     105                 :   { "ZIPL",       'L', 'N', OFTInteger,  107, 111,   5,       1,   1,     1 },
     106                 :   { "ZIPR",       'L', 'N', OFTInteger,  112, 116,   5,       1,   1,     1 },
     107                 :   { "FAIRL",      'L', 'N', OFTInteger,  117, 121,   5,       1,   1,     1 },
     108                 :   { "FAIRR",      'L', 'N', OFTInteger,  122, 126,   5,       1,   1,     1 },
     109                 :   { "TRUSTL",     'L', 'A', OFTString,   127, 127,   1,       1,   1,     1 },
     110                 :   { "TRUSTR",     'L', 'A', OFTString,   128, 128,   1,       1,   1,     1 },
     111                 :   { "CENSUS1",    'L', 'A', OFTString,   129, 129,   1,       1,   1,     1 },
     112                 :   { "CENSUS2",    'L', 'A', OFTString,   130, 130,   1,       1,   1,     1 },
     113                 :   { "STATEL",     'L', 'N', OFTInteger,  131, 132,   2,       1,   1,     1 },
     114                 :   { "STATER",     'L', 'N', OFTInteger,  133, 134,   2,       1,   1,     1 },
     115                 :   { "COUNTYL",    'L', 'N', OFTInteger,  135, 137,   3,       1,   1,     1 },
     116                 :   { "COUNTYR",    'L', 'N', OFTInteger,  138, 140,   3,       1,   1,     1 },
     117                 : 
     118                 :   { "FMCDL",      'L', 'N', OFTInteger,  141, 145,   5,       1,   1,     1 },
     119                 :   { "FMCDR",      'L', 'N', OFTInteger,  146, 150,   5,       1,   1,     1 },
     120                 :   { "FSMCDL",     'L', 'N', OFTInteger,  151, 155,   5,       1,   1,     1 },
     121                 :   { "FSMCDR",     'L', 'N', OFTInteger,  156, 160,   5,       1,   1,     1 },
     122                 :   { "FPLL",       'L', 'N', OFTInteger,  161, 165,   5,       1,   1,     1 },
     123                 :   { "FPLR",       'L', 'N', OFTInteger,  166, 170,   5,       1,   1,     1 },
     124                 :   { "CTBNAL",     'L', 'N', OFTInteger,  171, 176,   6,       1,   1,     1 },
     125                 :   { "CTBNAR",     'L', 'N', OFTInteger,  177, 182,   6,       1,   1,     1 },
     126                 :   { "BLKL",       'L', 'N', OFTString,   183, 186,   4,       1,   1,     1 },
     127                 :   { "BLKR",       'L', 'N', OFTString,   187, 190,   4,       1,   1,     1 }
     128                 : }; 
     129                 : static const TigerRecordInfo rt1_info =
     130                 :   {
     131                 :     rt1_fields,
     132                 :     sizeof(rt1_fields) / sizeof(TigerFieldInfo),
     133                 :     228
     134                 :   };
     135                 : 
     136                 : static const TigerRecordInfo rt2_info =
     137                 :   {
     138                 :     NULL,       // RT2 is handled specially in the code below; the only
     139                 :     0,          // thing from this structure that is used is:
     140                 :     208         // <--- nRecordLength
     141                 :   };
     142                 : 
     143                 : 
     144                 : static const TigerFieldInfo rt3_2000_Redistricting_fields[] = {
     145                 :   // fieldname    fmt  type OFTType       beg  end  len  bDefine bSet bWrite
     146                 :   { "TLID",       'R', 'N', OFTInteger,     6,  15,  10,       0,   0,     1 },
     147                 :   { "STATE90L",   'L', 'N', OFTInteger,    16,  17,   2,       1,   1,     1 },
     148                 :   { "STATE90R",   'L', 'N', OFTInteger,    18,  19,   2,       1,   1,     1 },
     149                 :   { "COUN90L",    'L', 'N', OFTInteger,    20,  22,   3,       1,   1,     1 },
     150                 :   { "COUN90R",    'L', 'N', OFTInteger,    23,  25,   3,       1,   1,     1 },
     151                 :   { "FMCD90L",    'L', 'N', OFTInteger,    26,  30,   5,       1,   1,     1 },
     152                 :   { "FMCD90R",    'L', 'N', OFTInteger,    31,  35,   5,       1,   1,     1 },
     153                 :   { "FPL90L",     'L', 'N', OFTInteger,    36,  40,   5,       1,   1,     1 },
     154                 :   { "FPL90R",     'L', 'N', OFTInteger,    41,  45,   5,       1,   1,     1 },
     155                 :   { "CTBNA90L",   'L', 'N', OFTInteger,    46,  51,   6,       1,   1,     1 },
     156                 :   { "CTBNA90R",   'L', 'N', OFTInteger,    52,  57,   6,       1,   1,     1 },
     157                 :   { "AIR90L",     'L', 'N', OFTInteger,    58,  61,   4,       1,   1,     1 },
     158                 :   { "AIR90R",     'L', 'N', OFTInteger,    62,  65,   4,       1,   1,     1 },
     159                 :   { "TRUST90L",   'L', 'A', OFTString,     66,  66,   1,       1,   1,     1 },
     160                 :   { "TRUST90R",   'L', 'A', OFTString,     67,  67,   1,       1,   1,     1 },
     161                 :   { "BLK90L",     'L', 'A', OFTString,     70,  73,   4,       1,   1,     1 },
     162                 :   { "BLK90R",     'L', 'A', OFTString,     74,  77,   4,       1,   1,     1 },
     163                 :   { "AIRL",       'L', 'N', OFTInteger,    78,  81,   4,       1,   1,     1 },
     164                 :   { "AIRR",       'L', 'N', OFTInteger,    82,  85,   4,       1,   1,     1 },
     165                 : 
     166                 :   { "ANRCL",      'L', 'N', OFTInteger,    86,  90,   5,       1,   1,     1 },
     167                 :   { "ANRCR",      'L', 'N', OFTInteger,    91,  95,   5,       1,   1,     1 },
     168                 :   { "AITSCEL",    'L', 'N', OFTInteger,    96,  98,   3,       1,   1,     1 },
     169                 :   { "AITSCER",    'L', 'N', OFTInteger,    99, 101,   3,       1,   1,     1 },
     170                 :   { "AITSL",      'L', 'N', OFTInteger,   102, 106,   5 ,      1,   1,     1 },
     171                 :   { "AITSR",      'L', 'N', OFTInteger,   107, 111,   5,       1,   1,     1 }
     172                 : };
     173                 : static const TigerRecordInfo rt3_2000_Redistricting_info  =
     174                 :   {
     175                 :     rt3_2000_Redistricting_fields,
     176                 :     sizeof(rt3_2000_Redistricting_fields) / sizeof(TigerFieldInfo),
     177                 :     111
     178                 :   };
     179                 : 
     180                 : static const TigerFieldInfo rt3_fields[] = {
     181                 :   // fieldname    fmt  type OFTType       beg  end  len  bDefine bSet bWrite
     182                 :   { "TLID",       'R', 'N', OFTInteger,     6,  15,  10,       0,   0,     1 },
     183                 :   { "STATE90L",   'L', 'N', OFTInteger,    16,  17,   2,       1,   1,     1 },
     184                 :   { "STATE90R",   'L', 'N', OFTInteger,    18,  19,   2,       1,   1,     1 },
     185                 :   { "COUN90L",    'L', 'N', OFTInteger,    20,  22,   3,       1,   1,     1 },
     186                 :   { "COUN90R",    'L', 'N', OFTInteger,    23,  25,   3,       1,   1,     1 },
     187                 :   { "FMCD90L",    'L', 'N', OFTInteger,    26,  30,   5,       1,   1,     1 },
     188                 :   { "FMCD90R",    'L', 'N', OFTInteger,    31,  35,   5,       1,   1,     1 },
     189                 :   { "FPL90L",     'L', 'N', OFTInteger,    36,  40,   5,       1,   1,     1 },
     190                 :   { "FPL90R",     'L', 'N', OFTInteger,    41,  45,   5,       1,   1,     1 },
     191                 :   { "CTBNA90L",   'L', 'N', OFTInteger,    46,  51,   6,       1,   1,     1 },
     192                 :   { "CTBNA90R",   'L', 'N', OFTInteger,    52,  57,   6,       1,   1,     1 },
     193                 :   { "AIR90L",     'L', 'N', OFTInteger,    58,  61,   4,       1,   1,     1 },
     194                 :   { "AIR90R",     'L', 'N', OFTInteger,    62,  65,   4,       1,   1,     1 },
     195                 :   { "TRUST90L",   'L', 'A', OFTInteger,    66,  66,   1,       1,   1,     1 },
     196                 :   { "TRUST90R",   'L', 'A', OFTInteger,    67,  67,   1,       1,   1,     1 },
     197                 :   { "BLK90L",     'L', 'A', OFTString,     70,  73,   4,       1,   1,     1 },
     198                 :   { "BLK90R",     'L', 'A', OFTString,     74,  77,   4,       1,   1,     1 },
     199                 :   { "AIRL",       'L', 'N', OFTInteger,    78,  81,   4,       1,   1,     1 },
     200                 :   { "AIRR",       'L', 'N', OFTInteger,    82,  85,   4,       1,   1,     1 },
     201                 :  
     202                 :   { "VTDL",       'L', 'A', OFTString,    104, 107,   4,       1,   1,     1 },
     203                 :   { "VTDR",       'L', 'A', OFTString,    108, 111,   4,       1,   1,     1 }
     204                 : 
     205                 : };
     206                 : static const TigerRecordInfo rt3_info =
     207                 :   {
     208                 :     rt3_fields,
     209                 :     sizeof(rt3_fields) / sizeof(TigerFieldInfo),
     210                 :     111
     211                 :   };
     212                 : 
     213                 : /************************************************************************/
     214                 : /*                         TigerCompleteChain()                         */
     215                 : /************************************************************************/
     216                 : 
     217               7 : TigerCompleteChain::TigerCompleteChain( OGRTigerDataSource * poDSIn,
     218               7 :                                         const char * pszPrototypeModule )
     219                 : 
     220                 : {
     221               7 :     poDS = poDSIn;
     222               7 :     poFeatureDefn = new OGRFeatureDefn( "CompleteChain" );
     223               7 :     poFeatureDefn->Reference();
     224               7 :     poFeatureDefn->SetGeomType( wkbLineString );
     225                 : 
     226                 : 
     227               7 :     if (poDS->GetVersion() >= TIGER_2002) {
     228               7 :       psRT1Info = &rt1_2002_info;
     229               7 :       bUsingRT3 = FALSE;
     230                 :     } else {
     231               0 :       psRT1Info = &rt1_info;
     232               0 :       bUsingRT3 = TRUE;
     233                 :     }
     234                 : 
     235               7 :     psRT2Info = &rt2_info;
     236                 : 
     237               7 :     nRT1RecOffset = 0;
     238                 : 
     239               7 :     if (poDS->GetVersion() >= TIGER_2000_Redistricting) {
     240               7 :       psRT3Info = &rt3_2000_Redistricting_info;
     241                 :     } else {
     242               0 :       psRT3Info = &rt3_info;
     243                 :     }
     244                 : 
     245               7 :     fpRT3 = NULL;
     246                 : 
     247               7 :     panShapeRecordId = NULL;
     248               7 :     fpShape = NULL;
     249                 :     
     250                 :     /* -------------------------------------------------------------------- */
     251                 :     /*      Fields from type 1 record.                                      */
     252                 :     /* -------------------------------------------------------------------- */
     253                 : 
     254               7 :     AddFieldDefns( psRT1Info, poFeatureDefn );
     255                 : 
     256                 :     /* -------------------------------------------------------------------- */
     257                 :     /*      Fields from type 3 record.  Eventually we should verify that    */
     258                 :     /*      a .RT3 file is available before adding these fields.            */
     259                 :     /* -------------------------------------------------------------------- */
     260               7 :     if( bUsingRT3 ) {
     261               0 :       AddFieldDefns( psRT3Info, poFeatureDefn );
     262                 :     }
     263               7 : }
     264                 : 
     265                 : /************************************************************************/
     266                 : /*                        ~TigerCompleteChain()                         */
     267                 : /************************************************************************/
     268                 : 
     269               7 : TigerCompleteChain::~TigerCompleteChain()
     270                 : 
     271                 : {
     272               7 :     CPLFree( panShapeRecordId );
     273                 : 
     274               7 :     if( fpRT3 != NULL )
     275               0 :         VSIFClose( fpRT3 );
     276                 : 
     277               7 :     if( fpShape != NULL )
     278               5 :         VSIFClose( fpShape );
     279               7 : }
     280                 : 
     281                 : /************************************************************************/
     282                 : /*                             SetModule()                              */
     283                 : /************************************************************************/
     284                 : 
     285              31 : int TigerCompleteChain::SetModule( const char * pszModule )
     286                 : 
     287                 : {
     288              31 :     if( !OpenFile( pszModule, "1" ) )
     289               0 :         return FALSE;
     290                 : 
     291              31 :     EstablishFeatureCount();
     292                 : 
     293                 : /* -------------------------------------------------------------------- */
     294                 : /*      Is this a copyright record inserted at the beginning of the     */
     295                 : /*      RT1 file by the folks at GDT?  If so, setup to ignore the       */
     296                 : /*      first record.                                                   */
     297                 : /* -------------------------------------------------------------------- */
     298              31 :     nRT1RecOffset = 0;
     299              31 :     if( pszModule )
     300                 :     {
     301                 :         char achHeader[10];
     302                 :         
     303              24 :         VSIFSeek( fpPrimary, 0, SEEK_SET );
     304              24 :         VSIFRead( achHeader, sizeof(achHeader), 1, fpPrimary );
     305                 :         
     306              24 :         if( EQUALN(achHeader,"Copyright",8) )
     307                 :         {
     308               0 :             nRT1RecOffset = 1;
     309               0 :             nFeatures--;
     310                 :         }
     311                 :     }
     312                 :         
     313                 : /* -------------------------------------------------------------------- */
     314                 : /*      Open the RT3 file                                               */
     315                 : /* -------------------------------------------------------------------- */
     316              31 :     if( bUsingRT3 )
     317                 :     {
     318               0 :         if( fpRT3 != NULL )
     319                 :         {
     320               0 :             VSIFClose( fpRT3 );
     321               0 :             fpRT3 = NULL;
     322                 :         }
     323                 : 
     324               0 :         if( pszModule )
     325                 :         {
     326                 :             char        *pszFilename;
     327                 :         
     328               0 :             pszFilename = poDS->BuildFilename( pszModule, "3" );
     329                 : 
     330               0 :             fpRT3 = VSIFOpen( pszFilename, "rb" );
     331                 : 
     332               0 :             CPLFree( pszFilename );
     333                 :         }
     334                 :     }
     335                 :     
     336                 : /* -------------------------------------------------------------------- */
     337                 : /*      Close the shape point file, if open and free the list of        */
     338                 : /*      record ids.                                                     */
     339                 : /* -------------------------------------------------------------------- */
     340              31 :     if( fpShape != NULL )
     341                 :     {
     342              20 :         VSIFClose( fpShape );
     343              20 :         fpShape = NULL;
     344                 :     }
     345                 :     
     346              31 :     CPLFree( panShapeRecordId );
     347              31 :     panShapeRecordId = NULL;
     348                 : 
     349                 : /* -------------------------------------------------------------------- */
     350                 : /*      Try to open the RT2 file corresponding to this RT1 file.        */
     351                 : /* -------------------------------------------------------------------- */
     352              31 :     if( pszModule != NULL )
     353                 :     {
     354                 :         char    *pszFilename;
     355                 : 
     356              24 :         pszFilename = poDS->BuildFilename( pszModule, "2" );
     357                 : 
     358              24 :         fpShape = VSIFOpen( pszFilename, "rb" );
     359                 :         
     360              24 :         if( fpShape == NULL )
     361                 :         {
     362               0 :             if( nRT1RecOffset == 0 )
     363                 :                 CPLError( CE_Warning, CPLE_OpenFailed,
     364                 :                           "Failed to open %s, intermediate shape arcs will not be available.\n",
     365               0 :                           pszFilename );
     366                 :         }
     367                 :         else
     368              24 :             panShapeRecordId = (int *)CPLCalloc(sizeof(int),GetFeatureCount());
     369                 :         
     370              24 :         CPLFree( pszFilename );
     371                 :     }
     372                 : 
     373              31 :     return TRUE;
     374                 : }
     375                 : 
     376                 : /************************************************************************/
     377                 : /*                             GetFeature()                             */
     378                 : /************************************************************************/
     379                 : 
     380          212194 : OGRFeature *TigerCompleteChain::GetFeature( int nRecordId )
     381                 : 
     382                 : {
     383                 :     char        achRecord[OGR_TIGER_RECBUF_LEN];
     384                 : 
     385          212194 :     if( nRecordId < 0 || nRecordId >= nFeatures )
     386                 :     {
     387                 :         CPLError( CE_Failure, CPLE_FileIO,
     388                 :                   "Request for out-of-range feature %d of %s1",
     389               0 :                   nRecordId, pszModule );
     390               0 :         return NULL;
     391                 :     }
     392                 : 
     393                 : /* -------------------------------------------------------------------- */
     394                 : /*      Read the raw record data from the file.                         */
     395                 : /* -------------------------------------------------------------------- */
     396          212194 :     if( fpPrimary == NULL )
     397               0 :         return NULL;
     398                 : 
     399          212194 :     if( VSIFSeek( fpPrimary, (nRecordId+nRT1RecOffset) * nRecordLength, 
     400                 :                   SEEK_SET ) != 0 )
     401                 :     {
     402                 :         CPLError( CE_Failure, CPLE_FileIO,
     403                 :                   "Failed to seek to %d of %s1",
     404               0 :                   nRecordId * nRecordLength, pszModule );
     405               0 :         return NULL;
     406                 :     }
     407                 : 
     408          212194 :     if( VSIFRead( achRecord, psRT1Info->nRecordLength, 1, fpPrimary ) != 1 )
     409                 :     {
     410                 :         CPLError( CE_Failure, CPLE_FileIO,
     411                 :                   "Failed to read %d bytes of record %d of %s1 at offset %d",
     412                 :                   psRT1Info->nRecordLength, nRecordId, pszModule,
     413               0 :                   (nRecordId+nRT1RecOffset) * nRecordLength );
     414               0 :         return NULL;
     415                 :     }
     416                 : 
     417                 :     /* -------------------------------------------------------------------- */
     418                 :     /*      Set fields.                                                     */
     419                 :     /* -------------------------------------------------------------------- */
     420                 : 
     421          212194 :     OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
     422                 : 
     423          212194 :     SetFields( psRT1Info, poFeature, achRecord );
     424                 : 
     425                 :     /* -------------------------------------------------------------------- */
     426                 :     /*      Read RT3 record, and apply fields.                              */
     427                 :     /* -------------------------------------------------------------------- */
     428                 : 
     429          212194 :     if( fpRT3 != NULL )
     430                 :     {
     431                 :         char    achRT3Rec[OGR_TIGER_RECBUF_LEN];
     432               0 :         int     nRT3RecLen = psRT3Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength;
     433                 : 
     434               0 :         if( VSIFSeek( fpRT3, nRecordId * nRT3RecLen, SEEK_SET ) != 0 )
     435                 :         {
     436                 :             CPLError( CE_Failure, CPLE_FileIO,
     437                 :                       "Failed to seek to %d of %s3",
     438               0 :                       nRecordId * nRT3RecLen, pszModule );
     439               0 :             return NULL;
     440                 :         }
     441                 : 
     442               0 :         if( VSIFRead( achRT3Rec, psRT3Info->nRecordLength, 1, fpRT3 ) != 1 )
     443                 :         {
     444                 :             CPLError( CE_Failure, CPLE_FileIO,
     445                 :                       "Failed to read record %d of %s3",
     446               0 :                       nRecordId, pszModule );
     447               0 :             return NULL;
     448                 :         }
     449                 : 
     450               0 :         SetFields( psRT3Info, poFeature, achRT3Rec );
     451                 : 
     452                 :     }
     453                 : 
     454                 : /* -------------------------------------------------------------------- */
     455                 : /*      Set geometry                                                    */
     456                 : /* -------------------------------------------------------------------- */
     457          212194 :     OGRLineString       *poLine = new OGRLineString();
     458                 : 
     459                 :     poLine->setPoint(0,
     460                 :                      atoi(GetField(achRecord, 191, 200)) / 1000000.0,
     461          212194 :                      atoi(GetField(achRecord, 201, 209)) / 1000000.0 );
     462                 : 
     463          212194 :     if( !AddShapePoints( poFeature->GetFieldAsInteger("TLID"), nRecordId,
     464                 :                          poLine, 0 ) )
     465                 :     {
     466               0 :         delete poFeature;
     467               0 :         return NULL;
     468                 :     }
     469                 :     
     470                 :     poLine->addPoint(atoi(GetField(achRecord, 210, 219)) / 1000000.0,
     471          212194 :                      atoi(GetField(achRecord, 220, 228)) / 1000000.0 );
     472                 : 
     473          212194 :     poFeature->SetGeometryDirectly( poLine );
     474                 : 
     475          212194 :     return poFeature;
     476                 : }
     477                 : 
     478                 : /************************************************************************/
     479                 : /*                           AddShapePoints()                           */
     480                 : /*                                                                      */
     481                 : /*      Record zero or more shape records associated with this line     */
     482                 : /*      and add the points to the passed line geometry.                 */
     483                 : /************************************************************************/
     484                 : 
     485          212194 : int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
     486                 :                                         OGRLineString * poLine, int nSeqNum ) 
     487                 : 
     488                 : {
     489                 :     int         nShapeRecId;
     490                 : 
     491          212194 :     nShapeRecId = GetShapeRecordId( nRecordId, nTLID );
     492                 : 
     493                 :     // -2 means an error occured.
     494          212194 :     if( nShapeRecId == -2 )
     495               0 :         return FALSE;
     496                 : 
     497                 :     // -1 means there are no extra shape vertices, but things worked fine.
     498          212194 :     if( nShapeRecId == -1 )
     499           34354 :         return TRUE;
     500                 : 
     501                 : /* -------------------------------------------------------------------- */
     502                 : /*      Read all the sequential records with the same TLID.             */
     503                 : /* -------------------------------------------------------------------- */
     504                 :     char        achShapeRec[OGR_TIGER_RECBUF_LEN];
     505          177840 :     int         nShapeRecLen = psRT2Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength;
     506                 : 
     507          171710 :     for( ; TRUE; nShapeRecId++ )
     508                 :     {
     509          349550 :         int  nBytesRead = 0;
     510                 : 
     511          349550 :         if( VSIFSeek( fpShape, (nShapeRecId-1) * nShapeRecLen,
     512                 :                       SEEK_SET ) != 0 )
     513                 :         {
     514                 :             CPLError( CE_Failure, CPLE_FileIO,
     515                 :                       "Failed to seek to %d of %s2",
     516               0 :                       (nShapeRecId-1) * nShapeRecLen, pszModule );
     517               0 :             return FALSE;
     518                 :         }
     519                 : 
     520                 :         nBytesRead = VSIFRead( achShapeRec, 1, psRT2Info->nRecordLength, 
     521          349550 :                                fpShape );
     522                 : 
     523                 :         /* 
     524                 :         ** Handle case where the last record in the file is full.  We will
     525                 :         ** try to read another record but not find it.  We require that we
     526                 :         ** have found at least one shape record for this case though. 
     527                 :         */
     528          349550 :         if( nBytesRead <= 0 && VSIFEof( fpShape ) 
     529                 :             && poLine->getNumPoints() > 0 )
     530               0 :             break;
     531                 : 
     532          349550 :         if( nBytesRead != psRT2Info->nRecordLength )
     533                 :         {
     534                 :             CPLError( CE_Failure, CPLE_FileIO,
     535                 :                       "Failed to read %d bytes of record %d of %s2 at offset %d",
     536                 :                       psRT2Info->nRecordLength, nShapeRecId, pszModule,
     537               0 :                       (nShapeRecId-1) * nShapeRecLen );
     538               0 :             return FALSE;
     539                 :         }
     540                 : 
     541          349550 :         if( atoi(GetField(achShapeRec,6,15)) != nTLID )
     542           10065 :             break;
     543                 : 
     544                 : /* -------------------------------------------------------------------- */
     545                 : /*      Translate the locations into OGRLineString vertices.            */
     546                 : /* -------------------------------------------------------------------- */
     547                 :         int     iVertex;
     548                 : 
     549         2759154 :         for( iVertex = 0; iVertex < 10; iVertex++ )
     550                 :         {
     551         2587444 :             int         iStart = 19 + 19*iVertex;
     552         2587444 :             int         nX = atoi(GetField(achShapeRec,iStart,iStart+9));
     553         2587444 :             int         nY = atoi(GetField(achShapeRec,iStart+10,iStart+18));
     554                 : 
     555         2587444 :             if( nX == 0 && nY == 0 )
     556          167775 :                 break;
     557                 : 
     558         2419669 :             poLine->addPoint( nX / 1000000.0, nY / 1000000.0 );
     559                 :         }
     560                 : 
     561                 : /* -------------------------------------------------------------------- */
     562                 : /*      Don't get another record if this one was incomplete.            */
     563                 : /* -------------------------------------------------------------------- */
     564          339485 :         if( iVertex < 10 )
     565          167775 :             break;
     566                 :     }
     567                 : 
     568          177840 :     return TRUE;
     569                 : }
     570                 : 
     571                 : /************************************************************************/
     572                 : /*                          GetShapeRecordId()                          */
     573                 : /*                                                                      */
     574                 : /*      Get the record id of the first record of shape points for       */
     575                 : /*      the provided TLID (complete chain).                             */
     576                 : /************************************************************************/
     577                 : 
     578          212194 : int TigerCompleteChain::GetShapeRecordId( int nChainId, int nTLID )
     579                 : 
     580                 : {
     581          212194 :     CPLAssert( nChainId >= 0 && nChainId < GetFeatureCount() );
     582                 : 
     583          212194 :     if( fpShape == NULL || panShapeRecordId == NULL )
     584               0 :         return -1;
     585                 :     
     586                 : /* -------------------------------------------------------------------- */
     587                 : /*      Do we already have the answer?                                  */
     588                 : /* -------------------------------------------------------------------- */
     589          212194 :     if( panShapeRecordId[nChainId] != 0 )
     590               2 :         return panShapeRecordId[nChainId];
     591                 :     
     592                 : /* -------------------------------------------------------------------- */
     593                 : /*      If we don't already have this value, then search from the       */
     594                 : /*      previous known record.                                          */
     595                 : /* -------------------------------------------------------------------- */
     596                 :     int iTestChain, nWorkingRecId;
     597                 :         
     598          475594 :     for( iTestChain = nChainId-1;
     599          263402 :          iTestChain >= 0 && panShapeRecordId[iTestChain] <= 0;
     600                 :          iTestChain-- ) {}
     601                 : 
     602          212192 :     if( iTestChain < 0 )
     603                 :     {
     604              18 :         iTestChain = -1;
     605              18 :         nWorkingRecId = 1;
     606                 :     }
     607                 :     else
     608                 :     {
     609          212174 :         nWorkingRecId = panShapeRecordId[iTestChain]+1;
     610                 :     }
     611                 : 
     612                 : /* -------------------------------------------------------------------- */
     613                 : /*      If we have non existent records following (-1's) we can         */
     614                 : /*      narrow our search a bit.                                        */
     615                 : /* -------------------------------------------------------------------- */
     616          475612 :     while( panShapeRecordId[iTestChain+1] == -1 )
     617                 :     {
     618           51228 :         iTestChain++;
     619                 :     }
     620                 : 
     621                 : /* -------------------------------------------------------------------- */
     622                 : /*      Read records up to the maximum distance that is possibly        */
     623                 : /*      required, looking for our target TLID.                          */
     624                 : /* -------------------------------------------------------------------- */
     625          212192 :     int         nMaxChainToRead = nChainId - iTestChain;
     626          212192 :     int         nChainsRead = 0;
     627                 :     char        achShapeRec[OGR_TIGER_RECBUF_LEN];
     628          212192 :     int         nShapeRecLen = psRT2Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength;
     629                 : 
     630          640733 :     while( nChainsRead < nMaxChainToRead )
     631                 :     {
     632          394198 :         if( VSIFSeek( fpShape, (nWorkingRecId-1) * nShapeRecLen,
     633                 :                       SEEK_SET ) != 0 )
     634                 :         {
     635                 :             CPLError( CE_Failure, CPLE_FileIO,
     636                 :                       "Failed to seek to %d of %s2",
     637               0 :                       (nWorkingRecId-1) * nShapeRecLen, pszModule );
     638               0 :             return -2;
     639                 :         }
     640                 : 
     641          394198 :         if( VSIFRead( achShapeRec, psRT2Info->nRecordLength, 1, fpShape ) != 1 )
     642                 :         {
     643              11 :             if( !VSIFEof( fpShape ) )
     644                 :             {
     645                 :                 CPLError( CE_Failure, CPLE_FileIO,
     646                 :                           "Failed to read record %d of %s2",
     647               0 :                           nWorkingRecId-1, pszModule );
     648               0 :                 return -2;
     649                 :             }
     650                 :             else
     651              11 :                 return -1;
     652                 :         }
     653                 : 
     654          394187 :         if( atoi(GetField(achShapeRec,6,15)) == nTLID )
     655                 :         {
     656          177838 :             panShapeRecordId[nChainId] = nWorkingRecId;
     657                 : 
     658          177838 :             return nWorkingRecId;
     659                 :         }
     660                 : 
     661          216349 :         if( atoi(GetField(achShapeRec,16,18)) == 1 )
     662                 :         {
     663           34343 :             nChainsRead++;
     664                 :         }
     665                 : 
     666          216349 :         nWorkingRecId++;
     667                 :     }
     668                 : 
     669           34343 :     panShapeRecordId[nChainId] = -1;
     670                 : 
     671           34343 :     return -1;
     672                 : }
     673                 : 
     674                 : /************************************************************************/
     675                 : /*                           SetWriteModule()                           */
     676                 : /************************************************************************/
     677           19289 : int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen, 
     678                 :                                         OGRFeature *poFeature )
     679                 : 
     680                 : {
     681                 :     int bSuccess;
     682                 : 
     683           19289 :     bSuccess = TigerFileBase::SetWriteModule( pszFileCode, nRecLen, poFeature);
     684           19289 :     if( !bSuccess )
     685               0 :         return bSuccess;
     686                 : 
     687                 : /* -------------------------------------------------------------------- */
     688                 : /*      Open the RT3 file                                               */
     689                 : /* -------------------------------------------------------------------- */
     690           19289 :     if( bUsingRT3 )
     691                 :     {
     692               0 :         if( fpRT3 != NULL )
     693                 :         {
     694               0 :             VSIFClose( fpRT3 );
     695               0 :             fpRT3 = NULL;
     696                 :         }
     697                 : 
     698               0 :         if( pszModule )
     699                 :         {
     700                 :             char        *pszFilename;
     701                 :         
     702               0 :             pszFilename = poDS->BuildFilename( pszModule, "3" );
     703                 : 
     704               0 :             fpRT3 = VSIFOpen( pszFilename, "ab" );
     705                 : 
     706               0 :             CPLFree( pszFilename );
     707                 :         }
     708                 :     }
     709                 :     
     710                 : /* -------------------------------------------------------------------- */
     711                 : /*      Close the shape point file, if open and free the list of        */
     712                 : /*      record ids.                                                     */
     713                 : /* -------------------------------------------------------------------- */
     714           19289 :     if( fpShape != NULL )
     715                 :     {
     716           19288 :         VSIFClose( fpShape );
     717           19288 :         fpShape = NULL;
     718                 :     }
     719                 :     
     720           19289 :     if( pszModule )
     721                 :     {
     722                 :         char        *pszFilename;
     723                 :         
     724           19289 :         pszFilename = poDS->BuildFilename( pszModule, "2" );
     725                 :         
     726           19289 :         fpShape = VSIFOpen( pszFilename, "ab" );
     727                 :         
     728           19289 :         CPLFree( pszFilename );
     729                 :     }
     730                 : 
     731           19289 :     return TRUE;
     732                 : }
     733                 : 
     734                 : /************************************************************************/
     735                 : /*                           CreateFeature()                            */
     736                 : /************************************************************************/
     737                 : 
     738           19289 : OGRErr TigerCompleteChain::CreateFeature( OGRFeature *poFeature )
     739                 : 
     740                 : {
     741                 :     char        szRecord[OGR_TIGER_RECBUF_LEN];
     742           19289 :     OGRLineString *poLine = (OGRLineString *) poFeature->GetGeometryRef();
     743                 : 
     744           38578 :     if( poLine == NULL 
     745           19289 :         || (poLine->getGeometryType() != wkbLineString
     746               0 :             && poLine->getGeometryType() != wkbLineString25D) )
     747               0 :         return OGRERR_FAILURE;
     748                 : 
     749                 :     /* -------------------------------------------------------------------- */
     750                 :     /*      Write basic data record ("RT1")                                 */
     751                 :     /* -------------------------------------------------------------------- */
     752           19289 :     if( !SetWriteModule( "1", psRT1Info->nRecordLength+2, poFeature ) )
     753               0 :         return OGRERR_FAILURE;
     754           19289 :     memset( szRecord, ' ', psRT1Info->nRecordLength );
     755           19289 :     WriteFields( psRT1Info, poFeature, szRecord );
     756           19289 :     WritePoint( szRecord, 191, poLine->getX(0), poLine->getY(0) );
     757                 :     WritePoint( szRecord, 210, 
     758                 :                 poLine->getX(poLine->getNumPoints()-1), 
     759           19289 :                 poLine->getY(poLine->getNumPoints()-1) );
     760           19289 :     WriteRecord( szRecord, psRT1Info->nRecordLength, "1" );
     761                 : 
     762                 :     /* -------------------------------------------------------------------- */
     763                 :     /*      Write geographic entity codes (RT3)                             */
     764                 :     /* -------------------------------------------------------------------- */
     765           19289 :     if (bUsingRT3) {
     766               0 :       memset( szRecord, ' ', psRT3Info->nRecordLength );
     767               0 :       WriteFields( psRT3Info, poFeature, szRecord );
     768               0 :       WriteRecord( szRecord, psRT3Info->nRecordLength, "3", fpRT3 );
     769                 :     }
     770                 : 
     771                 :     /* -------------------------------------------------------------------- */
     772                 :     /*      Write shapes sections (RT2)                                     */
     773                 :     /* -------------------------------------------------------------------- */
     774           19289 :     if( poLine->getNumPoints() > 2 )
     775                 :     {
     776           16166 :         int     nPoints = poLine->getNumPoints();
     777           16166 :         int     iPoint, nRTSQ = 1;
     778                 : 
     779           63193 :         for( iPoint = 1; iPoint < nPoints-1; )
     780                 :         {
     781                 :             int         i;
     782                 :             char        szTemp[5];
     783                 : 
     784           30861 :             memset( szRecord, ' ', psRT2Info->nRecordLength );
     785                 : 
     786           30861 :             WriteField( poFeature, "TLID", szRecord, 6, 15, 'R', 'N' );
     787                 :             
     788           30861 :             sprintf( szTemp, "%3d", nRTSQ );
     789           30861 :             strncpy( ((char *)szRecord) + 15, szTemp, 4 );
     790                 : 
     791          339471 :             for( i = 0; i < 10; i++ )
     792                 :             {
     793          308610 :                 if( iPoint < nPoints-1 )
     794                 :                     WritePoint( szRecord, 19+19*i, 
     795          219965 :                                 poLine->getX(iPoint), poLine->getY(iPoint) );
     796                 :                 else
     797           88645 :                     WritePoint( szRecord, 19+19*i, 0.0, 0.0 );
     798                 : 
     799          308610 :                 iPoint++;
     800                 :             }
     801                 :             
     802           30861 :             WriteRecord( szRecord, psRT2Info->nRecordLength, "2", fpShape );
     803                 : 
     804           30861 :             nRTSQ++;
     805                 :         }
     806                 :     }
     807                 : 
     808           19289 :     return OGRERR_NONE;
     809                 : }

Generated by: LCOV version 1.7