Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: OpenGIS Simple Features Reference Implementation 4 : * Purpose: Implements OGRVFKLayer class. 5 : * Author: Martin Landa, landa.martin gmail.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2009-2010, Martin Landa <landa.martin gmail.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "ogr_vfk.h" 14 : #include "cpl_conv.h" 15 : #include "cpl_string.h" 16 : 17 : /*! 18 : \brief OGRVFKLayer constructor 19 : 20 : \param pszName layer name 21 : \param poSRSIn spatial reference 22 : \param eReqType WKB geometry type 23 : \param poDSIn data source where to register OGR layer 24 : */ 25 976 : OGRVFKLayer::OGRVFKLayer(const char *pszName, OGRSpatialReference *poSRSIn, 26 976 : OGRwkbGeometryType eReqType, OGRVFKDataSource *poDSIn) 27 976 : : poSRS(poSRSIn == nullptr ? new OGRSpatialReference() : poSRSIn->Clone()), 28 976 : poFeatureDefn(new OGRFeatureDefn(pszName)), 29 2928 : poDataBlock(poDSIn->GetReader()->GetDataBlock(pszName)), m_iNextFeature(0) 30 : { 31 976 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); 32 : 33 976 : if (poSRSIn == nullptr) 34 : { 35 : // Default is S-JTSK (EPSG: 5514). 36 976 : if (poSRS->importFromEPSG(5514) != OGRERR_NONE) 37 : { 38 0 : delete poSRS; 39 0 : poSRS = nullptr; 40 : } 41 : } 42 : 43 976 : SetDescription(poFeatureDefn->GetName()); 44 976 : poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS); 45 : 46 976 : poFeatureDefn->Reference(); 47 976 : poFeatureDefn->SetGeomType(eReqType); 48 976 : } 49 : 50 : /*! 51 : \brief OGRVFKLayer() destructor 52 : */ 53 1952 : OGRVFKLayer::~OGRVFKLayer() 54 : { 55 976 : if (poFeatureDefn) 56 976 : poFeatureDefn->Release(); 57 : 58 976 : if (poSRS) 59 976 : poSRS->Release(); 60 1952 : } 61 : 62 : /*! 63 : \brief Test capability (random access, etc.) 64 : 65 : \param pszCap capability name 66 : */ 67 2 : int OGRVFKLayer::TestCapability(const char *pszCap) 68 : { 69 2 : if (EQUAL(pszCap, OLCRandomRead)) 70 : { 71 0 : return TRUE; /* ? */ 72 : } 73 2 : if (EQUAL(pszCap, OLCStringsAsUTF8)) 74 : { 75 2 : return TRUE; 76 : } 77 : 78 0 : return FALSE; 79 : } 80 : 81 : /*! 82 : \brief Reset reading 83 : 84 : \todo To be implemented 85 : */ 86 7 : void OGRVFKLayer::ResetReading() 87 : { 88 7 : m_iNextFeature = 0; 89 7 : poDataBlock->ResetReading(); 90 7 : } 91 : 92 : /*! 93 : \brief Get geometry from VFKFeature 94 : 95 : \param poVfkFeature pointer to VFKFeature 96 : 97 : \return pointer to OGRGeometry or NULL on error 98 : */ 99 31 : const OGRGeometry *OGRVFKLayer::GetGeometry(IVFKFeature *poVfkFeature) 100 : { 101 31 : return poVfkFeature->GetGeometry(); 102 : } 103 : 104 : /*! 105 : \brief Get feature count 106 : 107 : This method overwrites OGRLayer::GetFeatureCount(), 108 : 109 : \param bForce skip (return -1) 110 : 111 : \return number of features 112 : */ 113 3 : GIntBig OGRVFKLayer::GetFeatureCount(CPL_UNUSED int bForce) 114 : { 115 : /* note that 'nfeatures' is 0 when data are not read from DB */ 116 3 : int nfeatures = (int)poDataBlock->GetFeatureCount(); 117 3 : if (m_poFilterGeom || m_poAttrQuery || nfeatures < 1) 118 : { 119 : /* force real feature count */ 120 0 : nfeatures = (int)OGRLayer::GetFeatureCount(); 121 : } 122 : 123 3 : CPLDebug("OGR-VFK", "OGRVFKLayer::GetFeatureCount(): name=%s -> n=%d", 124 3 : GetName(), nfeatures); 125 : 126 3 : return nfeatures; 127 : } 128 : 129 : /*! 130 : \brief Get next feature 131 : 132 : \return pointer to OGRFeature instance 133 : */ 134 9 : OGRFeature *OGRVFKLayer::GetNextFeature() 135 : { 136 : /* loop till we find and translate a feature meeting all our 137 : requirements 138 : */ 139 9 : if (m_iNextFeature < 1 && m_poFilterGeom == nullptr && 140 6 : m_poAttrQuery == nullptr) 141 : { 142 : /* sequential feature properties access only supported when no 143 : filter enabled */ 144 4 : poDataBlock->LoadProperties(); 145 : } 146 : while (true) 147 : { 148 33 : IVFKFeature *poVFKFeature = poDataBlock->GetNextFeature(); 149 33 : if (!poVFKFeature) 150 : { 151 : /* clean loaded feature properties for a next run */ 152 3 : poDataBlock->CleanProperties(); 153 3 : return nullptr; 154 : } 155 : 156 : /* skip feature with unknown geometry type */ 157 30 : if (poVFKFeature->GetGeometryType() == wkbUnknown) 158 0 : continue; 159 : 160 30 : OGRFeature *poOGRFeature = GetFeature(poVFKFeature); 161 30 : if (poOGRFeature) 162 6 : return poOGRFeature; 163 24 : } 164 : } 165 : 166 : /*! 167 : \brief Get feature by fid 168 : 169 : \param nFID feature id (-1 for next) 170 : 171 : \return pointer to OGRFeature or NULL not found 172 : */ 173 1 : OGRFeature *OGRVFKLayer::GetFeature(GIntBig nFID) 174 : { 175 1 : IVFKFeature *poVFKFeature = poDataBlock->GetFeature(nFID); 176 : 177 1 : if (!poVFKFeature) 178 0 : return nullptr; 179 : 180 : /* clean loaded feature properties (sequential access not 181 : finished) */ 182 1 : if (m_iNextFeature > 0) 183 : { 184 0 : ResetReading(); 185 0 : poDataBlock->CleanProperties(); 186 : } 187 : 188 1 : CPLAssert(nFID == poVFKFeature->GetFID()); 189 1 : CPLDebug("OGR-VFK", "OGRVFKLayer::GetFeature(): name=%s fid=" CPL_FRMT_GIB, 190 1 : GetName(), nFID); 191 : 192 1 : return GetFeature(poVFKFeature); 193 : } 194 : 195 : /*! 196 : \brief Get feature (private) 197 : 198 : \return pointer to OGRFeature or NULL not found 199 : */ 200 31 : OGRFeature *OGRVFKLayer::GetFeature(IVFKFeature *poVFKFeature) 201 : { 202 : /* skip feature with unknown geometry type */ 203 31 : if (poVFKFeature->GetGeometryType() == wkbUnknown) 204 0 : return nullptr; 205 : 206 : /* get features geometry */ 207 31 : const OGRGeometry *poGeomRef = GetGeometry(poVFKFeature); 208 : 209 : /* does it satisfy the spatial query, if there is one? */ 210 31 : if (m_poFilterGeom != nullptr && poGeomRef && !FilterGeometry(poGeomRef)) 211 : { 212 0 : return nullptr; 213 : } 214 : 215 : /* convert the whole feature into an OGRFeature */ 216 31 : OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn()); 217 31 : poOGRFeature->SetFID(poVFKFeature->GetFID()); 218 31 : poVFKFeature->LoadProperties(poOGRFeature); 219 : 220 : /* test against the attribute query */ 221 31 : if (m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poOGRFeature)) 222 : { 223 24 : delete poOGRFeature; 224 24 : return nullptr; 225 : } 226 : 227 7 : if (poGeomRef) 228 : { 229 7 : auto poGeom = poGeomRef->clone(); 230 7 : poGeom->assignSpatialReference(poSRS); 231 7 : poOGRFeature->SetGeometryDirectly(poGeom); 232 : } 233 : 234 7 : m_iNextFeature++; 235 : 236 7 : return poOGRFeature; 237 : }