1 : /******************************************************************************
2 : * $Id: ogrvrtlayer.cpp 19643 2010-05-08 21:56:18Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRVRTLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2003, 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 "cpl_conv.h"
31 : #include "ogr_vrt.h"
32 : #include "cpl_string.h"
33 : #include <string>
34 :
35 : CPL_CVSID("$Id: ogrvrtlayer.cpp 19643 2010-05-08 21:56:18Z rouault $");
36 :
37 : typedef struct
38 : {
39 : OGRwkbGeometryType eType;
40 : const char *pszName;
41 : } OGRGeomTypeName;
42 :
43 : static const OGRGeomTypeName asGeomTypeNames[] = { /* 25D versions are implicit */
44 : { wkbUnknown, "wkbUnknown" },
45 : { wkbPoint, "wkbPoint" },
46 : { wkbLineString, "wkbLineString" },
47 : { wkbPolygon, "wkbPolygon" },
48 : { wkbMultiPoint, "wkbMultiPoint" },
49 : { wkbMultiLineString, "wkbMultiLineString" },
50 : { wkbMultiPolygon, "wkbMultiPolygon" },
51 : { wkbGeometryCollection, "wkbGeometryCollection" },
52 : { wkbNone, "wkbNone" },
53 : { wkbLinearRing, "wkbLinearRing" },
54 : { wkbNone, NULL }
55 : };
56 :
57 : /************************************************************************/
58 : /* OGRVRTLayer() */
59 : /************************************************************************/
60 :
61 18 : OGRVRTLayer::OGRVRTLayer()
62 :
63 : {
64 18 : poFeatureDefn = NULL;
65 18 : poSrcLayer = NULL;
66 18 : poSRS = NULL;
67 18 : poSrcDS = NULL;
68 :
69 18 : bUseSpatialSubquery = FALSE;
70 18 : iFIDField = -1;
71 18 : iStyleField = -1;
72 :
73 18 : eGeometryType = VGS_Direct;
74 18 : iGeomField = iGeomXField = iGeomYField = iGeomZField = -1;
75 :
76 18 : pszAttrFilter = NULL;
77 :
78 18 : bNeedReset = TRUE;
79 18 : bSrcLayerFromSQL = FALSE;
80 :
81 18 : bSrcClip = FALSE;
82 18 : poSrcRegion = NULL;
83 18 : bUpdate = FALSE;
84 18 : bAttrFilterPassThrough = FALSE;
85 18 : }
86 :
87 : /************************************************************************/
88 : /* ~OGRVRTLayer() */
89 : /************************************************************************/
90 :
91 18 : OGRVRTLayer::~OGRVRTLayer()
92 :
93 : {
94 18 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
95 : {
96 : CPLDebug( "VRT", "%d features read on layer '%s'.",
97 : (int) m_nFeaturesRead,
98 16 : poFeatureDefn->GetName() );
99 : }
100 :
101 18 : if( poSRS != NULL )
102 4 : poSRS->Release();
103 :
104 18 : if( poSrcDS != NULL )
105 : {
106 18 : if( bSrcLayerFromSQL && poSrcLayer )
107 2 : poSrcDS->ReleaseResultSet( poSrcLayer );
108 :
109 18 : if( bSrcDSShared )
110 3 : OGRSFDriverRegistrar::GetRegistrar()->ReleaseDataSource( poSrcDS );
111 : else
112 15 : delete poSrcDS;
113 : }
114 :
115 18 : if( poFeatureDefn )
116 18 : poFeatureDefn->Release();
117 :
118 18 : CPLFree( pszAttrFilter );
119 :
120 18 : if( poSrcRegion != NULL )
121 3 : delete poSrcRegion;
122 18 : }
123 :
124 : /************************************************************************/
125 : /* Initialize() */
126 : /************************************************************************/
127 :
128 : int OGRVRTLayer::Initialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
129 18 : int bUpdate)
130 :
131 : {
132 :
133 18 : if( !EQUAL(psLTree->pszValue,"OGRVRTLayer") )
134 0 : return FALSE;
135 :
136 : /* -------------------------------------------------------------------- */
137 : /* Get layer name. */
138 : /* -------------------------------------------------------------------- */
139 18 : const char *pszLayerName = CPLGetXMLValue( psLTree, "name", NULL );
140 :
141 18 : if( pszLayerName == NULL )
142 : {
143 : CPLError( CE_Failure, CPLE_AppDefined,
144 0 : "Missing name attribute on OGRVRTLayer" );
145 0 : return FALSE;
146 : }
147 :
148 18 : poFeatureDefn = new OGRFeatureDefn( pszLayerName );
149 18 : poFeatureDefn->Reference();
150 :
151 : /* -------------------------------------------------------------------- */
152 : /* Figure out the data source name. It may be treated relative */
153 : /* to vrt filename, but normally it is used directly. */
154 : /* -------------------------------------------------------------------- */
155 18 : OGRSFDriverRegistrar *poReg = OGRSFDriverRegistrar::GetRegistrar();
156 18 : char *pszSrcDSName = (char *) CPLGetXMLValue(psLTree,"SrcDataSource",NULL);
157 :
158 18 : if( pszSrcDSName == NULL )
159 : {
160 : CPLError( CE_Failure, CPLE_AppDefined,
161 0 : "Missing SrcDataSource for layer %s.", pszLayerName );
162 0 : return FALSE;
163 : }
164 :
165 18 : if( CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcDataSource.relativetoVRT",
166 : "0")) )
167 : {
168 : pszSrcDSName = CPLStrdup(
169 5 : CPLProjectRelativeFilename( pszVRTDirectory, pszSrcDSName ) );
170 : }
171 : else
172 : {
173 13 : pszSrcDSName = CPLStrdup(pszSrcDSName);
174 : }
175 :
176 : /* -------------------------------------------------------------------- */
177 : /* Are we accessing this datasource in shared mode? We default */
178 : /* to shared for SrcSQL requests, but we also allow the XML to */
179 : /* control our shared setting with an attribute on the */
180 : /* datasource element. */
181 : /* -------------------------------------------------------------------- */
182 : const char *pszSharedSetting = CPLGetXMLValue( psLTree,
183 : "SrcDataSource.shared",
184 18 : NULL );
185 18 : if( pszSharedSetting == NULL )
186 : {
187 17 : if( CPLGetXMLValue( psLTree, "SrcSQL", NULL ) == NULL )
188 15 : pszSharedSetting = "OFF";
189 : else
190 2 : pszSharedSetting = "ON";
191 : }
192 :
193 18 : bSrcDSShared = CSLTestBoolean( pszSharedSetting );
194 :
195 : // update mode doesn't make sense for a shared datasource or if we
196 : // have a SrcSQL element
197 18 : if (bSrcDSShared || CPLGetXMLValue( psLTree, "SrcSQL", NULL ) != NULL)
198 3 : bUpdate = FALSE;
199 :
200 : /* -------------------------------------------------------------------- */
201 : /* Try to access the datasource. */
202 : /* -------------------------------------------------------------------- */
203 18 : try_again:
204 18 : CPLErrorReset();
205 18 : if( EQUAL(pszSrcDSName,"@dummy@") )
206 : {
207 0 : OGRSFDriver *poMemDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("Memory");
208 0 : poSrcDS = poMemDriver->CreateDataSource( "@dummy@" );
209 0 : poSrcDS->CreateLayer( "@dummy@" );
210 : }
211 18 : else if( bSrcDSShared )
212 3 : poSrcDS = poReg->OpenShared( pszSrcDSName, bUpdate, NULL );
213 : else
214 15 : poSrcDS = poReg->Open( pszSrcDSName, bUpdate, NULL );
215 :
216 18 : if( poSrcDS == NULL )
217 : {
218 0 : if (bUpdate)
219 : {
220 : CPLError( CE_Warning, CPLE_AppDefined,
221 : "Cannot open datasource `%s' in update mode. Trying again in read-only mode",
222 0 : pszSrcDSName );
223 0 : bUpdate = FALSE;
224 0 : goto try_again;
225 : }
226 0 : if( strlen(CPLGetLastErrorMsg()) == 0 )
227 : CPLError( CE_Failure, CPLE_AppDefined,
228 : "Failed to open datasource `%s'.",
229 0 : pszSrcDSName );
230 0 : CPLFree( pszSrcDSName );
231 0 : return FALSE;
232 : }
233 :
234 18 : this->bUpdate = bUpdate;
235 :
236 : /* -------------------------------------------------------------------- */
237 : /* Is this layer derived from an SQL query result? */
238 : /* -------------------------------------------------------------------- */
239 18 : const char *pszSQL = CPLGetXMLValue( psLTree, "SrcSQL", NULL );
240 :
241 18 : if( pszSQL != NULL )
242 : {
243 2 : poSrcLayer = poSrcDS->ExecuteSQL( pszSQL, NULL, NULL );
244 2 : if( poSrcLayer == NULL )
245 : {
246 : CPLError( CE_Failure, CPLE_AppDefined,
247 : "SQL statement failed, or returned no layer result:\n%s",
248 0 : pszSQL );
249 0 : return FALSE;
250 : }
251 2 : bSrcLayerFromSQL = TRUE;
252 : }
253 :
254 : /* -------------------------------------------------------------------- */
255 : /* Fetch the layer if it is a regular layer. */
256 : /* -------------------------------------------------------------------- */
257 18 : if( poSrcLayer == NULL )
258 : {
259 : const char *pszSrcLayerName = CPLGetXMLValue( psLTree, "SrcLayer",
260 16 : pszLayerName );
261 :
262 16 : poSrcLayer = poSrcDS->GetLayerByName( pszSrcLayerName );
263 16 : if( poSrcLayer == NULL )
264 : {
265 : CPLError( CE_Failure, CPLE_AppDefined,
266 : "Failed to find layer '%s' on datasource '%s'.",
267 0 : pszSrcLayerName, pszSrcDSName );
268 0 : CPLFree( pszSrcDSName );
269 0 : return FALSE;
270 : }
271 : }
272 :
273 18 : CPLFree( pszSrcDSName );
274 :
275 : /* -------------------------------------------------------------------- */
276 : /* Do we have a fixed geometry type? If so use it, otherwise */
277 : /* derive from the source layer. */
278 : /* -------------------------------------------------------------------- */
279 18 : const char *pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
280 :
281 18 : if( pszGType != NULL )
282 : {
283 : int iType;
284 :
285 20 : for( iType = 0; asGeomTypeNames[iType].pszName != NULL; iType++ )
286 : {
287 20 : if( EQUALN(pszGType, asGeomTypeNames[iType].pszName,
288 : strlen(asGeomTypeNames[iType].pszName)) )
289 : {
290 7 : poFeatureDefn->SetGeomType( asGeomTypeNames[iType].eType );
291 :
292 7 : if( strstr(pszGType,"25D") != NULL )
293 : poFeatureDefn->SetGeomType(
294 : (OGRwkbGeometryType)
295 0 : (poFeatureDefn->GetGeomType() | wkb25DBit) );
296 7 : break;
297 : }
298 : }
299 :
300 7 : if( asGeomTypeNames[iType].pszName == NULL )
301 : {
302 : CPLError( CE_Failure, CPLE_AppDefined,
303 : "GeometryType %s not recognised.",
304 0 : pszGType );
305 0 : return FALSE;
306 : }
307 : }
308 :
309 : else
310 : {
311 11 : poFeatureDefn->SetGeomType(poSrcLayer->GetLayerDefn()->GetGeomType());
312 : }
313 :
314 : /* -------------------------------------------------------------------- */
315 : /* Apply a spatial reference system if provided, otherwise copy */
316 : /* from source. */
317 : /* -------------------------------------------------------------------- */
318 18 : const char *pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
319 :
320 18 : if( pszLayerSRS != NULL )
321 : {
322 4 : if( EQUAL(pszLayerSRS,"NULL") )
323 0 : poSRS = NULL;
324 : else
325 : {
326 4 : OGRSpatialReference oSRS;
327 :
328 4 : if( oSRS.SetFromUserInput( pszLayerSRS ) != OGRERR_NONE )
329 : {
330 : CPLError( CE_Failure, CPLE_AppDefined,
331 0 : "Failed to import LayerSRS `%s'.", pszLayerSRS );
332 0 : return FALSE;
333 : }
334 4 : poSRS = oSRS.Clone();
335 : }
336 : }
337 :
338 : else
339 : {
340 14 : if( poSrcLayer->GetSpatialRef() != NULL )
341 0 : poSRS = poSrcLayer->GetSpatialRef()->Clone();
342 : else
343 14 : poSRS = NULL;
344 : }
345 :
346 : /* -------------------------------------------------------------------- */
347 : /* Handle GeometryField. */
348 : /* -------------------------------------------------------------------- */
349 : const char *pszEncoding;
350 :
351 18 : pszEncoding = CPLGetXMLValue( psLTree,"GeometryField.encoding", "direct");
352 :
353 18 : if( EQUAL(pszEncoding,"Direct") )
354 5 : eGeometryType = VGS_Direct;
355 13 : else if( EQUAL(pszEncoding,"None") )
356 0 : eGeometryType = VGS_None;
357 13 : else if( EQUAL(pszEncoding,"WKT") )
358 7 : eGeometryType = VGS_WKT;
359 6 : else if( EQUAL(pszEncoding,"WKB") )
360 1 : eGeometryType = VGS_WKB;
361 5 : else if( EQUAL(pszEncoding,"Shape") )
362 0 : eGeometryType = VGS_Shape;
363 5 : else if( EQUAL(pszEncoding,"PointFromColumns") )
364 : {
365 5 : eGeometryType = VGS_PointFromColumns;
366 : bUseSpatialSubquery =
367 : CSLTestBoolean(
368 : CPLGetXMLValue(psLTree,
369 : "GeometryField.useSpatialSubquery",
370 5 : "TRUE"));
371 :
372 : iGeomXField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
373 5 : CPLGetXMLValue( psLTree, "GeometryField.x", "missing" ) );
374 : iGeomYField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
375 5 : CPLGetXMLValue( psLTree, "GeometryField.y", "missing" ) );
376 : iGeomZField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
377 5 : CPLGetXMLValue( psLTree, "GeometryField.z", "missing" ) );
378 :
379 5 : if( iGeomXField == -1 || iGeomYField == -1 )
380 : {
381 : CPLError( CE_Failure, CPLE_AppDefined,
382 0 : "Unable to identify source X or Y field for PointFromColumns encoding." );
383 0 : return FALSE;
384 : }
385 : }
386 : else
387 : {
388 : CPLError( CE_Failure, CPLE_AppDefined,
389 0 : "encoding=\"%s\" not recognised.", pszEncoding );
390 0 : return FALSE;
391 : }
392 :
393 18 : if( eGeometryType == VGS_WKT
394 : || eGeometryType == VGS_WKB
395 : || eGeometryType == VGS_Shape )
396 : {
397 : const char *pszFieldName =
398 8 : CPLGetXMLValue( psLTree, "GeometryField.field", "missing" );
399 :
400 8 : iGeomField = poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFieldName);
401 :
402 8 : if( iGeomField == -1 )
403 : {
404 : CPLError( CE_Failure, CPLE_AppDefined,
405 : "Unable to identify source field '%s' for geometry.",
406 0 : pszFieldName );
407 0 : return FALSE;
408 : }
409 : }
410 :
411 : /* -------------------------------------------------------------------- */
412 : /* Figure out what should be used as an FID. */
413 : /* -------------------------------------------------------------------- */
414 18 : const char *pszFIDFieldName = CPLGetXMLValue( psLTree, "FID", NULL );
415 :
416 18 : if( pszFIDFieldName != NULL )
417 : {
418 : iFIDField =
419 3 : poSrcLayer->GetLayerDefn()->GetFieldIndex( pszFIDFieldName );
420 3 : if( iFIDField == -1 )
421 : {
422 : CPLError( CE_Failure, CPLE_AppDefined,
423 : "Unable to identify FID field '%s'.",
424 0 : pszFIDFieldName );
425 0 : return FALSE;
426 : }
427 : }
428 :
429 : /* -------------------------------------------------------------------- */
430 : /* Figure out what should be used as a Style */
431 : /* -------------------------------------------------------------------- */
432 18 : const char *pszStyleFieldName = CPLGetXMLValue( psLTree, "Style", NULL );
433 :
434 18 : if( pszStyleFieldName != NULL )
435 : {
436 : iStyleField =
437 0 : poSrcLayer->GetLayerDefn()->GetFieldIndex( pszStyleFieldName );
438 0 : if( iStyleField == -1 )
439 : {
440 : CPLError( CE_Failure, CPLE_AppDefined,
441 : "Unable to identify Style field '%s'.",
442 0 : pszStyleFieldName );
443 0 : return FALSE;
444 : }
445 : }
446 :
447 : /* ==================================================================== */
448 : /* Search for schema definitions in the VRT. */
449 : /* ==================================================================== */
450 : CPLXMLNode *psChild;
451 108 : for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
452 : {
453 90 : if( psChild->eType == CXT_Element && EQUAL(psChild->pszValue,"Field") )
454 : {
455 : /* -------------------------------------------------------------------- */
456 : /* Field name. */
457 : /* -------------------------------------------------------------------- */
458 6 : const char *pszName = CPLGetXMLValue( psChild, "name", NULL );
459 6 : if( pszName == NULL )
460 : {
461 : CPLError( CE_Failure, CPLE_AppDefined,
462 0 : "Unable to identify Field name." );
463 0 : return FALSE;
464 : }
465 :
466 6 : OGRFieldDefn oFieldDefn( pszName, OFTString );
467 :
468 : /* -------------------------------------------------------------------- */
469 : /* Type */
470 : /* -------------------------------------------------------------------- */
471 6 : const char *pszArg = CPLGetXMLValue( psChild, "type", NULL );
472 :
473 6 : if( pszArg != NULL )
474 : {
475 : int iType;
476 :
477 8 : for( iType = 0; iType <= (int) OFTMaxType; iType++ )
478 : {
479 8 : if( EQUAL(pszArg,OGRFieldDefn::GetFieldTypeName(
480 : (OGRFieldType)iType)) )
481 : {
482 4 : oFieldDefn.SetType( (OGRFieldType) iType );
483 4 : break;
484 : }
485 : }
486 :
487 4 : if( iType > (int) OFTMaxType )
488 : {
489 : CPLError( CE_Failure, CPLE_AppDefined,
490 : "Unable to identify Field type '%s'.",
491 0 : pszArg );
492 0 : return FALSE;
493 : }
494 : }
495 :
496 : /* -------------------------------------------------------------------- */
497 : /* Width and precision. */
498 : /* -------------------------------------------------------------------- */
499 : oFieldDefn.SetWidth(
500 6 : atoi(CPLGetXMLValue( psChild, "width", "0" )) );
501 : oFieldDefn.SetPrecision(
502 6 : atoi(CPLGetXMLValue( psChild, "precision", "0" )) );
503 :
504 : /* -------------------------------------------------------------------- */
505 : /* Create the field. */
506 : /* -------------------------------------------------------------------- */
507 6 : poFeatureDefn->AddFieldDefn( &oFieldDefn );
508 :
509 6 : abDirectCopy.push_back( FALSE );
510 :
511 : /* -------------------------------------------------------------------- */
512 : /* Source field. */
513 : /* -------------------------------------------------------------------- */
514 : int iSrcField =
515 6 : poSrcLayer->GetLayerDefn()->GetFieldIndex( pszName );
516 :
517 6 : pszArg = CPLGetXMLValue( psChild, "src", NULL );
518 :
519 6 : if( pszArg != NULL )
520 : {
521 : iSrcField =
522 2 : poSrcLayer->GetLayerDefn()->GetFieldIndex( pszArg );
523 2 : if( iSrcField == -1 )
524 : {
525 : CPLError( CE_Failure, CPLE_AppDefined,
526 : "Unable to find source field '%s'.",
527 0 : pszArg );
528 0 : return FALSE;
529 : }
530 : }
531 :
532 6 : anSrcField.push_back( iSrcField );
533 : }
534 : }
535 :
536 18 : CPLAssert( poFeatureDefn->GetFieldCount() == (int) anSrcField.size() );
537 :
538 : /* -------------------------------------------------------------------- */
539 : /* Create the schema, if it was not explicitly in the VRT. */
540 : /* -------------------------------------------------------------------- */
541 18 : if( poFeatureDefn->GetFieldCount() == 0 )
542 : {
543 : int bReportSrcColumn =
544 16 : CSLTestBoolean(CPLGetXMLValue( psLTree, "GeometryField.reportSrcColumn", "YES" ));
545 :
546 : int iSrcField;
547 : int iDstField;
548 16 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
549 16 : int nSrcFieldCount = poSrcDefn->GetFieldCount();
550 16 : int nDstFieldCount = nSrcFieldCount;
551 16 : if (bReportSrcColumn == FALSE)
552 : {
553 2 : if (iGeomXField != -1) nDstFieldCount --;
554 2 : if (iGeomYField != -1) nDstFieldCount --;
555 2 : if (iGeomZField != -1) nDstFieldCount --;
556 2 : if (iGeomField != -1) nDstFieldCount --;
557 : }
558 :
559 71 : for( iSrcField = 0, iDstField = 0; iSrcField < nSrcFieldCount; iSrcField++ )
560 : {
561 55 : if (bReportSrcColumn == FALSE &&
562 : (iSrcField == iGeomXField || iSrcField == iGeomYField ||
563 : iSrcField == iGeomZField || iSrcField == iGeomField))
564 4 : continue;
565 :
566 51 : poFeatureDefn->AddFieldDefn( poSrcDefn->GetFieldDefn( iSrcField ) );
567 51 : anSrcField.push_back( iSrcField );
568 51 : abDirectCopy.push_back( TRUE );
569 51 : iDstField++;
570 : }
571 16 : bAttrFilterPassThrough = TRUE;
572 : }
573 :
574 : /* -------------------------------------------------------------------- */
575 : /* Allow vrt to override whether attribute filters should be */
576 : /* passed through. */
577 : /* -------------------------------------------------------------------- */
578 18 : if( CPLGetXMLValue( psLTree, "attrFilterPassThrough", NULL ) != NULL )
579 : bAttrFilterPassThrough =
580 : CSLTestBoolean(
581 : CPLGetXMLValue(psLTree, "attrFilterPassThrough",
582 0 : "TRUE") );
583 :
584 : /* -------------------------------------------------------------------- */
585 : /* Do we have a SrcRegion? */
586 : /* -------------------------------------------------------------------- */
587 18 : const char *pszSrcRegion = CPLGetXMLValue( psLTree, "SrcRegion", NULL );
588 18 : if( pszSrcRegion != NULL )
589 : {
590 3 : OGRGeometryFactory::createFromWkt( (char**) &pszSrcRegion, NULL, &poSrcRegion );
591 3 : if( poSrcRegion == NULL || wkbFlatten(poSrcRegion->getGeometryType()) != wkbPolygon)
592 : {
593 : CPLError(CE_Warning, CPLE_AppDefined,
594 0 : "Ignoring SrcRegion. It must be a valid WKT polygon");
595 0 : delete poSrcRegion;
596 0 : poSrcRegion = NULL;
597 : }
598 :
599 3 : bSrcClip = CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcRegion.clip", "FALSE" ));
600 : }
601 :
602 18 : return TRUE;
603 : }
604 :
605 : /************************************************************************/
606 : /* ResetReading() */
607 : /************************************************************************/
608 :
609 57 : void OGRVRTLayer::ResetReading()
610 :
611 : {
612 57 : bNeedReset = TRUE;
613 57 : }
614 :
615 : /************************************************************************/
616 : /* ResetSourceReading() */
617 : /************************************************************************/
618 :
619 34 : int OGRVRTLayer::ResetSourceReading()
620 :
621 : {
622 34 : int bSuccess = TRUE;
623 :
624 : /* -------------------------------------------------------------------- */
625 : /* Do we want to let source layer do spatial restriction? */
626 : /* -------------------------------------------------------------------- */
627 34 : char *pszFilter = NULL;
628 34 : if( (m_poFilterGeom || poSrcRegion) && bUseSpatialSubquery &&
629 : eGeometryType == VGS_PointFromColumns )
630 : {
631 : const char *pszXField, *pszYField;
632 :
633 7 : pszXField = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomXField)->GetNameRef();
634 7 : pszYField = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomYField)->GetNameRef();
635 7 : if (bUseSpatialSubquery)
636 : {
637 7 : OGRFieldType xType = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomXField)->GetType();
638 7 : OGRFieldType yType = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomYField)->GetType();
639 7 : if (!((xType == OFTReal || xType == OFTInteger) && (yType == OFTReal || yType == OFTInteger)))
640 : {
641 : CPLError(CE_Warning, CPLE_AppDefined,
642 : "The '%s' and/or '%s' fields of the source layer are not declared as numeric fields,\n"
643 : "so the spatial filter cannot be turned into an attribute filter on them",
644 1 : pszXField, pszYField);
645 1 : bUseSpatialSubquery = FALSE;
646 : }
647 : }
648 7 : if (bUseSpatialSubquery)
649 : {
650 6 : OGREnvelope sEnvelope;
651 :
652 : pszFilter = (char *)
653 6 : CPLMalloc(2*strlen(pszXField)+2*strlen(pszYField) + 100);
654 :
655 6 : if (poSrcRegion != NULL)
656 : {
657 5 : if (m_poFilterGeom == NULL)
658 3 : poSrcRegion->getEnvelope( &sEnvelope );
659 : else
660 : {
661 2 : OGRGeometry* poIntersection = poSrcRegion->Intersection(m_poFilterGeom);
662 2 : if (poIntersection)
663 : {
664 2 : poIntersection->getEnvelope( &sEnvelope );
665 2 : delete poIntersection;
666 : }
667 : else
668 : {
669 0 : sEnvelope.MinX = 0;
670 0 : sEnvelope.MaxX = 0;
671 0 : sEnvelope.MinY = 0;
672 0 : sEnvelope.MaxY = 0;
673 : }
674 : }
675 : }
676 : else
677 1 : m_poFilterGeom->getEnvelope( &sEnvelope );
678 :
679 : sprintf( pszFilter,
680 : "%s > %.15g AND %s < %.15g AND %s > %.15g AND %s < %.15g",
681 : pszXField, sEnvelope.MinX,
682 : pszXField, sEnvelope.MaxX,
683 : pszYField, sEnvelope.MinY,
684 6 : pszYField, sEnvelope.MaxY );
685 : char* pszComma;
686 12 : while((pszComma = strchr(pszFilter, ',')) != NULL)
687 0 : *pszComma = '.';
688 : }
689 : }
690 :
691 : /* -------------------------------------------------------------------- */
692 : /* Install spatial + attr filter query on source layer. */
693 : /* -------------------------------------------------------------------- */
694 59 : if( pszFilter == NULL && pszAttrFilter == NULL )
695 25 : bSuccess = (poSrcLayer->SetAttributeFilter( NULL ) == CE_None);
696 :
697 15 : else if( pszFilter != NULL && pszAttrFilter == NULL )
698 6 : bSuccess = (poSrcLayer->SetAttributeFilter( pszFilter ) == CE_None);
699 :
700 6 : else if( pszFilter == NULL && pszAttrFilter != NULL )
701 3 : bSuccess = (poSrcLayer->SetAttributeFilter( pszAttrFilter ) == CE_None);
702 :
703 : else
704 : {
705 0 : CPLString osMerged = pszFilter;
706 :
707 0 : osMerged += " AND ";
708 0 : osMerged += pszAttrFilter;
709 :
710 0 : bSuccess = (poSrcLayer->SetAttributeFilter(osMerged) == CE_None);
711 : }
712 :
713 34 : CPLFree( pszFilter );
714 :
715 : /* -------------------------------------------------------------------- */
716 : /* Clear spatial filter (to be safe) for non direct geometries */
717 : /* and reset reading. */
718 : /* -------------------------------------------------------------------- */
719 34 : if (eGeometryType == VGS_Direct)
720 : {
721 6 : if (poSrcRegion == NULL)
722 2 : poSrcLayer->SetSpatialFilter( m_poFilterGeom );
723 4 : else if (m_poFilterGeom == NULL)
724 2 : poSrcLayer->SetSpatialFilter( poSrcRegion );
725 : else
726 : {
727 2 : if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
728 : {
729 : CPLError(CE_Failure, CPLE_AppDefined,
730 0 : "Spatial filter should be polygon when a SrcRegion is defined. Ignoring it");
731 0 : poSrcLayer->SetSpatialFilter( poSrcRegion );
732 : }
733 : else
734 : {
735 2 : OGRGeometry* poIntersection = m_poFilterGeom->Intersection(poSrcRegion);
736 2 : poSrcLayer->SetSpatialFilter( poIntersection );
737 2 : delete poIntersection;
738 : }
739 : }
740 : }
741 : else
742 28 : poSrcLayer->SetSpatialFilter( NULL );
743 34 : poSrcLayer->ResetReading();
744 34 : bNeedReset = FALSE;
745 :
746 34 : return bSuccess;
747 : }
748 :
749 : /************************************************************************/
750 : /* GetNextFeature() */
751 : /************************************************************************/
752 :
753 56 : OGRFeature *OGRVRTLayer::GetNextFeature()
754 :
755 : {
756 56 : if( bNeedReset )
757 : {
758 30 : if( !ResetSourceReading() )
759 0 : return NULL;
760 : }
761 :
762 7 : for( ; TRUE; )
763 : {
764 : OGRFeature *poSrcFeature, *poFeature;
765 :
766 63 : poSrcFeature = poSrcLayer->GetNextFeature();
767 63 : if( poSrcFeature == NULL )
768 15 : return NULL;
769 :
770 48 : poFeature = TranslateFeature( poSrcFeature, TRUE );
771 48 : delete poSrcFeature;
772 :
773 48 : if( poFeature == NULL )
774 4 : return NULL;
775 :
776 44 : if( (eGeometryType == VGS_Direct || m_poFilterGeom == NULL
777 : || FilterGeometry( poFeature->GetGeometryRef() ) )
778 : && (m_poAttrQuery == NULL
779 : || m_poAttrQuery->Evaluate( poFeature )) )
780 37 : return poFeature;
781 :
782 7 : delete poFeature;
783 : }
784 : }
785 :
786 : /************************************************************************/
787 : /* TranslateFeature() */
788 : /* */
789 : /* Translate a source feature into a feature for this layer. */
790 : /************************************************************************/
791 :
792 62 : OGRFeature *OGRVRTLayer::TranslateFeature( OGRFeature*& poSrcFeat, int bUseSrcRegion )
793 :
794 : {
795 62 : retry:
796 62 : OGRFeature *poDstFeat = new OGRFeature( poFeatureDefn );
797 :
798 62 : m_nFeaturesRead++;
799 :
800 : /* -------------------------------------------------------------------- */
801 : /* Handle FID. */
802 : /* -------------------------------------------------------------------- */
803 62 : if( iFIDField == -1 )
804 42 : poDstFeat->SetFID( poSrcFeat->GetFID() );
805 : else
806 20 : poDstFeat->SetFID( poSrcFeat->GetFieldAsInteger( iFIDField ) );
807 :
808 : /* -------------------------------------------------------------------- */
809 : /* Handle style string. */
810 : /* -------------------------------------------------------------------- */
811 62 : if( iStyleField != -1 )
812 : {
813 0 : if( poSrcFeat->IsFieldSet(iStyleField) )
814 : poDstFeat->SetStyleString(
815 0 : poSrcFeat->GetFieldAsString(iStyleField) );
816 : }
817 : else
818 : {
819 62 : if( poSrcFeat->GetStyleString() != NULL )
820 0 : poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
821 : }
822 :
823 : /* -------------------------------------------------------------------- */
824 : /* Handle the geometry. Eventually there will be several more */
825 : /* supported options. */
826 : /* -------------------------------------------------------------------- */
827 62 : if( eGeometryType == VGS_None )
828 : {
829 : /* do nothing */
830 : }
831 62 : else if( eGeometryType == VGS_WKT )
832 : {
833 39 : char *pszWKT = (char *) poSrcFeat->GetFieldAsString( iGeomField );
834 :
835 39 : if( pszWKT != NULL )
836 : {
837 39 : OGRGeometry *poGeom = NULL;
838 :
839 39 : OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom );
840 39 : if( poGeom == NULL )
841 : CPLDebug( "OGR_VRT", "Did not get geometry from %s",
842 0 : pszWKT );
843 :
844 39 : poDstFeat->SetGeometryDirectly( poGeom );
845 : }
846 : }
847 23 : else if( eGeometryType == VGS_WKB )
848 : {
849 : int nBytes;
850 : GByte *pabyWKB;
851 1 : int bNeedFree = FALSE;
852 :
853 1 : if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
854 : {
855 0 : pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
856 : }
857 : else
858 : {
859 1 : const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
860 :
861 1 : pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
862 1 : bNeedFree = TRUE;
863 : }
864 :
865 1 : if( pabyWKB != NULL )
866 : {
867 1 : OGRGeometry *poGeom = NULL;
868 :
869 1 : if( OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeom,
870 : nBytes ) == OGRERR_NONE )
871 1 : poDstFeat->SetGeometryDirectly( poGeom );
872 : }
873 :
874 1 : if( bNeedFree )
875 1 : CPLFree( pabyWKB );
876 : }
877 22 : else if( eGeometryType == VGS_Shape )
878 : {
879 : int nBytes;
880 : GByte *pabyWKB;
881 0 : int bNeedFree = FALSE;
882 :
883 0 : if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
884 : {
885 0 : pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
886 : }
887 : else
888 : {
889 0 : const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
890 :
891 0 : pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
892 0 : bNeedFree = TRUE;
893 : }
894 :
895 0 : if( pabyWKB != NULL )
896 : {
897 0 : OGRGeometry *poGeom = NULL;
898 :
899 0 : if( createFromShapeBin( pabyWKB, &poGeom, nBytes ) == OGRERR_NONE )
900 0 : poDstFeat->SetGeometryDirectly( poGeom );
901 : }
902 :
903 0 : if( bNeedFree )
904 0 : CPLFree( pabyWKB );
905 : }
906 22 : else if( eGeometryType == VGS_Direct )
907 : {
908 6 : poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
909 : }
910 16 : else if( eGeometryType == VGS_PointFromColumns )
911 : {
912 16 : if( iGeomZField != -1 )
913 : poDstFeat->SetGeometryDirectly(
914 : new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
915 : poSrcFeat->GetFieldAsDouble( iGeomYField ),
916 8 : poSrcFeat->GetFieldAsDouble( iGeomZField ) ) );
917 : else
918 : poDstFeat->SetGeometryDirectly(
919 : new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
920 8 : poSrcFeat->GetFieldAsDouble( iGeomYField ) ) );
921 : }
922 : else
923 : /* add other options here. */;
924 :
925 : /* In the non direct case, we need to check that the geometry intersects the source */
926 : /* region before an optionnal clipping */
927 62 : if( bUseSrcRegion && eGeometryType != VGS_Direct && poSrcRegion != NULL )
928 : {
929 23 : OGRGeometry* poGeom = poDstFeat->GetGeometryRef();
930 23 : if (poGeom != NULL && !poGeom->Intersects(poSrcRegion))
931 : {
932 14 : delete poSrcFeat;
933 14 : delete poDstFeat;
934 :
935 : /* Fetch next source feature and retry translating it */
936 14 : poSrcFeat = poSrcLayer->GetNextFeature();
937 14 : if (poSrcFeat == NULL)
938 4 : return NULL;
939 :
940 10 : goto retry;
941 : }
942 : }
943 :
944 : /* Clip the geometry to the SrcRegion if asked */
945 48 : if (poSrcRegion != NULL && bSrcClip && poDstFeat->GetGeometryRef() != NULL)
946 : {
947 0 : OGRGeometry* poClippedGeom = poDstFeat->GetGeometryRef()->Intersection(poSrcRegion);
948 0 : poDstFeat->SetGeometryDirectly(poClippedGeom);
949 : }
950 :
951 48 : if (poDstFeat->GetGeometryRef() != NULL && poSRS != NULL)
952 15 : poDstFeat->GetGeometryRef()->assignSpatialReference(poSRS);
953 :
954 : /* -------------------------------------------------------------------- */
955 : /* Copy fields. */
956 : /* -------------------------------------------------------------------- */
957 : int iVRTField;
958 :
959 259 : for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
960 : {
961 211 : if( anSrcField[iVRTField] == -1 )
962 5 : continue;
963 :
964 206 : OGRFieldDefn *poDstDefn = poFeatureDefn->GetFieldDefn( iVRTField );
965 206 : OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
966 :
967 206 : if( abDirectCopy[iVRTField]
968 : && poDstDefn->GetType() == poSrcDefn->GetType() )
969 : {
970 : poDstFeat->SetField( iVRTField,
971 196 : poSrcFeat->GetRawFieldRef( anSrcField[iVRTField] ) );
972 : }
973 : else
974 : {
975 : /* Eventually we need to offer some more sophisticated translation
976 : options here for more esoteric types. */
977 10 : if (poDstDefn->GetType() == OFTReal)
978 : poDstFeat->SetField( iVRTField,
979 0 : poSrcFeat->GetFieldAsDouble(anSrcField[iVRTField]));
980 : else
981 : poDstFeat->SetField( iVRTField,
982 10 : poSrcFeat->GetFieldAsString(anSrcField[iVRTField]));
983 : }
984 : }
985 :
986 48 : return poDstFeat;
987 : }
988 :
989 :
990 : /************************************************************************/
991 : /* GetFeature() */
992 : /************************************************************************/
993 :
994 4 : OGRFeature *OGRVRTLayer::GetFeature( long nFeatureId )
995 :
996 : {
997 4 : bNeedReset = TRUE;
998 :
999 : /* -------------------------------------------------------------------- */
1000 : /* If the FID is directly mapped, we can do a simple */
1001 : /* GetFeature() to get our target feature. Otherwise we need */
1002 : /* to setup an appropriate query to get it. */
1003 : /* -------------------------------------------------------------------- */
1004 : OGRFeature *poSrcFeature, *poFeature;
1005 :
1006 4 : if( iFIDField == -1 )
1007 : {
1008 3 : poSrcFeature = poSrcLayer->GetFeature( nFeatureId );
1009 : }
1010 : else
1011 : {
1012 1 : const char* pszFID = poSrcLayer->GetLayerDefn()->GetFieldDefn(iFIDField)->GetNameRef();
1013 1 : char* pszFIDQuery = (char*)CPLMalloc(strlen(pszFID) + 64);
1014 :
1015 1 : poSrcLayer->ResetReading();
1016 1 : sprintf( pszFIDQuery, "%s = %ld", pszFID, nFeatureId );
1017 1 : poSrcLayer->SetSpatialFilter( NULL );
1018 1 : poSrcLayer->SetAttributeFilter( pszFIDQuery );
1019 1 : CPLFree(pszFIDQuery);
1020 :
1021 1 : poSrcFeature = poSrcLayer->GetNextFeature();
1022 : }
1023 :
1024 4 : if( poSrcFeature == NULL )
1025 0 : return NULL;
1026 :
1027 : /* -------------------------------------------------------------------- */
1028 : /* Translate feature and return it. */
1029 : /* -------------------------------------------------------------------- */
1030 4 : poFeature = TranslateFeature( poSrcFeature, FALSE );
1031 4 : delete poSrcFeature;
1032 :
1033 4 : return poFeature;
1034 : }
1035 :
1036 : /************************************************************************/
1037 : /* SetNextByIndex() */
1038 : /************************************************************************/
1039 :
1040 0 : OGRErr OGRVRTLayer::SetNextByIndex( long nIndex )
1041 : {
1042 0 : if (TestCapability(OLCFastSetNextByIndex))
1043 0 : return poSrcLayer->SetNextByIndex(nIndex);
1044 :
1045 0 : return OGRLayer::SetNextByIndex(nIndex);
1046 : }
1047 :
1048 : /************************************************************************/
1049 : /* TranslateVRTFeatureToSrcFeature() */
1050 : /* */
1051 : /* Translate a VRT feature into a feature for the source layer */
1052 : /************************************************************************/
1053 :
1054 3 : OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeature)
1055 : {
1056 3 : OGRFeature *poSrcFeat = new OGRFeature( poSrcLayer->GetLayerDefn() );
1057 :
1058 3 : poSrcFeat->SetFID( poVRTFeature->GetFID() );
1059 :
1060 : /* -------------------------------------------------------------------- */
1061 : /* Handle style string. */
1062 : /* -------------------------------------------------------------------- */
1063 3 : if( iStyleField != -1 )
1064 : {
1065 0 : if( poVRTFeature->GetStyleString() != NULL )
1066 0 : poSrcFeat->SetField( iStyleField, poVRTFeature->GetStyleString() );
1067 : }
1068 : else
1069 : {
1070 3 : if( poVRTFeature->GetStyleString() != NULL )
1071 0 : poSrcFeat->SetStyleString(poVRTFeature->GetStyleString());
1072 : }
1073 :
1074 : /* -------------------------------------------------------------------- */
1075 : /* Handle the geometry. Eventually there will be several more */
1076 : /* supported options. */
1077 : /* -------------------------------------------------------------------- */
1078 3 : if( eGeometryType == VGS_None )
1079 : {
1080 : /* do nothing */
1081 : }
1082 3 : else if( eGeometryType == VGS_WKT )
1083 : {
1084 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1085 1 : if (poGeom != NULL)
1086 : {
1087 1 : char* pszWKT = NULL;
1088 1 : if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
1089 : {
1090 1 : poSrcFeat->SetField(iGeomField, pszWKT);
1091 : }
1092 1 : CPLFree(pszWKT);
1093 : }
1094 : }
1095 2 : else if( eGeometryType == VGS_WKB )
1096 : {
1097 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1098 1 : if (poGeom != NULL)
1099 : {
1100 1 : int nSize = poGeom->WkbSize();
1101 1 : GByte* pabyData = (GByte*)CPLMalloc(nSize);
1102 1 : if (poGeom->exportToWkb(wkbNDR, pabyData) == OGRERR_NONE)
1103 : {
1104 1 : if ( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
1105 : {
1106 0 : poSrcFeat->SetField(iGeomField, nSize, pabyData);
1107 : }
1108 : else
1109 : {
1110 1 : char* pszHexWKB = CPLBinaryToHex(nSize, pabyData);
1111 1 : poSrcFeat->SetField(iGeomField, pszHexWKB);
1112 1 : CPLFree(pszHexWKB);
1113 : }
1114 : }
1115 1 : CPLFree(pabyData);
1116 : }
1117 : }
1118 1 : else if( eGeometryType == VGS_Shape )
1119 : {
1120 0 : CPLDebug("OGR_VRT", "Update of VGS_Shape geometries not supported");
1121 : }
1122 1 : else if( eGeometryType == VGS_Direct )
1123 : {
1124 0 : poSrcFeat->SetGeometry( poVRTFeature->GetGeometryRef() );
1125 : }
1126 1 : else if( eGeometryType == VGS_PointFromColumns )
1127 : {
1128 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1129 1 : if (poGeom != NULL)
1130 : {
1131 1 : if (wkbFlatten(poGeom->getGeometryType()) != wkbPoint)
1132 : {
1133 : CPLError(CE_Warning, CPLE_NotSupported,
1134 0 : "Cannot set a non ponctual geometry for PointFromColumns geometry");
1135 : }
1136 : else
1137 : {
1138 1 : poSrcFeat->SetField( iGeomXField, ((OGRPoint*)poGeom)->getX() );
1139 1 : poSrcFeat->SetField( iGeomYField, ((OGRPoint*)poGeom)->getY() );
1140 1 : if( iGeomZField != -1 )
1141 : {
1142 0 : poSrcFeat->SetField( iGeomZField, ((OGRPoint*)poGeom)->getZ() );
1143 : }
1144 : }
1145 : }
1146 : }
1147 : else
1148 : /* add other options here. */;
1149 :
1150 3 : if (poSrcFeat->GetGeometryRef() != NULL && poSRS != NULL)
1151 0 : poSrcFeat->GetGeometryRef()->assignSpatialReference(poSRS);
1152 :
1153 : /* -------------------------------------------------------------------- */
1154 : /* Copy fields. */
1155 : /* -------------------------------------------------------------------- */
1156 :
1157 : int iVRTField;
1158 :
1159 11 : for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
1160 : {
1161 : /* Do not set source geometry columns. Have been set just above */
1162 8 : if (anSrcField[iVRTField] == iGeomField || anSrcField[iVRTField] == iGeomXField ||
1163 : anSrcField[iVRTField] == iGeomYField || anSrcField[iVRTField] == iGeomZField)
1164 2 : continue;
1165 :
1166 6 : OGRFieldDefn *poVRTDefn = poFeatureDefn->GetFieldDefn( iVRTField );
1167 6 : OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
1168 :
1169 6 : if( abDirectCopy[iVRTField]
1170 : && poVRTDefn->GetType() == poSrcDefn->GetType() )
1171 : {
1172 : poSrcFeat->SetField( anSrcField[iVRTField],
1173 6 : poVRTFeature->GetRawFieldRef( iVRTField ) );
1174 : }
1175 : else
1176 : {
1177 : /* Eventually we need to offer some more sophisticated translation
1178 : options here for more esoteric types. */
1179 : poSrcFeat->SetField( anSrcField[iVRTField],
1180 0 : poVRTFeature->GetFieldAsString(iVRTField));
1181 : }
1182 : }
1183 :
1184 3 : return poSrcFeat;
1185 : }
1186 :
1187 : /************************************************************************/
1188 : /* CreateFeature() */
1189 : /************************************************************************/
1190 :
1191 3 : OGRErr OGRVRTLayer::CreateFeature( OGRFeature* poVRTFeature )
1192 : {
1193 3 : if(!bUpdate)
1194 : {
1195 : CPLError( CE_Failure, CPLE_AppDefined,
1196 0 : "The CreateFeature() operation is not permitted on a read-only VRT." );
1197 0 : return OGRERR_FAILURE;
1198 : }
1199 :
1200 3 : if( iFIDField != -1 )
1201 : {
1202 : CPLError( CE_Failure, CPLE_AppDefined,
1203 0 : "The CreateFeature() operation is not supported if the FID option is specified." );
1204 0 : return OGRERR_FAILURE;
1205 : }
1206 :
1207 3 : OGRFeature* poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
1208 3 : poSrcFeature->SetFID(OGRNullFID);
1209 3 : OGRErr eErr = poSrcLayer->CreateFeature(poSrcFeature);
1210 3 : if (eErr == OGRERR_NONE)
1211 : {
1212 3 : poVRTFeature->SetFID(poSrcFeature->GetFID());
1213 : }
1214 3 : delete poSrcFeature;
1215 3 : return eErr;
1216 : }
1217 :
1218 : /************************************************************************/
1219 : /* SetFeature() */
1220 : /************************************************************************/
1221 :
1222 0 : OGRErr OGRVRTLayer::SetFeature( OGRFeature* poVRTFeature )
1223 : {
1224 0 : if(!bUpdate)
1225 : {
1226 : CPLError( CE_Failure, CPLE_AppDefined,
1227 0 : "The SetFeature() operation is not permitted on a read-only VRT." );
1228 0 : return OGRERR_FAILURE;
1229 : }
1230 :
1231 0 : if( iFIDField != -1 )
1232 : {
1233 : CPLError( CE_Failure, CPLE_AppDefined,
1234 0 : "The SetFeature() operation is not supported if the FID option is specified." );
1235 0 : return OGRERR_FAILURE;
1236 : }
1237 :
1238 0 : OGRFeature* poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
1239 0 : OGRErr eErr = poSrcLayer->SetFeature(poSrcFeature);
1240 0 : delete poSrcFeature;
1241 0 : return eErr;
1242 : }
1243 :
1244 : /************************************************************************/
1245 : /* DeleteFeature() */
1246 : /************************************************************************/
1247 :
1248 0 : OGRErr OGRVRTLayer::DeleteFeature( long nFID )
1249 :
1250 : {
1251 0 : if(!bUpdate )
1252 : {
1253 : CPLError( CE_Failure, CPLE_AppDefined,
1254 0 : "The DeleteFeature() operation is not permitted on a read-only VRT." );
1255 0 : return OGRERR_FAILURE;
1256 : }
1257 :
1258 0 : if( iFIDField != -1 )
1259 : {
1260 : CPLError( CE_Failure, CPLE_AppDefined,
1261 0 : "The DeleteFeature() operation is not supported if the FID option is specified." );
1262 0 : return OGRERR_FAILURE;
1263 : }
1264 :
1265 0 : return poSrcLayer->DeleteFeature(nFID);
1266 : }
1267 :
1268 : /************************************************************************/
1269 : /* SetAttributeFilter() */
1270 : /************************************************************************/
1271 :
1272 7 : OGRErr OGRVRTLayer::SetAttributeFilter( const char *pszNewQuery )
1273 :
1274 : {
1275 7 : if( bAttrFilterPassThrough )
1276 : {
1277 6 : CPLFree( pszAttrFilter );
1278 10 : if( pszNewQuery == NULL || strlen(pszNewQuery) == 0 )
1279 4 : pszAttrFilter = NULL;
1280 : else
1281 2 : pszAttrFilter = CPLStrdup( pszNewQuery );
1282 :
1283 6 : ResetReading();
1284 6 : return OGRERR_NONE;
1285 : }
1286 : else
1287 : {
1288 : /* setup m_poAttrQuery */
1289 1 : return OGRLayer::SetAttributeFilter( pszNewQuery );
1290 : }
1291 : }
1292 :
1293 : /************************************************************************/
1294 : /* TestCapability() */
1295 : /************************************************************************/
1296 :
1297 6 : int OGRVRTLayer::TestCapability( const char * pszCap )
1298 :
1299 : {
1300 6 : if ((EQUAL(pszCap,OLCFastFeatureCount) ||
1301 : EQUAL(pszCap,OLCFastSetNextByIndex)) &&
1302 : (eGeometryType == VGS_Direct ||
1303 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1304 : m_poAttrQuery == NULL )
1305 1 : return poSrcLayer->TestCapability(pszCap);
1306 :
1307 5 : else if( EQUAL(pszCap,OLCFastSpatialFilter) &&
1308 : eGeometryType == VGS_Direct && m_poAttrQuery == NULL )
1309 1 : return poSrcLayer->TestCapability(pszCap);
1310 :
1311 4 : else if (EQUAL(pszCap,OLCFastGetExtent) &&
1312 : (eGeometryType == VGS_Direct ||
1313 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1314 : m_poAttrQuery == NULL )
1315 1 : return poSrcLayer->TestCapability(pszCap);
1316 :
1317 3 : else if( EQUAL(pszCap,OLCRandomRead) && iFIDField == -1 )
1318 1 : return poSrcLayer->TestCapability(pszCap);
1319 :
1320 2 : else if( EQUAL(pszCap,OLCSequentialWrite)
1321 : || EQUAL(pszCap,OLCRandomWrite)
1322 : || EQUAL(pszCap,OLCDeleteFeature))
1323 0 : return bUpdate && iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
1324 :
1325 2 : else if( EQUAL(pszCap,OLCStringsAsUTF8) )
1326 0 : return poSrcLayer->TestCapability(pszCap);
1327 :
1328 2 : return FALSE;
1329 : }
1330 :
1331 : /************************************************************************/
1332 : /* GetSpatialRef() */
1333 : /************************************************************************/
1334 :
1335 3 : OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
1336 :
1337 : {
1338 3 : return poSRS;
1339 : }
1340 :
1341 : /************************************************************************/
1342 : /* GetExtent() */
1343 : /************************************************************************/
1344 :
1345 0 : OGRErr OGRVRTLayer::GetExtent( OGREnvelope *psExtent, int bForce )
1346 : {
1347 0 : if ( (eGeometryType == VGS_Direct ||
1348 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1349 : m_poAttrQuery == NULL )
1350 : {
1351 0 : if( bNeedReset )
1352 0 : ResetSourceReading();
1353 0 : return poSrcLayer->GetExtent(psExtent, bForce);
1354 : }
1355 :
1356 0 : return OGRLayer::GetExtent(psExtent, bForce);
1357 : }
1358 :
1359 : /************************************************************************/
1360 : /* GetFeatureCount() */
1361 : /************************************************************************/
1362 :
1363 14 : int OGRVRTLayer::GetFeatureCount( int bForce )
1364 :
1365 : {
1366 14 : if ((eGeometryType == VGS_Direct ||
1367 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1368 : m_poAttrQuery == NULL )
1369 : {
1370 4 : if( bNeedReset )
1371 4 : ResetSourceReading();
1372 4 : return poSrcLayer->GetFeatureCount( bForce );
1373 : }
1374 : else
1375 10 : return OGRLayer::GetFeatureCount( bForce );
1376 : }
1377 :
1378 :
1379 : /************************************************************************/
1380 : /* SetSpatialFilter() */
1381 : /************************************************************************/
1382 :
1383 15 : void OGRVRTLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
1384 : {
1385 15 : if (eGeometryType == VGS_Direct)
1386 5 : bNeedReset = TRUE;
1387 15 : OGRLayer::SetSpatialFilter(poGeomIn);
1388 15 : }
1389 :
1390 : /************************************************************************/
1391 : /* createFromShapeBin() */
1392 : /* */
1393 : /* Translate shapefile binary representation to an OGR */
1394 : /* geometry. */
1395 : /************************************************************************/
1396 :
1397 : #define SHPT_NULL 0
1398 : #define SHPT_POINT 1
1399 : #define SHPT_ARC 3
1400 : #define SHPT_POLYGON 5
1401 : #define SHPT_MULTIPOINT 8
1402 : #define SHPT_POINTZ 11
1403 : #define SHPT_ARCZ 13
1404 : #define SHPT_POLYGONZ 15
1405 : #define SHPT_MULTIPOINTZ 18
1406 : #define SHPT_POINTM 21
1407 : #define SHPT_ARCM 23
1408 : #define SHPT_POLYGONM 25
1409 : #define SHPT_MULTIPOINTM 28
1410 : #define SHPT_MULTIPATCH 31
1411 :
1412 : OGRErr OGRVRTLayer::createFromShapeBin( GByte *pabyShape, OGRGeometry **ppoGeom,
1413 0 : int nBytes )
1414 :
1415 : {
1416 0 : *ppoGeom = NULL;
1417 :
1418 0 : if( nBytes < 1 )
1419 0 : return OGRERR_FAILURE;
1420 :
1421 : // printf( "%s\n", CPLBinaryToHex( nBytes, pabyShape ) );
1422 :
1423 0 : int nSHPType = pabyShape[0];
1424 :
1425 : /* ==================================================================== */
1426 : /* Extract vertices for a Polygon or Arc. */
1427 : /* ==================================================================== */
1428 0 : if( nSHPType == SHPT_POLYGON
1429 : || nSHPType == SHPT_ARC
1430 : || nSHPType == SHPT_POLYGONZ
1431 : || nSHPType == SHPT_POLYGONM
1432 : || nSHPType == SHPT_ARCZ
1433 : || nSHPType == SHPT_ARCM
1434 : || nSHPType == SHPT_MULTIPATCH )
1435 : {
1436 : GInt32 nPoints, nParts;
1437 : int i, nOffset;
1438 : GInt32 *panPartStart;
1439 :
1440 : /* -------------------------------------------------------------------- */
1441 : /* Extract part/point count, and build vertex and part arrays */
1442 : /* to proper size. */
1443 : /* -------------------------------------------------------------------- */
1444 0 : memcpy( &nPoints, pabyShape + 40, 4 );
1445 0 : memcpy( &nParts, pabyShape + 36, 4 );
1446 :
1447 : CPL_LSBPTR32( &nPoints );
1448 : CPL_LSBPTR32( &nParts );
1449 :
1450 0 : panPartStart = (GInt32 *) CPLCalloc(nParts,sizeof(GInt32));
1451 :
1452 : /* -------------------------------------------------------------------- */
1453 : /* Copy out the part array from the record. */
1454 : /* -------------------------------------------------------------------- */
1455 0 : memcpy( panPartStart, pabyShape + 44, 4 * nParts );
1456 0 : for( i = 0; i < nParts; i++ )
1457 : {
1458 : CPL_LSBPTR32( panPartStart + i );
1459 : }
1460 :
1461 0 : nOffset = 44 + 4*nParts;
1462 :
1463 : /* -------------------------------------------------------------------- */
1464 : /* If this is a multipatch, we will also have parts types. For */
1465 : /* now we ignore and skip past them. */
1466 : /* -------------------------------------------------------------------- */
1467 0 : if( nSHPType == SHPT_MULTIPATCH )
1468 0 : nOffset += 4*nParts;
1469 :
1470 : /* -------------------------------------------------------------------- */
1471 : /* Copy out the vertices from the record. */
1472 : /* -------------------------------------------------------------------- */
1473 0 : double *padfX = (double *) CPLMalloc(sizeof(double)*nPoints);
1474 0 : double *padfY = (double *) CPLMalloc(sizeof(double)*nPoints);
1475 0 : double *padfZ = (double *) CPLCalloc(sizeof(double),nPoints);
1476 :
1477 0 : for( i = 0; i < nPoints; i++ )
1478 : {
1479 0 : memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
1480 0 : memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
1481 : CPL_LSBPTR64( padfX + i );
1482 : CPL_LSBPTR64( padfY + i );
1483 : }
1484 :
1485 0 : nOffset += 16*nPoints;
1486 :
1487 : /* -------------------------------------------------------------------- */
1488 : /* If we have a Z coordinate, collect that now. */
1489 : /* -------------------------------------------------------------------- */
1490 0 : if( nSHPType == SHPT_POLYGONZ
1491 : || nSHPType == SHPT_ARCZ
1492 : || nSHPType == SHPT_MULTIPATCH )
1493 : {
1494 0 : for( i = 0; i < nPoints; i++ )
1495 : {
1496 0 : memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
1497 : CPL_LSBPTR64( padfZ + i );
1498 : }
1499 :
1500 0 : nOffset += 16 + 8*nPoints;
1501 : }
1502 :
1503 : /* -------------------------------------------------------------------- */
1504 : /* Build corresponding OGR objects. */
1505 : /* -------------------------------------------------------------------- */
1506 0 : if( nSHPType == SHPT_ARC
1507 : || nSHPType == SHPT_ARCZ
1508 : || nSHPType == SHPT_ARCM )
1509 : {
1510 : /* -------------------------------------------------------------------- */
1511 : /* Arc - As LineString */
1512 : /* -------------------------------------------------------------------- */
1513 0 : if( nParts == 1 )
1514 : {
1515 0 : OGRLineString *poLine = new OGRLineString();
1516 0 : *ppoGeom = poLine;
1517 :
1518 0 : poLine->setPoints( nPoints, padfX, padfY, padfX );
1519 : }
1520 :
1521 : /* -------------------------------------------------------------------- */
1522 : /* Arc - As MultiLineString */
1523 : /* -------------------------------------------------------------------- */
1524 : else
1525 : {
1526 0 : OGRMultiLineString *poMulti = new OGRMultiLineString;
1527 0 : *ppoGeom = poMulti;
1528 :
1529 0 : for( i = 0; i < nParts; i++ )
1530 : {
1531 0 : OGRLineString *poLine = new OGRLineString;
1532 : int nVerticesInThisPart;
1533 :
1534 0 : if( i == nParts-1 )
1535 0 : nVerticesInThisPart = nPoints - panPartStart[i];
1536 : else
1537 : nVerticesInThisPart =
1538 0 : panPartStart[i+1] - panPartStart[i];
1539 :
1540 : poLine->setPoints( nVerticesInThisPart,
1541 : padfX + panPartStart[i],
1542 : padfY + panPartStart[i],
1543 0 : padfZ + panPartStart[i] );
1544 :
1545 0 : poMulti->addGeometryDirectly( poLine );
1546 : }
1547 : }
1548 : } /* ARC */
1549 :
1550 : /* -------------------------------------------------------------------- */
1551 : /* Polygon */
1552 : /* -------------------------------------------------------------------- */
1553 0 : else if( nSHPType == SHPT_POLYGON
1554 : || nSHPType == SHPT_POLYGONZ
1555 : || nSHPType == SHPT_POLYGONM )
1556 : {
1557 0 : OGRPolygon *poMulti = new OGRPolygon;
1558 0 : *ppoGeom = poMulti;
1559 :
1560 0 : for( i = 0; i < nParts; i++ )
1561 : {
1562 0 : OGRLinearRing *poRing = new OGRLinearRing;
1563 : int nVerticesInThisPart;
1564 :
1565 0 : if( i == nParts-1 )
1566 0 : nVerticesInThisPart = nPoints - panPartStart[i];
1567 : else
1568 : nVerticesInThisPart =
1569 0 : panPartStart[i+1] - panPartStart[i];
1570 :
1571 : poRing->setPoints( nVerticesInThisPart,
1572 : padfX + panPartStart[i],
1573 : padfY + panPartStart[i],
1574 0 : padfZ + panPartStart[i] );
1575 :
1576 0 : poMulti->addRingDirectly( poRing );
1577 : }
1578 : } /* polygon */
1579 :
1580 : /* -------------------------------------------------------------------- */
1581 : /* Multipatch */
1582 : /* -------------------------------------------------------------------- */
1583 : else if( nSHPType == SHPT_MULTIPATCH )
1584 : {
1585 : /* return to this later */
1586 : }
1587 :
1588 0 : CPLFree( panPartStart );
1589 0 : CPLFree( padfX );
1590 0 : CPLFree( padfY );
1591 0 : CPLFree( padfZ );
1592 :
1593 0 : if( nSHPType == SHPT_ARC
1594 : || nSHPType == SHPT_POLYGON )
1595 0 : (*ppoGeom)->setCoordinateDimension( 2 );
1596 :
1597 0 : return OGRERR_NONE;
1598 : }
1599 :
1600 : /* ==================================================================== */
1601 : /* Extract vertices for a MultiPoint. */
1602 : /* ==================================================================== */
1603 0 : else if( nSHPType == SHPT_MULTIPOINT
1604 : || nSHPType == SHPT_MULTIPOINTM
1605 : || nSHPType == SHPT_MULTIPOINTZ )
1606 : {
1607 : #ifdef notdef
1608 : int32 nPoints;
1609 : int i, nOffset;
1610 :
1611 : memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
1612 : if( bBigEndian ) SwapWord( 4, &nPoints );
1613 :
1614 : psShape->nVertices = nPoints;
1615 : psShape->padfX = (double *) calloc(nPoints,sizeof(double));
1616 : psShape->padfY = (double *) calloc(nPoints,sizeof(double));
1617 : psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
1618 : psShape->padfM = (double *) calloc(nPoints,sizeof(double));
1619 :
1620 : for( i = 0; i < nPoints; i++ )
1621 : {
1622 : memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
1623 : memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
1624 :
1625 : if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
1626 : if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
1627 : }
1628 :
1629 : nOffset = 48 + 16*nPoints;
1630 :
1631 : /* -------------------------------------------------------------------- */
1632 : /* Get the X/Y bounds. */
1633 : /* -------------------------------------------------------------------- */
1634 : memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
1635 : memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
1636 : memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
1637 : memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
1638 :
1639 : if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
1640 : if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
1641 : if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
1642 : if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
1643 :
1644 : /* -------------------------------------------------------------------- */
1645 : /* If we have a Z coordinate, collect that now. */
1646 : /* -------------------------------------------------------------------- */
1647 : if( psShape->nSHPType == SHPT_MULTIPOINTZ )
1648 : {
1649 : memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
1650 : memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
1651 :
1652 : if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
1653 : if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
1654 :
1655 : for( i = 0; i < nPoints; i++ )
1656 : {
1657 : memcpy( psShape->padfZ + i,
1658 : psSHP->pabyRec + nOffset + 16 + i*8, 8 );
1659 : if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
1660 : }
1661 :
1662 : nOffset += 16 + 8*nPoints;
1663 : }
1664 :
1665 : /* -------------------------------------------------------------------- */
1666 : /* If we have a M measure value, then read it now. We assume */
1667 : /* that the measure can be present for any shape if the size is */
1668 : /* big enough, but really it will only occur for the Z shapes */
1669 : /* (options), and the M shapes. */
1670 : /* -------------------------------------------------------------------- */
1671 : if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
1672 : {
1673 : memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
1674 : memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
1675 :
1676 : if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
1677 : if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
1678 :
1679 : for( i = 0; i < nPoints; i++ )
1680 : {
1681 : memcpy( psShape->padfM + i,
1682 : psSHP->pabyRec + nOffset + 16 + i*8, 8 );
1683 : if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
1684 : }
1685 : }
1686 : #endif
1687 : }
1688 :
1689 : /* ==================================================================== */
1690 : /* Extract vertices for a point. */
1691 : /* ==================================================================== */
1692 0 : else if( nSHPType == SHPT_POINT
1693 : || nSHPType == SHPT_POINTM
1694 : || nSHPType == SHPT_POINTZ )
1695 : {
1696 : int nOffset;
1697 0 : double dfX, dfY, dfZ = 0;
1698 :
1699 0 : memcpy( &dfX, pabyShape + 4, 8 );
1700 0 : memcpy( &dfY, pabyShape + 4 + 8, 8 );
1701 :
1702 : CPL_LSBPTR64( &dfX );
1703 : CPL_LSBPTR64( &dfY );
1704 0 : nOffset = 20 + 8;
1705 :
1706 0 : if( nSHPType == SHPT_POINTZ )
1707 : {
1708 0 : memcpy( &dfZ, pabyShape + 4 + 16, 8 );
1709 : CPL_LSBPTR64( &dfY );
1710 : }
1711 :
1712 0 : *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
1713 :
1714 0 : if( nSHPType != SHPT_POINTZ )
1715 0 : (*ppoGeom)->setCoordinateDimension( 2 );
1716 :
1717 0 : return OGRERR_NONE;
1718 : }
1719 :
1720 0 : return OGRERR_FAILURE;
1721 : }
|