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 1037 : OGRVFKLayer::OGRVFKLayer(const char *pszName, OGRSpatialReference *poSRSIn, 26 1037 : OGRwkbGeometryType eReqType, OGRVFKDataSource *poDSIn) 27 1037 : : poSRS(poSRSIn == nullptr ? new OGRSpatialReference() : poSRSIn->Clone()), 28 1037 : poFeatureDefn(new OGRFeatureDefn(pszName)), 29 3111 : poDataBlock(poDSIn->GetReader()->GetDataBlock(pszName)), m_iNextFeature(0) 30 : { 31 1037 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); 32 : 33 1037 : if (poSRSIn == nullptr) 34 : { 35 : // Default is S-JTSK (EPSG: 5514). 36 1037 : if (poSRS->importFromEPSG(5514) != OGRERR_NONE) 37 : { 38 0 : delete poSRS; 39 0 : poSRS = nullptr; 40 : } 41 : } 42 : 43 1037 : SetDescription(poFeatureDefn->GetName()); 44 1037 : poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS); 45 : 46 1037 : poFeatureDefn->Reference(); 47 1037 : poFeatureDefn->SetGeomType(eReqType); 48 1037 : } 49 : 50 : /*! 51 : \brief OGRVFKLayer() destructor 52 : */ 53 2074 : OGRVFKLayer::~OGRVFKLayer() 54 : { 55 1037 : if (poFeatureDefn) 56 1037 : poFeatureDefn->Release(); 57 : 58 1037 : if (poSRS) 59 1037 : poSRS->Release(); 60 2074 : } 61 : 62 : /*! 63 : \brief Test capability (random access, etc.) 64 : 65 : \param pszCap capability name 66 : */ 67 2 : int OGRVFKLayer::TestCapability(const char *pszCap) const 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 8 : void OGRVFKLayer::ResetReading() 87 : { 88 8 : m_iNextFeature = 0; 89 8 : poDataBlock->ResetReading(); 90 8 : } 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 32 : const OGRGeometry *OGRVFKLayer::GetGeometry(IVFKFeature *poVfkFeature) 100 : { 101 32 : 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 10 : OGRFeature *OGRVFKLayer::GetNextFeature() 135 : { 136 : /* loop till we find and translate a feature meeting all our 137 : requirements 138 : */ 139 10 : if (m_iNextFeature < 1 && m_poFilterGeom == nullptr && 140 7 : m_poAttrQuery == nullptr) 141 : { 142 : /* sequential feature properties access only supported when no 143 : filter enabled */ 144 5 : poDataBlock->LoadProperties(); 145 : } 146 : while (true) 147 : { 148 34 : IVFKFeature *poVFKFeature = poDataBlock->GetNextFeature(); 149 34 : 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 31 : if (poVFKFeature->GetGeometryType() == wkbUnknown) 158 0 : continue; 159 : 160 31 : OGRFeature *poOGRFeature = GetFeature(poVFKFeature); 161 31 : if (poOGRFeature) 162 7 : 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 32 : OGRFeature *OGRVFKLayer::GetFeature(IVFKFeature *poVFKFeature) 201 : { 202 : /* skip feature with unknown geometry type */ 203 32 : if (poVFKFeature->GetGeometryType() == wkbUnknown) 204 0 : return nullptr; 205 : 206 : /* get features geometry */ 207 32 : const OGRGeometry *poGeomRef = GetGeometry(poVFKFeature); 208 : 209 : /* does it satisfy the spatial query, if there is one? */ 210 32 : if (m_poFilterGeom != nullptr && poGeomRef && !FilterGeometry(poGeomRef)) 211 : { 212 0 : return nullptr; 213 : } 214 : 215 : /* convert the whole feature into an OGRFeature */ 216 32 : OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn()); 217 32 : poOGRFeature->SetFID(poVFKFeature->GetFID()); 218 32 : poVFKFeature->LoadProperties(poOGRFeature); 219 : 220 : /* test against the attribute query */ 221 32 : if (m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poOGRFeature)) 222 : { 223 24 : delete poOGRFeature; 224 24 : return nullptr; 225 : } 226 : 227 8 : if (poGeomRef) 228 : { 229 8 : auto poGeom = poGeomRef->clone(); 230 8 : poGeom->assignSpatialReference(poSRS); 231 8 : poOGRFeature->SetGeometryDirectly(poGeom); 232 : } 233 : 234 8 : m_iNextFeature++; 235 : 236 8 : return poOGRFeature; 237 : }