1 : /******************************************************************************
2 : * $Id: ogrnaslayer.cpp 25120 2012-10-13 22:38:57Z rouault $
3 : *
4 : * Project: OGR
5 : * Purpose: Implements OGRNASLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_nas.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_port.h"
33 : #include "cpl_string.h"
34 :
35 : CPL_CVSID("$Id: ogrnaslayer.cpp 25120 2012-10-13 22:38:57Z rouault $");
36 :
37 : /************************************************************************/
38 : /* OGRNASLayer() */
39 : /************************************************************************/
40 :
41 127 : OGRNASLayer::OGRNASLayer( const char * pszName,
42 : OGRSpatialReference *poSRSIn,
43 : OGRwkbGeometryType eReqType,
44 127 : OGRNASDataSource *poDSIn )
45 :
46 : {
47 127 : if( poSRSIn == NULL )
48 127 : poSRS = NULL;
49 : else
50 0 : poSRS = poSRSIn->Clone();
51 :
52 127 : iNextNASId = 0;
53 127 : nTotalNASCount = -1;
54 :
55 127 : poDS = poDSIn;
56 :
57 127 : if ( EQUALN(pszName, "ogr:", 4) )
58 0 : poFeatureDefn = new OGRFeatureDefn( pszName+4 );
59 : else
60 127 : poFeatureDefn = new OGRFeatureDefn( pszName );
61 127 : poFeatureDefn->Reference();
62 127 : poFeatureDefn->SetGeomType( eReqType );
63 :
64 : /* -------------------------------------------------------------------- */
65 : /* Reader's should get the corresponding NASFeatureClass and */
66 : /* cache it. */
67 : /* -------------------------------------------------------------------- */
68 127 : poFClass = poDS->GetReader()->GetClass( pszName );
69 127 : }
70 :
71 : /************************************************************************/
72 : /* ~OGRNASLayer() */
73 : /************************************************************************/
74 :
75 127 : OGRNASLayer::~OGRNASLayer()
76 :
77 : {
78 127 : if( poFeatureDefn )
79 127 : poFeatureDefn->Release();
80 :
81 127 : if( poSRS != NULL )
82 0 : poSRS->Release();
83 127 : }
84 :
85 : /************************************************************************/
86 : /* ResetReading() */
87 : /************************************************************************/
88 :
89 8 : void OGRNASLayer::ResetReading()
90 :
91 : {
92 8 : iNextNASId = 0;
93 8 : poDS->GetReader()->ResetReading();
94 8 : if (poFClass)
95 8 : poDS->GetReader()->SetFilteredClassName(poFClass->GetName());
96 8 : }
97 :
98 : /************************************************************************/
99 : /* GetNextFeature() */
100 : /************************************************************************/
101 :
102 337 : OGRFeature *OGRNASLayer::GetNextFeature()
103 :
104 : {
105 337 : GMLFeature *poNASFeature = NULL;
106 337 : OGRGeometry *poGeom = NULL;
107 :
108 337 : if( iNextNASId == 0 )
109 5 : ResetReading();
110 :
111 : /* ==================================================================== */
112 : /* Loop till we find and translate a feature meeting all our */
113 : /* requirements. */
114 : /* ==================================================================== */
115 0 : while( TRUE )
116 : {
117 : /* -------------------------------------------------------------------- */
118 : /* Cleanup last feature, and get a new raw nas feature. */
119 : /* -------------------------------------------------------------------- */
120 337 : delete poNASFeature;
121 337 : delete poGeom;
122 :
123 337 : poNASFeature = NULL;
124 337 : poGeom = NULL;
125 :
126 337 : poNASFeature = poDS->GetReader()->NextFeature();
127 337 : if( poNASFeature == NULL )
128 0 : return NULL;
129 :
130 : /* -------------------------------------------------------------------- */
131 : /* Is it of the proper feature class? */
132 : /* -------------------------------------------------------------------- */
133 :
134 : // We count reading low level NAS features as a feature read for
135 : // work checking purposes, though at least we didn't necessary
136 : // have to turn it into an OGRFeature.
137 337 : m_nFeaturesRead++;
138 :
139 337 : if( poNASFeature->GetClass() != poFClass )
140 0 : continue;
141 :
142 337 : iNextNASId++;
143 :
144 : /* -------------------------------------------------------------------- */
145 : /* Does it satisfy the spatial query, if there is one? */
146 : /* -------------------------------------------------------------------- */
147 337 : const CPLXMLNode* const * papsGeometry = poNASFeature->GetGeometryList();
148 337 : if (papsGeometry[0] != NULL)
149 : {
150 335 : poGeom = (OGRGeometry*) OGR_G_CreateFromGMLTree(papsGeometry[0]);
151 :
152 1675 : if( EQUAL( papsGeometry[0]->pszValue, "CompositeCurve" ) ||
153 335 : EQUAL( papsGeometry[0]->pszValue, "MultiCurve" ) ||
154 335 : EQUAL( papsGeometry[0]->pszValue, "LineString" ) ||
155 335 : EQUAL( papsGeometry[0]->pszValue, "MultiLineString" ) ||
156 335 : EQUAL( papsGeometry[0]->pszValue, "Curve" ) )
157 : {
158 0 : poGeom = OGRGeometryFactory::forceToLineString( poGeom, false );
159 : }
160 :
161 : // poGeom->dumpReadable( 0, "NAS: " );
162 :
163 : // We assume the OGR_G_CreateFromGMLTree() function would have already
164 : // reported an error.
165 335 : if( poGeom == NULL )
166 : {
167 0 : delete poNASFeature;
168 0 : return NULL;
169 : }
170 :
171 335 : if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
172 0 : continue;
173 : }
174 :
175 : /* -------------------------------------------------------------------- */
176 : /* Convert the whole feature into an OGRFeature. */
177 : /* -------------------------------------------------------------------- */
178 : int iField;
179 337 : OGRFeature *poOGRFeature = new OGRFeature( GetLayerDefn() );
180 :
181 337 : poOGRFeature->SetFID( iNextNASId );
182 :
183 8363 : for( iField = 0; iField < poFClass->GetPropertyCount(); iField++ )
184 : {
185 8026 : const GMLProperty *psGMLProperty = poNASFeature->GetProperty( iField );
186 8026 : if( psGMLProperty == NULL || psGMLProperty->nSubProperties == 0 )
187 1661 : continue;
188 :
189 6365 : switch( poFClass->GetProperty(iField)->GetType() )
190 : {
191 : case GMLPT_Real:
192 : {
193 334 : poOGRFeature->SetField( iField, CPLAtof(psGMLProperty->papszSubProperties[0]) );
194 : }
195 334 : break;
196 :
197 : case GMLPT_IntegerList:
198 : {
199 0 : int nCount = psGMLProperty->nSubProperties;
200 0 : int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount );
201 : int i;
202 :
203 0 : for( i = 0; i < nCount; i++ )
204 0 : panIntList[i] = atoi(psGMLProperty->papszSubProperties[i]);
205 :
206 0 : poOGRFeature->SetField( iField, nCount, panIntList );
207 0 : CPLFree( panIntList );
208 : }
209 0 : break;
210 :
211 : case GMLPT_RealList:
212 : {
213 0 : int nCount = psGMLProperty->nSubProperties;
214 0 : double *padfList = (double *)CPLMalloc(sizeof(double)*nCount);
215 : int i;
216 :
217 0 : for( i = 0; i < nCount; i++ )
218 0 : padfList[i] = CPLAtof(psGMLProperty->papszSubProperties[i]);
219 :
220 0 : poOGRFeature->SetField( iField, nCount, padfList );
221 0 : CPLFree( padfList );
222 : }
223 0 : break;
224 :
225 : case GMLPT_StringList:
226 : {
227 0 : poOGRFeature->SetField( iField, psGMLProperty->papszSubProperties );
228 : }
229 0 : break;
230 :
231 : default:
232 6031 : poOGRFeature->SetField( iField, psGMLProperty->papszSubProperties[0] );
233 : break;
234 : }
235 : }
236 :
237 : /* -------------------------------------------------------------------- */
238 : /* Test against the attribute query. */
239 : /* -------------------------------------------------------------------- */
240 337 : if( m_poAttrQuery != NULL
241 : && !m_poAttrQuery->Evaluate( poOGRFeature ) )
242 : {
243 0 : delete poOGRFeature;
244 0 : continue;
245 : }
246 :
247 : /* -------------------------------------------------------------------- */
248 : /* Wow, we got our desired feature. Return it. */
249 : /* -------------------------------------------------------------------- */
250 337 : delete poNASFeature;
251 :
252 337 : poOGRFeature->SetGeometryDirectly( poGeom );
253 :
254 337 : return poOGRFeature;
255 : }
256 :
257 : return NULL;
258 : }
259 :
260 : /************************************************************************/
261 : /* GetFeatureCount() */
262 : /************************************************************************/
263 :
264 3 : int OGRNASLayer::GetFeatureCount( int bForce )
265 :
266 : {
267 3 : if( poFClass == NULL )
268 0 : return 0;
269 :
270 3 : if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
271 0 : return OGRLayer::GetFeatureCount( bForce );
272 : else
273 3 : return poFClass->GetFeatureCount();
274 : }
275 :
276 : /************************************************************************/
277 : /* GetExtent() */
278 : /************************************************************************/
279 :
280 0 : OGRErr OGRNASLayer::GetExtent(OGREnvelope *psExtent, int bForce )
281 :
282 : {
283 : double dfXMin, dfXMax, dfYMin, dfYMax;
284 :
285 0 : if( poFClass != NULL &&
286 : poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ) )
287 : {
288 0 : psExtent->MinX = dfXMin;
289 0 : psExtent->MaxX = dfXMax;
290 0 : psExtent->MinY = dfYMin;
291 0 : psExtent->MaxY = dfYMax;
292 :
293 0 : return OGRERR_NONE;
294 : }
295 : else
296 0 : return OGRLayer::GetExtent( psExtent, bForce );
297 : }
298 :
299 : /************************************************************************/
300 : /* TestCapability() */
301 : /************************************************************************/
302 :
303 0 : int OGRNASLayer::TestCapability( const char * pszCap )
304 :
305 : {
306 0 : if( EQUAL(pszCap,OLCFastGetExtent) )
307 : {
308 : double dfXMin, dfXMax, dfYMin, dfYMax;
309 :
310 0 : if( poFClass == NULL )
311 0 : return FALSE;
312 :
313 0 : return poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax );
314 : }
315 :
316 0 : else if( EQUAL(pszCap,OLCFastFeatureCount) )
317 : {
318 0 : if( poFClass == NULL
319 : || m_poFilterGeom != NULL
320 : || m_poAttrQuery != NULL )
321 0 : return FALSE;
322 :
323 0 : return poFClass->GetFeatureCount() != -1;
324 : }
325 :
326 0 : else if( EQUAL(pszCap,OLCStringsAsUTF8) )
327 0 : return TRUE;
328 :
329 : else
330 0 : return FALSE;
331 : }
332 :
333 : /************************************************************************/
334 : /* GetSpatialRef() */
335 : /************************************************************************/
336 :
337 0 : OGRSpatialReference *OGRNASLayer::GetSpatialRef()
338 :
339 : {
340 0 : return poSRS;
341 : }
342 :
|