Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: TIGER/Line Translator 4 : * Purpose: Implements OGRTigerLayer class. 5 : * Author: Frank Warmerdam, warmerdam@pobox.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 1999, Frank Warmerdam 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "ogr_tiger.h" 14 : 15 : /************************************************************************/ 16 : /* OGRTigerLayer() */ 17 : /* */ 18 : /* Note that the OGRTigerLayer assumes ownership of the passed */ 19 : /* OGRFeatureDefn object. */ 20 : /************************************************************************/ 21 : 22 0 : OGRTigerLayer::OGRTigerLayer(OGRTigerDataSource *poDSIn, 23 0 : TigerFileBase *poReaderIn) 24 : : poReader(poReaderIn), poDS(poDSIn), nFeatureCount(0), 25 : panModuleFCount(nullptr), panModuleOffset(nullptr), iLastFeatureId(0), 26 0 : iLastModule(-1) 27 : { 28 : /* -------------------------------------------------------------------- */ 29 : /* Setup module feature counts. */ 30 : /* -------------------------------------------------------------------- */ 31 0 : panModuleFCount = (int *)CPLCalloc(poDS->GetModuleCount(), sizeof(int)); 32 0 : panModuleOffset = (int *)CPLCalloc(poDS->GetModuleCount() + 1, sizeof(int)); 33 : 34 0 : nFeatureCount = 0; 35 : 36 0 : for (int iModule = 0; iModule < poDS->GetModuleCount(); iModule++) 37 : { 38 0 : if (poReader->SetModule(poDS->GetModule(iModule))) 39 0 : panModuleFCount[iModule] = poReader->GetFeatureCount(); 40 : else 41 0 : panModuleFCount[iModule] = 0; 42 : 43 0 : panModuleOffset[iModule] = nFeatureCount; 44 0 : nFeatureCount += panModuleFCount[iModule]; 45 : } 46 : 47 : // this entry is just to make range comparisons easy without worrying 48 : // about falling off the end of the array. 49 0 : panModuleOffset[poDS->GetModuleCount()] = nFeatureCount; 50 : 51 0 : poReader->SetModule(nullptr); 52 0 : } 53 : 54 : /************************************************************************/ 55 : /* ~OGRTigerLayer() */ 56 : /************************************************************************/ 57 : 58 0 : OGRTigerLayer::~OGRTigerLayer() 59 : 60 : { 61 0 : if (m_nFeaturesRead > 0 && poReader->GetFeatureDefn() != nullptr) 62 : { 63 0 : CPLDebug("TIGER", "%d features read on layer '%s'.", 64 0 : (int)m_nFeaturesRead, poReader->GetFeatureDefn()->GetName()); 65 : } 66 : 67 0 : delete poReader; 68 : 69 0 : CPLFree(panModuleFCount); 70 0 : CPLFree(panModuleOffset); 71 0 : } 72 : 73 : /************************************************************************/ 74 : /* ResetReading() */ 75 : /************************************************************************/ 76 : 77 0 : void OGRTigerLayer::ResetReading() 78 : 79 : { 80 0 : iLastFeatureId = 0; 81 0 : iLastModule = -1; 82 0 : } 83 : 84 : /************************************************************************/ 85 : /* GetFeature() */ 86 : /************************************************************************/ 87 : 88 0 : OGRFeature *OGRTigerLayer::GetFeature(GIntBig nFeatureId) 89 : 90 : { 91 0 : if (nFeatureId < 1 || nFeatureId > nFeatureCount) 92 0 : return nullptr; 93 : 94 : /* -------------------------------------------------------------------- */ 95 : /* If we don't have the current module open for the requested */ 96 : /* data, then open it now. */ 97 : /* -------------------------------------------------------------------- */ 98 0 : if (iLastModule == -1 || nFeatureId <= panModuleOffset[iLastModule] || 99 0 : nFeatureId > panModuleOffset[iLastModule + 1]) 100 : { 101 0 : for (iLastModule = 0; iLastModule < poDS->GetModuleCount() && 102 0 : nFeatureId > panModuleOffset[iLastModule + 1]; 103 0 : iLastModule++) 104 : { 105 : } 106 : 107 0 : if (!poReader->SetModule(poDS->GetModule(iLastModule))) 108 : { 109 0 : return nullptr; 110 : } 111 : } 112 : 113 : /* -------------------------------------------------------------------- */ 114 : /* Fetch the feature associated with the record. */ 115 : /* -------------------------------------------------------------------- */ 116 0 : OGRFeature *poFeature = poReader->GetFeature( 117 0 : (int)nFeatureId - panModuleOffset[iLastModule] - 1); 118 : 119 0 : if (poFeature != nullptr) 120 : { 121 0 : poFeature->SetFID(nFeatureId); 122 : 123 0 : if (poFeature->GetGeometryRef() != nullptr) 124 0 : poFeature->GetGeometryRef()->assignSpatialReference( 125 0 : poDS->DSGetSpatialRef()); 126 : 127 0 : poFeature->SetField(0, poReader->GetShortModule()); 128 : 129 0 : m_nFeaturesRead++; 130 : } 131 : 132 0 : return poFeature; 133 : } 134 : 135 : /************************************************************************/ 136 : /* GetNextFeature() */ 137 : /************************************************************************/ 138 : 139 0 : OGRFeature *OGRTigerLayer::GetNextFeature() 140 : 141 : { 142 : /* -------------------------------------------------------------------- */ 143 : /* Read features till we find one that satisfies our current */ 144 : /* spatial criteria. */ 145 : /* -------------------------------------------------------------------- */ 146 0 : while (iLastFeatureId < nFeatureCount) 147 : { 148 0 : OGRFeature *poFeature = GetFeature(++iLastFeatureId); 149 : 150 0 : if (poFeature == nullptr) 151 0 : break; 152 : 153 0 : if ((m_poFilterGeom == nullptr || 154 0 : FilterGeometry(poFeature->GetGeometryRef())) && 155 0 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature))) 156 0 : return poFeature; 157 : 158 0 : delete poFeature; 159 : } 160 : 161 0 : return nullptr; 162 : } 163 : 164 : /************************************************************************/ 165 : /* TestCapability() */ 166 : /************************************************************************/ 167 : 168 0 : int OGRTigerLayer::TestCapability(const char *pszCap) 169 : 170 : { 171 0 : if (EQUAL(pszCap, OLCRandomRead)) 172 0 : return TRUE; 173 : 174 0 : else if (EQUAL(pszCap, OLCFastFeatureCount)) 175 0 : return TRUE; 176 : 177 : else 178 0 : return FALSE; 179 : } 180 : 181 : /************************************************************************/ 182 : /* GetLayerDefn() */ 183 : /************************************************************************/ 184 : 185 0 : OGRFeatureDefn *OGRTigerLayer::GetLayerDefn() 186 : 187 : { 188 0 : OGRFeatureDefn *poFDefn = poReader->GetFeatureDefn(); 189 0 : if (poFDefn != nullptr) 190 : { 191 0 : if (poFDefn->GetGeomFieldCount() > 0) 192 0 : poFDefn->GetGeomFieldDefn(0)->SetSpatialRef( 193 0 : poDS->DSGetSpatialRef()); 194 : } 195 0 : return poFDefn; 196 : } 197 : 198 : /************************************************************************/ 199 : /* GetFeatureCount() */ 200 : /************************************************************************/ 201 : 202 0 : GIntBig OGRTigerLayer::GetFeatureCount(int bForce) 203 : 204 : { 205 0 : if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr) 206 0 : return nFeatureCount; 207 : else 208 0 : return OGRLayer::GetFeatureCount(bForce); 209 : }