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 : * Permission is hereby granted, free of charge, to any person
11 : * obtaining a copy of this software and associated documentation
12 : * files (the "Software"), to deal in the Software without
13 : * restriction, including without limitation the rights to use, copy,
14 : * modify, merge, publish, distribute, sublicense, and/or sell copies
15 : * of the Software, and to permit persons to whom the Software is
16 : * furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be
19 : * included in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25 : * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26 : * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 : * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 : * SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "ogr_vfk.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 :
35 : /*!
36 : \brief OGRVFKLayer constructor
37 :
38 : \param pszName layer name
39 : \param poSRSIn spatial reference
40 : \param eReqType WKB geometry type
41 : \param poDSIn data source where to register OGR layer
42 : */
43 976 : OGRVFKLayer::OGRVFKLayer(const char *pszName, OGRSpatialReference *poSRSIn,
44 976 : OGRwkbGeometryType eReqType, OGRVFKDataSource *poDSIn)
45 976 : : poSRS(poSRSIn == nullptr ? new OGRSpatialReference() : poSRSIn->Clone()),
46 976 : poFeatureDefn(new OGRFeatureDefn(pszName)),
47 2928 : poDataBlock(poDSIn->GetReader()->GetDataBlock(pszName)), m_iNextFeature(0)
48 : {
49 976 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
50 :
51 976 : if (poSRSIn == nullptr)
52 : {
53 : // Default is S-JTSK (EPSG: 5514).
54 976 : if (poSRS->importFromEPSG(5514) != OGRERR_NONE)
55 : {
56 0 : delete poSRS;
57 0 : poSRS = nullptr;
58 : }
59 : }
60 :
61 976 : SetDescription(poFeatureDefn->GetName());
62 976 : poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
63 :
64 976 : poFeatureDefn->Reference();
65 976 : poFeatureDefn->SetGeomType(eReqType);
66 976 : }
67 :
68 : /*!
69 : \brief OGRVFKLayer() destructor
70 : */
71 1952 : OGRVFKLayer::~OGRVFKLayer()
72 : {
73 976 : if (poFeatureDefn)
74 976 : poFeatureDefn->Release();
75 :
76 976 : if (poSRS)
77 976 : poSRS->Release();
78 1952 : }
79 :
80 : /*!
81 : \brief Test capability (random access, etc.)
82 :
83 : \param pszCap capability name
84 : */
85 2 : int OGRVFKLayer::TestCapability(const char *pszCap)
86 : {
87 2 : if (EQUAL(pszCap, OLCRandomRead))
88 : {
89 0 : return TRUE; /* ? */
90 : }
91 2 : if (EQUAL(pszCap, OLCStringsAsUTF8))
92 : {
93 2 : return TRUE;
94 : }
95 :
96 0 : return FALSE;
97 : }
98 :
99 : /*!
100 : \brief Reset reading
101 :
102 : \todo To be implemented
103 : */
104 7 : void OGRVFKLayer::ResetReading()
105 : {
106 7 : m_iNextFeature = 0;
107 7 : poDataBlock->ResetReading();
108 7 : }
109 :
110 : /*!
111 : \brief Get geometry from VFKFeature
112 :
113 : \param poVfkFeature pointer to VFKFeature
114 :
115 : \return pointer to OGRGeometry or NULL on error
116 : */
117 31 : const OGRGeometry *OGRVFKLayer::GetGeometry(IVFKFeature *poVfkFeature)
118 : {
119 31 : return poVfkFeature->GetGeometry();
120 : }
121 :
122 : /*!
123 : \brief Get feature count
124 :
125 : This method overwrites OGRLayer::GetFeatureCount(),
126 :
127 : \param bForce skip (return -1)
128 :
129 : \return number of features
130 : */
131 3 : GIntBig OGRVFKLayer::GetFeatureCount(CPL_UNUSED int bForce)
132 : {
133 : /* note that 'nfeatures' is 0 when data are not read from DB */
134 3 : int nfeatures = (int)poDataBlock->GetFeatureCount();
135 3 : if (m_poFilterGeom || m_poAttrQuery || nfeatures < 1)
136 : {
137 : /* force real feature count */
138 0 : nfeatures = (int)OGRLayer::GetFeatureCount();
139 : }
140 :
141 3 : CPLDebug("OGR-VFK", "OGRVFKLayer::GetFeatureCount(): name=%s -> n=%d",
142 3 : GetName(), nfeatures);
143 :
144 3 : return nfeatures;
145 : }
146 :
147 : /*!
148 : \brief Get next feature
149 :
150 : \return pointer to OGRFeature instance
151 : */
152 9 : OGRFeature *OGRVFKLayer::GetNextFeature()
153 : {
154 : /* loop till we find and translate a feature meeting all our
155 : requirements
156 : */
157 9 : if (m_iNextFeature < 1 && m_poFilterGeom == nullptr &&
158 6 : m_poAttrQuery == nullptr)
159 : {
160 : /* sequential feature properties access only supported when no
161 : filter enabled */
162 4 : poDataBlock->LoadProperties();
163 : }
164 : while (true)
165 : {
166 33 : IVFKFeature *poVFKFeature = poDataBlock->GetNextFeature();
167 33 : if (!poVFKFeature)
168 : {
169 : /* clean loaded feature properties for a next run */
170 3 : poDataBlock->CleanProperties();
171 3 : return nullptr;
172 : }
173 :
174 : /* skip feature with unknown geometry type */
175 30 : if (poVFKFeature->GetGeometryType() == wkbUnknown)
176 0 : continue;
177 :
178 30 : OGRFeature *poOGRFeature = GetFeature(poVFKFeature);
179 30 : if (poOGRFeature)
180 6 : return poOGRFeature;
181 24 : }
182 : }
183 :
184 : /*!
185 : \brief Get feature by fid
186 :
187 : \param nFID feature id (-1 for next)
188 :
189 : \return pointer to OGRFeature or NULL not found
190 : */
191 1 : OGRFeature *OGRVFKLayer::GetFeature(GIntBig nFID)
192 : {
193 1 : IVFKFeature *poVFKFeature = poDataBlock->GetFeature(nFID);
194 :
195 1 : if (!poVFKFeature)
196 0 : return nullptr;
197 :
198 : /* clean loaded feature properties (sequential access not
199 : finished) */
200 1 : if (m_iNextFeature > 0)
201 : {
202 0 : ResetReading();
203 0 : poDataBlock->CleanProperties();
204 : }
205 :
206 1 : CPLAssert(nFID == poVFKFeature->GetFID());
207 1 : CPLDebug("OGR-VFK", "OGRVFKLayer::GetFeature(): name=%s fid=" CPL_FRMT_GIB,
208 1 : GetName(), nFID);
209 :
210 1 : return GetFeature(poVFKFeature);
211 : }
212 :
213 : /*!
214 : \brief Get feature (private)
215 :
216 : \return pointer to OGRFeature or NULL not found
217 : */
218 31 : OGRFeature *OGRVFKLayer::GetFeature(IVFKFeature *poVFKFeature)
219 : {
220 : /* skip feature with unknown geometry type */
221 31 : if (poVFKFeature->GetGeometryType() == wkbUnknown)
222 0 : return nullptr;
223 :
224 : /* get features geometry */
225 31 : const OGRGeometry *poGeomRef = GetGeometry(poVFKFeature);
226 :
227 : /* does it satisfy the spatial query, if there is one? */
228 31 : if (m_poFilterGeom != nullptr && poGeomRef && !FilterGeometry(poGeomRef))
229 : {
230 0 : return nullptr;
231 : }
232 :
233 : /* convert the whole feature into an OGRFeature */
234 31 : OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
235 31 : poOGRFeature->SetFID(poVFKFeature->GetFID());
236 31 : poVFKFeature->LoadProperties(poOGRFeature);
237 :
238 : /* test against the attribute query */
239 31 : if (m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poOGRFeature))
240 : {
241 24 : delete poOGRFeature;
242 24 : return nullptr;
243 : }
244 :
245 7 : if (poGeomRef)
246 : {
247 7 : auto poGeom = poGeomRef->clone();
248 7 : poGeom->assignSpatialReference(poSRS);
249 7 : poOGRFeature->SetGeometryDirectly(poGeom);
250 : }
251 :
252 7 : m_iNextFeature++;
253 :
254 7 : return poOGRFeature;
255 : }
|