Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: S-57 Translator 4 : * Purpose: Implements OGRS57Layer class. 5 : * Author: Frank Warmerdam, warmerdam@pobox.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 1999, Frank Warmerdam 9 : * Copyright (c) 2009-2014, Even Rouault <even dot rouault at spatialys.com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************/ 13 : 14 : #include "cpl_conv.h" 15 : #include "cpl_string.h" 16 : #include "ogr_s57.h" 17 : 18 : /************************************************************************/ 19 : /* OGRS57Layer() */ 20 : /* */ 21 : /* Note that the OGRS57Layer assumes ownership of the passed */ 22 : /* OGRFeatureDefn object. */ 23 : /************************************************************************/ 24 : 25 5402 : OGRS57Layer::OGRS57Layer(OGRS57DataSource *poDSIn, OGRFeatureDefn *poDefnIn, 26 5402 : int nFeatureCountIn, int nOBJLIn) 27 : : poDS(poDSIn), poFeatureDefn(poDefnIn), nCurrentModule(-1), 28 : nRCNM(100), // Default to feature. 29 5402 : nOBJL(nOBJLIn), nNextFEIndex(0), nFeatureCount(nFeatureCountIn) 30 : { 31 5402 : SetDescription(poFeatureDefn->GetName()); 32 5402 : if (poFeatureDefn->GetGeomFieldCount() > 0) 33 10442 : poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( 34 5221 : poDS->DSGetSpatialRef()); 35 : 36 5402 : if (EQUAL(poDefnIn->GetName(), OGRN_VI)) 37 21 : nRCNM = RCNM_VI; 38 5381 : else if (EQUAL(poDefnIn->GetName(), OGRN_VC)) 39 21 : nRCNM = RCNM_VC; 40 5360 : else if (EQUAL(poDefnIn->GetName(), OGRN_VE)) 41 21 : nRCNM = RCNM_VE; 42 5339 : else if (EQUAL(poDefnIn->GetName(), OGRN_VF)) 43 21 : nRCNM = RCNM_VF; 44 5318 : else if (EQUAL(poDefnIn->GetName(), "DSID")) 45 37 : nRCNM = RCNM_DSID; 46 : // Leave as feature. 47 5402 : } 48 : 49 : /************************************************************************/ 50 : /* ~OGRS57Layer() */ 51 : /************************************************************************/ 52 : 53 10804 : OGRS57Layer::~OGRS57Layer() 54 : 55 : { 56 5402 : if (m_nFeaturesRead > 0) 57 : { 58 98 : CPLDebug("S57", "%d features read on layer '%s'.", 59 49 : static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName()); 60 : } 61 : 62 5402 : poFeatureDefn->Release(); 63 10804 : } 64 : 65 : /************************************************************************/ 66 : /* ResetReading() */ 67 : /************************************************************************/ 68 : 69 1093 : void OGRS57Layer::ResetReading() 70 : 71 : { 72 1093 : nNextFEIndex = 0; 73 1093 : nCurrentModule = -1; 74 1093 : } 75 : 76 : /************************************************************************/ 77 : /* GetNextUnfilteredFeature() */ 78 : /************************************************************************/ 79 : 80 2010 : OGRFeature *OGRS57Layer::GetNextUnfilteredFeature() 81 : 82 : { 83 : /* -------------------------------------------------------------------- */ 84 : /* Are we out of modules to request features from? */ 85 : /* -------------------------------------------------------------------- */ 86 2010 : if (nCurrentModule >= poDS->GetModuleCount()) 87 361 : return nullptr; 88 : 89 : /* -------------------------------------------------------------------- */ 90 : /* Set the current position on the current module and fetch a */ 91 : /* feature. */ 92 : /* -------------------------------------------------------------------- */ 93 1649 : S57Reader *poReader = poDS->GetModule(nCurrentModule); 94 1649 : OGRFeature *poFeature = nullptr; 95 : 96 1649 : if (poReader != nullptr) 97 : { 98 1159 : poReader->SetNextFEIndex(nNextFEIndex, nRCNM); 99 1159 : poFeature = poReader->ReadNextFeature(poFeatureDefn); 100 1159 : nNextFEIndex = poReader->GetNextFEIndex(nRCNM); 101 : } 102 : 103 : /* -------------------------------------------------------------------- */ 104 : /* If we didn't get a feature we need to move onto the next file. */ 105 : /* -------------------------------------------------------------------- */ 106 1649 : if (poFeature == nullptr) 107 : { 108 838 : nCurrentModule++; 109 838 : poReader = poDS->GetModule(nCurrentModule); 110 : 111 838 : if (poReader != nullptr && poReader->GetModule() == nullptr) 112 : { 113 0 : if (!poReader->Open(FALSE)) 114 0 : return nullptr; 115 : } 116 : 117 838 : return GetNextUnfilteredFeature(); 118 : } 119 : else 120 : { 121 811 : m_nFeaturesRead++; 122 811 : if (poFeature->GetGeometryRef() != nullptr) 123 772 : poFeature->GetGeometryRef()->assignSpatialReference( 124 772 : GetSpatialRef()); 125 : } 126 : 127 811 : return poFeature; 128 : } 129 : 130 : /************************************************************************/ 131 : /* GetNextFeature() */ 132 : /************************************************************************/ 133 : 134 945 : OGRFeature *OGRS57Layer::GetNextFeature() 135 : 136 : { 137 945 : OGRFeature *poFeature = nullptr; 138 : 139 : /* -------------------------------------------------------------------- */ 140 : /* Read features till we find one that satisfies our current */ 141 : /* spatial criteria. */ 142 : /* -------------------------------------------------------------------- */ 143 : while (true) 144 : { 145 1172 : poFeature = GetNextUnfilteredFeature(); 146 1172 : if (poFeature == nullptr) 147 361 : break; 148 : 149 1853 : if ((m_poFilterGeom == nullptr || 150 1528 : FilterGeometry(poFeature->GetGeometryRef())) && 151 717 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature))) 152 584 : break; 153 : 154 227 : delete poFeature; 155 : } 156 : 157 945 : return poFeature; 158 : } 159 : 160 : /************************************************************************/ 161 : /* TestCapability() */ 162 : /************************************************************************/ 163 : 164 759 : int OGRS57Layer::TestCapability(const char *pszCap) 165 : 166 : { 167 759 : if (EQUAL(pszCap, OLCRandomRead)) 168 0 : return false; 169 : 170 759 : if (EQUAL(pszCap, OLCSequentialWrite)) 171 13 : return true; 172 : 173 746 : if (EQUAL(pszCap, OLCRandomWrite)) 174 13 : return false; 175 : 176 733 : if (EQUAL(pszCap, OLCFastFeatureCount)) 177 231 : return !( 178 231 : m_poFilterGeom != nullptr || m_poAttrQuery != nullptr || 179 157 : nFeatureCount == -1 || 180 144 : (EQUAL(poFeatureDefn->GetName(), "SOUNDG") && 181 12 : poDS->GetModule(0) != nullptr && 182 243 : (poDS->GetModule(0)->GetOptionFlags() & S57M_SPLIT_MULTIPOINT))); 183 : 184 502 : if (EQUAL(pszCap, OLCFastGetExtent)) 185 : { 186 24 : OGREnvelope oEnvelope; 187 : 188 24 : return GetExtent(&oEnvelope, FALSE) == OGRERR_NONE; 189 : } 190 : 191 478 : if (EQUAL(pszCap, OLCFastSpatialFilter)) 192 0 : return false; 193 : 194 478 : if (EQUAL(pszCap, OLCStringsAsUTF8)) 195 : { 196 306 : return poDS->GetModule(0) != nullptr && 197 306 : (poDS->GetModule(0)->GetOptionFlags() & S57M_RECODE_BY_DSSI); 198 : } 199 : 200 325 : if (EQUAL(pszCap, OLCZGeometries)) 201 39 : return true; 202 : 203 286 : return false; 204 : } 205 : 206 : /************************************************************************/ 207 : /* GetExtent() */ 208 : /************************************************************************/ 209 : 210 73 : OGRErr OGRS57Layer::GetExtent(OGREnvelope *psExtent, int bForce) 211 : 212 : { 213 73 : if (GetGeomType() == wkbNone) 214 1 : return OGRERR_FAILURE; 215 : 216 72 : return poDS->GetDSExtent(psExtent, bForce); 217 : } 218 : 219 : /************************************************************************/ 220 : /* GetFeatureCount() */ 221 : /************************************************************************/ 222 231 : GIntBig OGRS57Layer::GetFeatureCount(int bForce) 223 : { 224 : 225 231 : if (!TestCapability(OLCFastFeatureCount)) 226 87 : return OGRLayer::GetFeatureCount(bForce); 227 : 228 144 : return nFeatureCount; 229 : } 230 : 231 : /************************************************************************/ 232 : /* GetFeature() */ 233 : /************************************************************************/ 234 : 235 64 : OGRFeature *OGRS57Layer::GetFeature(GIntBig nFeatureId) 236 : 237 : { 238 64 : S57Reader *poReader = poDS->GetModule(0); // not multi-reader aware 239 : 240 64 : if (poReader != nullptr && nFeatureId <= INT_MAX) 241 : { 242 : OGRFeature *poFeature = 243 51 : poReader->ReadFeature(static_cast<int>(nFeatureId), poFeatureDefn); 244 : 245 51 : if (poFeature != nullptr && poFeature->GetGeometryRef() != nullptr) 246 24 : poFeature->GetGeometryRef()->assignSpatialReference( 247 24 : GetSpatialRef()); 248 51 : return poFeature; 249 : } 250 : 251 13 : return nullptr; 252 : } 253 : 254 : /************************************************************************/ 255 : /* ICreateFeature() */ 256 : /************************************************************************/ 257 : 258 118 : OGRErr OGRS57Layer::ICreateFeature(OGRFeature *poFeature) 259 : 260 : { 261 : /* -------------------------------------------------------------------- */ 262 : /* Set RCNM if not already set. */ 263 : /* -------------------------------------------------------------------- */ 264 118 : const int iRCNMFld = poFeature->GetFieldIndex("RCNM"); 265 : 266 118 : if (iRCNMFld != -1) 267 : { 268 94 : if (!poFeature->IsFieldSetAndNotNull(iRCNMFld)) 269 0 : poFeature->SetField(iRCNMFld, nRCNM); 270 : else 271 : { 272 94 : CPLAssert(poFeature->GetFieldAsInteger(iRCNMFld) == nRCNM); 273 : } 274 : } 275 : 276 : /* -------------------------------------------------------------------- */ 277 : /* Set OBJL if not already set. */ 278 : /* -------------------------------------------------------------------- */ 279 118 : if (nOBJL != -1) 280 : { 281 24 : const int iOBJLFld = poFeature->GetFieldIndex("OBJL"); 282 : 283 24 : if (!poFeature->IsFieldSetAndNotNull(iOBJLFld)) 284 0 : poFeature->SetField(iOBJLFld, nOBJL); 285 : else 286 : { 287 24 : CPLAssert(poFeature->GetFieldAsInteger(iOBJLFld) == nOBJL); 288 : } 289 : } 290 : 291 : /* -------------------------------------------------------------------- */ 292 : /* Create the isolated node feature. */ 293 : /* -------------------------------------------------------------------- */ 294 118 : if (poDS->GetWriter()->WriteCompleteFeature(poFeature)) 295 118 : return OGRERR_NONE; 296 : 297 0 : return OGRERR_FAILURE; 298 : }