1 : /******************************************************************************
2 : * $Id: ogrvrtlayer.cpp 17924 2009-10-30 07:59:28Z warmerdam $
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 17924 2009-10-30 07:59:28Z warmerdam $");
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 36 : 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 36 : }
123 :
124 : /************************************************************************/
125 : /* Initialize() */
126 : /************************************************************************/
127 :
128 18 : int OGRVRTLayer::Initialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
129 : 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 : 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 5 : iGeomXField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
373 10 : CPLGetXMLValue( psLTree, "GeometryField.x", "missing" ) );
374 5 : iGeomYField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
375 10 : CPLGetXMLValue( psLTree, "GeometryField.y", "missing" ) );
376 5 : iGeomZField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
377 10 : 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 : 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 : }
686 : }
687 :
688 : /* -------------------------------------------------------------------- */
689 : /* Install spatial + attr filter query on source layer. */
690 : /* -------------------------------------------------------------------- */
691 59 : if( pszFilter == NULL && pszAttrFilter == NULL )
692 25 : bSuccess = (poSrcLayer->SetAttributeFilter( NULL ) == CE_None);
693 :
694 15 : else if( pszFilter != NULL && pszAttrFilter == NULL )
695 6 : bSuccess = (poSrcLayer->SetAttributeFilter( pszFilter ) == CE_None);
696 :
697 6 : else if( pszFilter == NULL && pszAttrFilter != NULL )
698 3 : bSuccess = (poSrcLayer->SetAttributeFilter( pszAttrFilter ) == CE_None);
699 :
700 : else
701 : {
702 0 : CPLString osMerged = pszFilter;
703 :
704 0 : osMerged += " AND ";
705 0 : osMerged += pszAttrFilter;
706 :
707 0 : bSuccess = (poSrcLayer->SetAttributeFilter(osMerged) == CE_None);
708 : }
709 :
710 34 : CPLFree( pszFilter );
711 :
712 : /* -------------------------------------------------------------------- */
713 : /* Clear spatial filter (to be safe) for non direct geometries */
714 : /* and reset reading. */
715 : /* -------------------------------------------------------------------- */
716 34 : if (eGeometryType == VGS_Direct)
717 : {
718 6 : if (poSrcRegion == NULL)
719 2 : poSrcLayer->SetSpatialFilter( m_poFilterGeom );
720 4 : else if (m_poFilterGeom == NULL)
721 2 : poSrcLayer->SetSpatialFilter( poSrcRegion );
722 : else
723 : {
724 2 : if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
725 : {
726 : CPLError(CE_Failure, CPLE_AppDefined,
727 0 : "Spatial filter should be polygon when a SrcRegion is defined. Ignoring it");
728 0 : poSrcLayer->SetSpatialFilter( poSrcRegion );
729 : }
730 : else
731 : {
732 2 : OGRGeometry* poIntersection = m_poFilterGeom->Intersection(poSrcRegion);
733 2 : poSrcLayer->SetSpatialFilter( poIntersection );
734 2 : delete poIntersection;
735 : }
736 : }
737 : }
738 : else
739 28 : poSrcLayer->SetSpatialFilter( NULL );
740 34 : poSrcLayer->ResetReading();
741 34 : bNeedReset = FALSE;
742 :
743 34 : return bSuccess;
744 : }
745 :
746 : /************************************************************************/
747 : /* GetNextFeature() */
748 : /************************************************************************/
749 :
750 56 : OGRFeature *OGRVRTLayer::GetNextFeature()
751 :
752 : {
753 56 : if( bNeedReset )
754 : {
755 30 : if( !ResetSourceReading() )
756 0 : return NULL;
757 : }
758 :
759 7 : for( ; TRUE; )
760 : {
761 : OGRFeature *poSrcFeature, *poFeature;
762 :
763 63 : poSrcFeature = poSrcLayer->GetNextFeature();
764 63 : if( poSrcFeature == NULL )
765 15 : return NULL;
766 :
767 48 : poFeature = TranslateFeature( poSrcFeature, TRUE );
768 48 : delete poSrcFeature;
769 :
770 48 : if( poFeature == NULL )
771 4 : return NULL;
772 :
773 44 : if( (eGeometryType == VGS_Direct || m_poFilterGeom == NULL
774 : || FilterGeometry( poFeature->GetGeometryRef() ) )
775 : && (m_poAttrQuery == NULL
776 : || m_poAttrQuery->Evaluate( poFeature )) )
777 37 : return poFeature;
778 :
779 7 : delete poFeature;
780 : }
781 : }
782 :
783 : /************************************************************************/
784 : /* TranslateFeature() */
785 : /* */
786 : /* Translate a source feature into a feature for this layer. */
787 : /************************************************************************/
788 :
789 62 : OGRFeature *OGRVRTLayer::TranslateFeature( OGRFeature*& poSrcFeat, int bUseSrcRegion )
790 :
791 : {
792 : retry:
793 62 : OGRFeature *poDstFeat = new OGRFeature( poFeatureDefn );
794 :
795 62 : m_nFeaturesRead++;
796 :
797 : /* -------------------------------------------------------------------- */
798 : /* Handle FID. */
799 : /* -------------------------------------------------------------------- */
800 62 : if( iFIDField == -1 )
801 42 : poDstFeat->SetFID( poSrcFeat->GetFID() );
802 : else
803 20 : poDstFeat->SetFID( poSrcFeat->GetFieldAsInteger( iFIDField ) );
804 :
805 : /* -------------------------------------------------------------------- */
806 : /* Handle style string. */
807 : /* -------------------------------------------------------------------- */
808 62 : if( iStyleField != -1 )
809 : {
810 0 : if( poSrcFeat->IsFieldSet(iStyleField) )
811 : poDstFeat->SetStyleString(
812 0 : poSrcFeat->GetFieldAsString(iStyleField) );
813 : }
814 : else
815 : {
816 62 : if( poSrcFeat->GetStyleString() != NULL )
817 0 : poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
818 : }
819 :
820 : /* -------------------------------------------------------------------- */
821 : /* Handle the geometry. Eventually there will be several more */
822 : /* supported options. */
823 : /* -------------------------------------------------------------------- */
824 62 : if( eGeometryType == VGS_None )
825 : {
826 : /* do nothing */
827 : }
828 62 : else if( eGeometryType == VGS_WKT )
829 : {
830 39 : char *pszWKT = (char *) poSrcFeat->GetFieldAsString( iGeomField );
831 :
832 39 : if( pszWKT != NULL )
833 : {
834 39 : OGRGeometry *poGeom = NULL;
835 :
836 39 : OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom );
837 39 : if( poGeom == NULL )
838 : CPLDebug( "OGR_VRT", "Did not get geometry from %s",
839 0 : pszWKT );
840 :
841 39 : poDstFeat->SetGeometryDirectly( poGeom );
842 : }
843 : }
844 23 : else if( eGeometryType == VGS_WKB )
845 : {
846 : int nBytes;
847 : GByte *pabyWKB;
848 1 : int bNeedFree = FALSE;
849 :
850 1 : if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
851 : {
852 0 : pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
853 : }
854 : else
855 : {
856 1 : const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
857 :
858 1 : pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
859 1 : bNeedFree = TRUE;
860 : }
861 :
862 1 : if( pabyWKB != NULL )
863 : {
864 1 : OGRGeometry *poGeom = NULL;
865 :
866 1 : if( OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeom,
867 : nBytes ) == OGRERR_NONE )
868 1 : poDstFeat->SetGeometryDirectly( poGeom );
869 : }
870 :
871 1 : if( bNeedFree )
872 1 : CPLFree( pabyWKB );
873 : }
874 22 : else if( eGeometryType == VGS_Shape )
875 : {
876 : int nBytes;
877 : GByte *pabyWKB;
878 0 : int bNeedFree = FALSE;
879 :
880 0 : if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
881 : {
882 0 : pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
883 : }
884 : else
885 : {
886 0 : const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
887 :
888 0 : pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
889 0 : bNeedFree = TRUE;
890 : }
891 :
892 0 : if( pabyWKB != NULL )
893 : {
894 0 : OGRGeometry *poGeom = NULL;
895 :
896 0 : if( createFromShapeBin( pabyWKB, &poGeom, nBytes ) == OGRERR_NONE )
897 0 : poDstFeat->SetGeometryDirectly( poGeom );
898 : }
899 :
900 0 : if( bNeedFree )
901 0 : CPLFree( pabyWKB );
902 : }
903 22 : else if( eGeometryType == VGS_Direct )
904 : {
905 6 : poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
906 : }
907 16 : else if( eGeometryType == VGS_PointFromColumns )
908 : {
909 16 : if( iGeomZField != -1 )
910 : poDstFeat->SetGeometryDirectly(
911 : new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
912 : poSrcFeat->GetFieldAsDouble( iGeomYField ),
913 8 : poSrcFeat->GetFieldAsDouble( iGeomZField ) ) );
914 : else
915 : poDstFeat->SetGeometryDirectly(
916 : new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
917 8 : poSrcFeat->GetFieldAsDouble( iGeomYField ) ) );
918 : }
919 : else
920 : /* add other options here. */;
921 :
922 : /* In the non direct case, we need to check that the geometry intersects the source */
923 : /* region before an optionnal clipping */
924 62 : if( bUseSrcRegion && eGeometryType != VGS_Direct && poSrcRegion != NULL )
925 : {
926 23 : OGRGeometry* poGeom = poDstFeat->GetGeometryRef();
927 23 : if (poGeom != NULL && !poGeom->Intersects(poSrcRegion))
928 : {
929 14 : delete poSrcFeat;
930 14 : delete poDstFeat;
931 :
932 : /* Fetch next source feature and retry translating it */
933 14 : poSrcFeat = poSrcLayer->GetNextFeature();
934 14 : if (poSrcFeat == NULL)
935 4 : return NULL;
936 :
937 10 : goto retry;
938 : }
939 : }
940 :
941 : /* Clip the geometry to the SrcRegion if asked */
942 48 : if (poSrcRegion != NULL && bSrcClip && poDstFeat->GetGeometryRef() != NULL)
943 : {
944 0 : OGRGeometry* poClippedGeom = poDstFeat->GetGeometryRef()->Intersection(poSrcRegion);
945 0 : poDstFeat->SetGeometryDirectly(poClippedGeom);
946 : }
947 :
948 48 : if (poDstFeat->GetGeometryRef() != NULL && poSRS != NULL)
949 15 : poDstFeat->GetGeometryRef()->assignSpatialReference(poSRS);
950 :
951 : /* -------------------------------------------------------------------- */
952 : /* Copy fields. */
953 : /* -------------------------------------------------------------------- */
954 : int iVRTField;
955 :
956 259 : for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
957 : {
958 211 : if( anSrcField[iVRTField] == -1 )
959 5 : continue;
960 :
961 206 : OGRFieldDefn *poDstDefn = poFeatureDefn->GetFieldDefn( iVRTField );
962 206 : OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
963 :
964 206 : if( abDirectCopy[iVRTField]
965 : && poDstDefn->GetType() == poSrcDefn->GetType() )
966 : {
967 : poDstFeat->SetField( iVRTField,
968 196 : poSrcFeat->GetRawFieldRef( anSrcField[iVRTField] ) );
969 : }
970 : else
971 : {
972 : /* Eventually we need to offer some more sophisticated translation
973 : options here for more esoteric types. */
974 :
975 : poDstFeat->SetField( iVRTField,
976 10 : poSrcFeat->GetFieldAsString(anSrcField[iVRTField]));
977 : }
978 : }
979 :
980 48 : return poDstFeat;
981 : }
982 :
983 :
984 : /************************************************************************/
985 : /* GetFeature() */
986 : /************************************************************************/
987 :
988 4 : OGRFeature *OGRVRTLayer::GetFeature( long nFeatureId )
989 :
990 : {
991 4 : bNeedReset = TRUE;
992 :
993 : /* -------------------------------------------------------------------- */
994 : /* If the FID is directly mapped, we can do a simple */
995 : /* GetFeature() to get our target feature. Otherwise we need */
996 : /* to setup an appropriate query to get it. */
997 : /* -------------------------------------------------------------------- */
998 : OGRFeature *poSrcFeature, *poFeature;
999 :
1000 4 : if( iFIDField == -1 )
1001 : {
1002 3 : poSrcFeature = poSrcLayer->GetFeature( nFeatureId );
1003 : }
1004 : else
1005 : {
1006 1 : const char* pszFID = poSrcLayer->GetLayerDefn()->GetFieldDefn(iFIDField)->GetNameRef();
1007 1 : char* pszFIDQuery = (char*)CPLMalloc(strlen(pszFID) + 64);
1008 :
1009 1 : poSrcLayer->ResetReading();
1010 1 : sprintf( pszFIDQuery, "%s = %ld", pszFID, nFeatureId );
1011 1 : poSrcLayer->SetSpatialFilter( NULL );
1012 1 : poSrcLayer->SetAttributeFilter( pszFIDQuery );
1013 1 : CPLFree(pszFIDQuery);
1014 :
1015 1 : poSrcFeature = poSrcLayer->GetNextFeature();
1016 : }
1017 :
1018 4 : if( poSrcFeature == NULL )
1019 0 : return NULL;
1020 :
1021 : /* -------------------------------------------------------------------- */
1022 : /* Translate feature and return it. */
1023 : /* -------------------------------------------------------------------- */
1024 4 : poFeature = TranslateFeature( poSrcFeature, FALSE );
1025 4 : delete poSrcFeature;
1026 :
1027 4 : return poFeature;
1028 : }
1029 :
1030 : /************************************************************************/
1031 : /* SetNextByIndex() */
1032 : /************************************************************************/
1033 :
1034 0 : OGRErr OGRVRTLayer::SetNextByIndex( long nIndex )
1035 : {
1036 0 : if (TestCapability(OLCFastSetNextByIndex))
1037 0 : return poSrcLayer->SetNextByIndex(nIndex);
1038 :
1039 0 : return OGRLayer::SetNextByIndex(nIndex);
1040 : }
1041 :
1042 : /************************************************************************/
1043 : /* TranslateVRTFeatureToSrcFeature() */
1044 : /* */
1045 : /* Translate a VRT feature into a feature for the source layer */
1046 : /************************************************************************/
1047 :
1048 3 : OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeature)
1049 : {
1050 3 : OGRFeature *poSrcFeat = new OGRFeature( poSrcLayer->GetLayerDefn() );
1051 :
1052 3 : poSrcFeat->SetFID( poVRTFeature->GetFID() );
1053 :
1054 : /* -------------------------------------------------------------------- */
1055 : /* Handle style string. */
1056 : /* -------------------------------------------------------------------- */
1057 3 : if( iStyleField != -1 )
1058 : {
1059 0 : if( poVRTFeature->GetStyleString() != NULL )
1060 0 : poSrcFeat->SetField( iStyleField, poVRTFeature->GetStyleString() );
1061 : }
1062 : else
1063 : {
1064 3 : if( poVRTFeature->GetStyleString() != NULL )
1065 0 : poSrcFeat->SetStyleString(poVRTFeature->GetStyleString());
1066 : }
1067 :
1068 : /* -------------------------------------------------------------------- */
1069 : /* Handle the geometry. Eventually there will be several more */
1070 : /* supported options. */
1071 : /* -------------------------------------------------------------------- */
1072 3 : if( eGeometryType == VGS_None )
1073 : {
1074 : /* do nothing */
1075 : }
1076 3 : else if( eGeometryType == VGS_WKT )
1077 : {
1078 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1079 1 : if (poGeom != NULL)
1080 : {
1081 1 : char* pszWKT = NULL;
1082 1 : if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
1083 : {
1084 1 : poSrcFeat->SetField(iGeomField, pszWKT);
1085 : }
1086 1 : CPLFree(pszWKT);
1087 : }
1088 : }
1089 2 : else if( eGeometryType == VGS_WKB )
1090 : {
1091 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1092 1 : if (poGeom != NULL)
1093 : {
1094 1 : int nSize = poGeom->WkbSize();
1095 1 : GByte* pabyData = (GByte*)CPLMalloc(nSize);
1096 1 : if (poGeom->exportToWkb(wkbNDR, pabyData) == OGRERR_NONE)
1097 : {
1098 1 : if ( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
1099 : {
1100 0 : poSrcFeat->SetField(iGeomField, nSize, pabyData);
1101 : }
1102 : else
1103 : {
1104 1 : char* pszHexWKB = CPLBinaryToHex(nSize, pabyData);
1105 1 : poSrcFeat->SetField(iGeomField, pszHexWKB);
1106 1 : CPLFree(pszHexWKB);
1107 : }
1108 : }
1109 1 : CPLFree(pabyData);
1110 : }
1111 : }
1112 1 : else if( eGeometryType == VGS_Shape )
1113 : {
1114 0 : CPLDebug("OGR_VRT", "Update of VGS_Shape geometries not supported");
1115 : }
1116 1 : else if( eGeometryType == VGS_Direct )
1117 : {
1118 0 : poSrcFeat->SetGeometry( poVRTFeature->GetGeometryRef() );
1119 : }
1120 1 : else if( eGeometryType == VGS_PointFromColumns )
1121 : {
1122 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1123 1 : if (poGeom != NULL)
1124 : {
1125 1 : if (wkbFlatten(poGeom->getGeometryType()) != wkbPoint)
1126 : {
1127 : CPLError(CE_Warning, CPLE_NotSupported,
1128 0 : "Cannot set a non ponctual geometry for PointFromColumns geometry");
1129 : }
1130 : else
1131 : {
1132 1 : poSrcFeat->SetField( iGeomXField, ((OGRPoint*)poGeom)->getX() );
1133 1 : poSrcFeat->SetField( iGeomYField, ((OGRPoint*)poGeom)->getY() );
1134 1 : if( iGeomZField != -1 )
1135 : {
1136 0 : poSrcFeat->SetField( iGeomZField, ((OGRPoint*)poGeom)->getZ() );
1137 : }
1138 : }
1139 : }
1140 : }
1141 : else
1142 : /* add other options here. */;
1143 :
1144 3 : if (poSrcFeat->GetGeometryRef() != NULL && poSRS != NULL)
1145 0 : poSrcFeat->GetGeometryRef()->assignSpatialReference(poSRS);
1146 :
1147 : /* -------------------------------------------------------------------- */
1148 : /* Copy fields. */
1149 : /* -------------------------------------------------------------------- */
1150 :
1151 : int iVRTField;
1152 :
1153 11 : for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
1154 : {
1155 : /* Do not set source geometry columns. Have been set just above */
1156 8 : if (anSrcField[iVRTField] == iGeomField || anSrcField[iVRTField] == iGeomXField ||
1157 : anSrcField[iVRTField] == iGeomYField || anSrcField[iVRTField] == iGeomZField)
1158 2 : continue;
1159 :
1160 6 : OGRFieldDefn *poVRTDefn = poFeatureDefn->GetFieldDefn( iVRTField );
1161 6 : OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
1162 :
1163 6 : if( abDirectCopy[iVRTField]
1164 : && poVRTDefn->GetType() == poSrcDefn->GetType() )
1165 : {
1166 : poSrcFeat->SetField( anSrcField[iVRTField],
1167 6 : poVRTFeature->GetRawFieldRef( iVRTField ) );
1168 : }
1169 : else
1170 : {
1171 : /* Eventually we need to offer some more sophisticated translation
1172 : options here for more esoteric types. */
1173 : poSrcFeat->SetField( anSrcField[iVRTField],
1174 0 : poVRTFeature->GetFieldAsString(iVRTField));
1175 : }
1176 : }
1177 :
1178 3 : return poSrcFeat;
1179 : }
1180 :
1181 : /************************************************************************/
1182 : /* CreateFeature() */
1183 : /************************************************************************/
1184 :
1185 3 : OGRErr OGRVRTLayer::CreateFeature( OGRFeature* poVRTFeature )
1186 : {
1187 3 : if(!bUpdate)
1188 : {
1189 : CPLError( CE_Failure, CPLE_AppDefined,
1190 0 : "The CreateFeature() operation is not permitted on a read-only VRT." );
1191 0 : return OGRERR_FAILURE;
1192 : }
1193 :
1194 3 : if( iFIDField != -1 )
1195 : {
1196 : CPLError( CE_Failure, CPLE_AppDefined,
1197 0 : "The CreateFeature() operation is not supported if the FID option is specified." );
1198 0 : return OGRERR_FAILURE;
1199 : }
1200 :
1201 3 : OGRFeature* poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
1202 3 : poSrcFeature->SetFID(OGRNullFID);
1203 3 : OGRErr eErr = poSrcLayer->CreateFeature(poSrcFeature);
1204 3 : if (eErr == OGRERR_NONE)
1205 : {
1206 3 : poVRTFeature->SetFID(poSrcFeature->GetFID());
1207 : }
1208 3 : delete poSrcFeature;
1209 3 : return eErr;
1210 : }
1211 :
1212 : /************************************************************************/
1213 : /* SetFeature() */
1214 : /************************************************************************/
1215 :
1216 0 : OGRErr OGRVRTLayer::SetFeature( OGRFeature* poVRTFeature )
1217 : {
1218 0 : if(!bUpdate)
1219 : {
1220 : CPLError( CE_Failure, CPLE_AppDefined,
1221 0 : "The SetFeature() operation is not permitted on a read-only VRT." );
1222 0 : return OGRERR_FAILURE;
1223 : }
1224 :
1225 0 : if( iFIDField != -1 )
1226 : {
1227 : CPLError( CE_Failure, CPLE_AppDefined,
1228 0 : "The SetFeature() operation is not supported if the FID option is specified." );
1229 0 : return OGRERR_FAILURE;
1230 : }
1231 :
1232 0 : OGRFeature* poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
1233 0 : OGRErr eErr = poSrcLayer->SetFeature(poSrcFeature);
1234 0 : delete poSrcFeature;
1235 0 : return eErr;
1236 : }
1237 :
1238 : /************************************************************************/
1239 : /* DeleteFeature() */
1240 : /************************************************************************/
1241 :
1242 0 : OGRErr OGRVRTLayer::DeleteFeature( long nFID )
1243 :
1244 : {
1245 0 : if(!bUpdate )
1246 : {
1247 : CPLError( CE_Failure, CPLE_AppDefined,
1248 0 : "The DeleteFeature() operation is not permitted on a read-only VRT." );
1249 0 : return OGRERR_FAILURE;
1250 : }
1251 :
1252 0 : if( iFIDField != -1 )
1253 : {
1254 : CPLError( CE_Failure, CPLE_AppDefined,
1255 0 : "The DeleteFeature() operation is not supported if the FID option is specified." );
1256 0 : return OGRERR_FAILURE;
1257 : }
1258 :
1259 0 : return poSrcLayer->DeleteFeature(nFID);
1260 : }
1261 :
1262 : /************************************************************************/
1263 : /* SetAttributeFilter() */
1264 : /************************************************************************/
1265 :
1266 7 : OGRErr OGRVRTLayer::SetAttributeFilter( const char *pszNewQuery )
1267 :
1268 : {
1269 7 : if( bAttrFilterPassThrough )
1270 : {
1271 6 : CPLFree( pszAttrFilter );
1272 10 : if( pszNewQuery == NULL || strlen(pszNewQuery) == 0 )
1273 4 : pszAttrFilter = NULL;
1274 : else
1275 2 : pszAttrFilter = CPLStrdup( pszNewQuery );
1276 :
1277 6 : ResetReading();
1278 6 : return OGRERR_NONE;
1279 : }
1280 : else
1281 : {
1282 : /* setup m_poAttrQuery */
1283 1 : return OGRLayer::SetAttributeFilter( pszNewQuery );
1284 : }
1285 : }
1286 :
1287 : /************************************************************************/
1288 : /* TestCapability() */
1289 : /************************************************************************/
1290 :
1291 6 : int OGRVRTLayer::TestCapability( const char * pszCap )
1292 :
1293 : {
1294 6 : if ((EQUAL(pszCap,OLCFastFeatureCount) ||
1295 : EQUAL(pszCap,OLCFastSetNextByIndex)) &&
1296 : (eGeometryType == VGS_Direct ||
1297 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1298 : m_poAttrQuery == NULL )
1299 1 : return poSrcLayer->TestCapability(pszCap);
1300 :
1301 5 : else if( EQUAL(pszCap,OLCFastSpatialFilter) &&
1302 : eGeometryType == VGS_Direct && m_poAttrQuery == NULL )
1303 1 : return poSrcLayer->TestCapability(pszCap);
1304 :
1305 4 : else if (EQUAL(pszCap,OLCFastGetExtent) &&
1306 : (eGeometryType == VGS_Direct ||
1307 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1308 : m_poAttrQuery == NULL )
1309 1 : return poSrcLayer->TestCapability(pszCap);
1310 :
1311 3 : else if( EQUAL(pszCap,OLCRandomRead) && iFIDField == -1 )
1312 1 : return poSrcLayer->TestCapability(pszCap);
1313 :
1314 2 : else if( EQUAL(pszCap,OLCSequentialWrite)
1315 : || EQUAL(pszCap,OLCRandomWrite)
1316 : || EQUAL(pszCap,OLCDeleteFeature))
1317 0 : return bUpdate && iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
1318 :
1319 2 : else if( EQUAL(pszCap,OLCStringsAsUTF8) )
1320 0 : return poSrcLayer->TestCapability(pszCap);
1321 :
1322 2 : return FALSE;
1323 : }
1324 :
1325 : /************************************************************************/
1326 : /* GetSpatialRef() */
1327 : /************************************************************************/
1328 :
1329 3 : OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
1330 :
1331 : {
1332 3 : return poSRS;
1333 : }
1334 :
1335 : /************************************************************************/
1336 : /* GetExtent() */
1337 : /************************************************************************/
1338 :
1339 0 : OGRErr OGRVRTLayer::GetExtent( OGREnvelope *psExtent, int bForce )
1340 : {
1341 0 : if ( (eGeometryType == VGS_Direct ||
1342 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1343 : m_poAttrQuery == NULL )
1344 : {
1345 0 : if( bNeedReset )
1346 0 : ResetSourceReading();
1347 0 : return poSrcLayer->GetExtent(psExtent, bForce);
1348 : }
1349 :
1350 0 : return OGRLayer::GetExtent(psExtent, bForce);
1351 : }
1352 :
1353 : /************************************************************************/
1354 : /* GetFeatureCount() */
1355 : /************************************************************************/
1356 :
1357 14 : int OGRVRTLayer::GetFeatureCount( int bForce )
1358 :
1359 : {
1360 14 : if ((eGeometryType == VGS_Direct ||
1361 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1362 : m_poAttrQuery == NULL )
1363 : {
1364 4 : if( bNeedReset )
1365 4 : ResetSourceReading();
1366 4 : return poSrcLayer->GetFeatureCount( bForce );
1367 : }
1368 : else
1369 10 : return OGRLayer::GetFeatureCount( bForce );
1370 : }
1371 :
1372 :
1373 : /************************************************************************/
1374 : /* SetSpatialFilter() */
1375 : /************************************************************************/
1376 :
1377 15 : void OGRVRTLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
1378 : {
1379 15 : if (eGeometryType == VGS_Direct)
1380 5 : bNeedReset = TRUE;
1381 15 : OGRLayer::SetSpatialFilter(poGeomIn);
1382 15 : }
1383 :
1384 : /************************************************************************/
1385 : /* createFromShapeBin() */
1386 : /* */
1387 : /* Translate shapefile binary representation to an OGR */
1388 : /* geometry. */
1389 : /************************************************************************/
1390 :
1391 : #define SHPT_NULL 0
1392 : #define SHPT_POINT 1
1393 : #define SHPT_ARC 3
1394 : #define SHPT_POLYGON 5
1395 : #define SHPT_MULTIPOINT 8
1396 : #define SHPT_POINTZ 11
1397 : #define SHPT_ARCZ 13
1398 : #define SHPT_POLYGONZ 15
1399 : #define SHPT_MULTIPOINTZ 18
1400 : #define SHPT_POINTM 21
1401 : #define SHPT_ARCM 23
1402 : #define SHPT_POLYGONM 25
1403 : #define SHPT_MULTIPOINTM 28
1404 : #define SHPT_MULTIPATCH 31
1405 :
1406 0 : OGRErr OGRVRTLayer::createFromShapeBin( GByte *pabyShape, OGRGeometry **ppoGeom,
1407 : int nBytes )
1408 :
1409 : {
1410 0 : *ppoGeom = NULL;
1411 :
1412 0 : if( nBytes < 1 )
1413 0 : return OGRERR_FAILURE;
1414 :
1415 : // printf( "%s\n", CPLBinaryToHex( nBytes, pabyShape ) );
1416 :
1417 0 : int nSHPType = pabyShape[0];
1418 :
1419 : /* ==================================================================== */
1420 : /* Extract vertices for a Polygon or Arc. */
1421 : /* ==================================================================== */
1422 0 : if( nSHPType == SHPT_POLYGON
1423 : || nSHPType == SHPT_ARC
1424 : || nSHPType == SHPT_POLYGONZ
1425 : || nSHPType == SHPT_POLYGONM
1426 : || nSHPType == SHPT_ARCZ
1427 : || nSHPType == SHPT_ARCM
1428 : || nSHPType == SHPT_MULTIPATCH )
1429 : {
1430 : GInt32 nPoints, nParts;
1431 : int i, nOffset;
1432 : GInt32 *panPartStart;
1433 :
1434 : /* -------------------------------------------------------------------- */
1435 : /* Extract part/point count, and build vertex and part arrays */
1436 : /* to proper size. */
1437 : /* -------------------------------------------------------------------- */
1438 0 : memcpy( &nPoints, pabyShape + 40, 4 );
1439 0 : memcpy( &nParts, pabyShape + 36, 4 );
1440 :
1441 : CPL_LSBPTR32( &nPoints );
1442 : CPL_LSBPTR32( &nParts );
1443 :
1444 0 : panPartStart = (GInt32 *) CPLCalloc(nParts,sizeof(GInt32));
1445 :
1446 : /* -------------------------------------------------------------------- */
1447 : /* Copy out the part array from the record. */
1448 : /* -------------------------------------------------------------------- */
1449 0 : memcpy( panPartStart, pabyShape + 44, 4 * nParts );
1450 0 : for( i = 0; i < nParts; i++ )
1451 : {
1452 : CPL_LSBPTR32( panPartStart + i );
1453 : }
1454 :
1455 0 : nOffset = 44 + 4*nParts;
1456 :
1457 : /* -------------------------------------------------------------------- */
1458 : /* If this is a multipatch, we will also have parts types. For */
1459 : /* now we ignore and skip past them. */
1460 : /* -------------------------------------------------------------------- */
1461 0 : if( nSHPType == SHPT_MULTIPATCH )
1462 0 : nOffset += 4*nParts;
1463 :
1464 : /* -------------------------------------------------------------------- */
1465 : /* Copy out the vertices from the record. */
1466 : /* -------------------------------------------------------------------- */
1467 0 : double *padfX = (double *) CPLMalloc(sizeof(double)*nPoints);
1468 0 : double *padfY = (double *) CPLMalloc(sizeof(double)*nPoints);
1469 0 : double *padfZ = (double *) CPLCalloc(sizeof(double),nPoints);
1470 :
1471 0 : for( i = 0; i < nPoints; i++ )
1472 : {
1473 0 : memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
1474 0 : memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
1475 : CPL_LSBPTR64( padfX + i );
1476 : CPL_LSBPTR64( padfY + i );
1477 : }
1478 :
1479 0 : nOffset += 16*nPoints;
1480 :
1481 : /* -------------------------------------------------------------------- */
1482 : /* If we have a Z coordinate, collect that now. */
1483 : /* -------------------------------------------------------------------- */
1484 0 : if( nSHPType == SHPT_POLYGONZ
1485 : || nSHPType == SHPT_ARCZ
1486 : || nSHPType == SHPT_MULTIPATCH )
1487 : {
1488 0 : for( i = 0; i < nPoints; i++ )
1489 : {
1490 0 : memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
1491 : CPL_LSBPTR64( padfZ + i );
1492 : }
1493 :
1494 0 : nOffset += 16 + 8*nPoints;
1495 : }
1496 :
1497 : /* -------------------------------------------------------------------- */
1498 : /* Build corresponding OGR objects. */
1499 : /* -------------------------------------------------------------------- */
1500 0 : if( nSHPType == SHPT_ARC
1501 : || nSHPType == SHPT_ARCZ
1502 : || nSHPType == SHPT_ARCM )
1503 : {
1504 : /* -------------------------------------------------------------------- */
1505 : /* Arc - As LineString */
1506 : /* -------------------------------------------------------------------- */
1507 0 : if( nParts == 1 )
1508 : {
1509 0 : OGRLineString *poLine = new OGRLineString();
1510 0 : *ppoGeom = poLine;
1511 :
1512 0 : poLine->setPoints( nPoints, padfX, padfY, padfX );
1513 : }
1514 :
1515 : /* -------------------------------------------------------------------- */
1516 : /* Arc - As MultiLineString */
1517 : /* -------------------------------------------------------------------- */
1518 : else
1519 : {
1520 0 : OGRMultiLineString *poMulti = new OGRMultiLineString;
1521 0 : *ppoGeom = poMulti;
1522 :
1523 0 : for( i = 0; i < nParts; i++ )
1524 : {
1525 0 : OGRLineString *poLine = new OGRLineString;
1526 : int nVerticesInThisPart;
1527 :
1528 0 : if( i == nParts-1 )
1529 0 : nVerticesInThisPart = nPoints - panPartStart[i];
1530 : else
1531 : nVerticesInThisPart =
1532 0 : panPartStart[i+1] - panPartStart[i];
1533 :
1534 : poLine->setPoints( nVerticesInThisPart,
1535 0 : padfX + panPartStart[i],
1536 0 : padfY + panPartStart[i],
1537 0 : padfZ + panPartStart[i] );
1538 :
1539 0 : poMulti->addGeometryDirectly( poLine );
1540 : }
1541 : }
1542 : } /* ARC */
1543 :
1544 : /* -------------------------------------------------------------------- */
1545 : /* Polygon */
1546 : /* -------------------------------------------------------------------- */
1547 0 : else if( nSHPType == SHPT_POLYGON
1548 : || nSHPType == SHPT_POLYGONZ
1549 : || nSHPType == SHPT_POLYGONM )
1550 : {
1551 0 : OGRPolygon *poMulti = new OGRPolygon;
1552 0 : *ppoGeom = poMulti;
1553 :
1554 0 : for( i = 0; i < nParts; i++ )
1555 : {
1556 0 : OGRLinearRing *poRing = new OGRLinearRing;
1557 : int nVerticesInThisPart;
1558 :
1559 0 : if( i == nParts-1 )
1560 0 : nVerticesInThisPart = nPoints - panPartStart[i];
1561 : else
1562 : nVerticesInThisPart =
1563 0 : panPartStart[i+1] - panPartStart[i];
1564 :
1565 : poRing->setPoints( nVerticesInThisPart,
1566 0 : padfX + panPartStart[i],
1567 0 : padfY + panPartStart[i],
1568 0 : padfZ + panPartStart[i] );
1569 :
1570 0 : poMulti->addRingDirectly( poRing );
1571 : }
1572 : } /* polygon */
1573 :
1574 : /* -------------------------------------------------------------------- */
1575 : /* Multipatch */
1576 : /* -------------------------------------------------------------------- */
1577 : else if( nSHPType == SHPT_MULTIPATCH )
1578 : {
1579 : /* return to this later */
1580 : }
1581 :
1582 0 : CPLFree( panPartStart );
1583 0 : CPLFree( padfX );
1584 0 : CPLFree( padfY );
1585 0 : CPLFree( padfZ );
1586 :
1587 0 : if( nSHPType == SHPT_ARC
1588 : || nSHPType == SHPT_POLYGON )
1589 0 : (*ppoGeom)->setCoordinateDimension( 2 );
1590 :
1591 0 : return OGRERR_NONE;
1592 : }
1593 :
1594 : /* ==================================================================== */
1595 : /* Extract vertices for a MultiPoint. */
1596 : /* ==================================================================== */
1597 0 : else if( nSHPType == SHPT_MULTIPOINT
1598 : || nSHPType == SHPT_MULTIPOINTM
1599 : || nSHPType == SHPT_MULTIPOINTZ )
1600 : {
1601 : #ifdef notdef
1602 : int32 nPoints;
1603 : int i, nOffset;
1604 :
1605 : memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
1606 : if( bBigEndian ) SwapWord( 4, &nPoints );
1607 :
1608 : psShape->nVertices = nPoints;
1609 : psShape->padfX = (double *) calloc(nPoints,sizeof(double));
1610 : psShape->padfY = (double *) calloc(nPoints,sizeof(double));
1611 : psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
1612 : psShape->padfM = (double *) calloc(nPoints,sizeof(double));
1613 :
1614 : for( i = 0; i < nPoints; i++ )
1615 : {
1616 : memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
1617 : memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
1618 :
1619 : if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
1620 : if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
1621 : }
1622 :
1623 : nOffset = 48 + 16*nPoints;
1624 :
1625 : /* -------------------------------------------------------------------- */
1626 : /* Get the X/Y bounds. */
1627 : /* -------------------------------------------------------------------- */
1628 : memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
1629 : memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
1630 : memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
1631 : memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
1632 :
1633 : if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
1634 : if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
1635 : if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
1636 : if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
1637 :
1638 : /* -------------------------------------------------------------------- */
1639 : /* If we have a Z coordinate, collect that now. */
1640 : /* -------------------------------------------------------------------- */
1641 : if( psShape->nSHPType == SHPT_MULTIPOINTZ )
1642 : {
1643 : memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
1644 : memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
1645 :
1646 : if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
1647 : if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
1648 :
1649 : for( i = 0; i < nPoints; i++ )
1650 : {
1651 : memcpy( psShape->padfZ + i,
1652 : psSHP->pabyRec + nOffset + 16 + i*8, 8 );
1653 : if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
1654 : }
1655 :
1656 : nOffset += 16 + 8*nPoints;
1657 : }
1658 :
1659 : /* -------------------------------------------------------------------- */
1660 : /* If we have a M measure value, then read it now. We assume */
1661 : /* that the measure can be present for any shape if the size is */
1662 : /* big enough, but really it will only occur for the Z shapes */
1663 : /* (options), and the M shapes. */
1664 : /* -------------------------------------------------------------------- */
1665 : if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
1666 : {
1667 : memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
1668 : memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
1669 :
1670 : if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
1671 : if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
1672 :
1673 : for( i = 0; i < nPoints; i++ )
1674 : {
1675 : memcpy( psShape->padfM + i,
1676 : psSHP->pabyRec + nOffset + 16 + i*8, 8 );
1677 : if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
1678 : }
1679 : }
1680 : #endif
1681 : }
1682 :
1683 : /* ==================================================================== */
1684 : /* Extract vertices for a point. */
1685 : /* ==================================================================== */
1686 0 : else if( nSHPType == SHPT_POINT
1687 : || nSHPType == SHPT_POINTM
1688 : || nSHPType == SHPT_POINTZ )
1689 : {
1690 : int nOffset;
1691 0 : double dfX, dfY, dfZ = 0;
1692 :
1693 0 : memcpy( &dfX, pabyShape + 4, 8 );
1694 0 : memcpy( &dfY, pabyShape + 4 + 8, 8 );
1695 :
1696 : CPL_LSBPTR64( &dfX );
1697 : CPL_LSBPTR64( &dfY );
1698 0 : nOffset = 20 + 8;
1699 :
1700 0 : if( nSHPType == SHPT_POINTZ )
1701 : {
1702 0 : memcpy( &dfZ, pabyShape + 4 + 16, 8 );
1703 : CPL_LSBPTR64( &dfY );
1704 : }
1705 :
1706 0 : *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
1707 :
1708 0 : if( nSHPType != SHPT_POINTZ )
1709 0 : (*ppoGeom)->setCoordinateDimension( 2 );
1710 :
1711 0 : return OGRERR_NONE;
1712 : }
1713 :
1714 0 : return OGRERR_FAILURE;
1715 : }
|