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