1 /******************************************************************************
2 * $Id: ogrlayer.cpp 28928 2015-04-17 10:24:19Z rouault $
3 *
4 * Project: OpenGIS Simple Features Reference Implementation
5 * Purpose: The generic portions of the OGRSFLayer class.
6 * Author: Frank Warmerdam, warmerdam@pobox.com
7 *
8 ******************************************************************************
9 * Copyright (c) 1999, Les Technologies SoftMap Inc.
10 * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 #include "ogrsf_frmts.h"
32 #include "ogr_api.h"
33 #include "ogr_p.h"
34 #include "ogr_attrind.h"
35 #include "swq.h"
36 #include "ograpispy.h"
37
38 CPL_CVSID("$Id: ogrlayer.cpp 28928 2015-04-17 10:24:19Z rouault $");
39
40 /************************************************************************/
41 /* OGRLayer() */
42 /************************************************************************/
43
OGRLayer()44 OGRLayer::OGRLayer()
45
46 {
47 m_poStyleTable = NULL;
48 m_poAttrQuery = NULL;
49 m_pszAttrQueryString = NULL;
50 m_poAttrIndex = NULL;
51 m_nRefCount = 0;
52
53 m_nFeaturesRead = 0;
54
55 m_poFilterGeom = NULL;
56 m_bFilterIsEnvelope = FALSE;
57 m_pPreparedFilterGeom = NULL;
58 m_iGeomFieldFilter = 0;
59 }
60
61 /************************************************************************/
62 /* ~OGRLayer() */
63 /************************************************************************/
64
~OGRLayer()65 OGRLayer::~OGRLayer()
66
67 {
68 if ( m_poStyleTable )
69 {
70 delete m_poStyleTable;
71 m_poStyleTable = NULL;
72 }
73
74 if( m_poAttrIndex != NULL )
75 {
76 delete m_poAttrIndex;
77 m_poAttrIndex = NULL;
78 }
79
80 if( m_poAttrQuery != NULL )
81 {
82 delete m_poAttrQuery;
83 m_poAttrQuery = NULL;
84 }
85
86 CPLFree( m_pszAttrQueryString );
87
88 if( m_poFilterGeom )
89 {
90 delete m_poFilterGeom;
91 m_poFilterGeom = NULL;
92 }
93
94 if( m_pPreparedFilterGeom != NULL )
95 {
96 OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
97 m_pPreparedFilterGeom = NULL;
98 }
99 }
100
101 /************************************************************************/
102 /* Reference() */
103 /************************************************************************/
104
Reference()105 int OGRLayer::Reference()
106
107 {
108 return ++m_nRefCount;
109 }
110
111 /************************************************************************/
112 /* OGR_L_Reference() */
113 /************************************************************************/
114
OGR_L_Reference(OGRLayerH hLayer)115 int OGR_L_Reference( OGRLayerH hLayer )
116
117 {
118 VALIDATE_POINTER1( hLayer, "OGR_L_Reference", 0 );
119
120 return ((OGRLayer *) hLayer)->Reference();
121 }
122
123 /************************************************************************/
124 /* Dereference() */
125 /************************************************************************/
126
Dereference()127 int OGRLayer::Dereference()
128
129 {
130 return --m_nRefCount;
131 }
132
133 /************************************************************************/
134 /* OGR_L_Dereference() */
135 /************************************************************************/
136
OGR_L_Dereference(OGRLayerH hLayer)137 int OGR_L_Dereference( OGRLayerH hLayer )
138
139 {
140 VALIDATE_POINTER1( hLayer, "OGR_L_Dereference", 0 );
141
142 return ((OGRLayer *) hLayer)->Dereference();
143 }
144
145 /************************************************************************/
146 /* GetRefCount() */
147 /************************************************************************/
148
GetRefCount() const149 int OGRLayer::GetRefCount() const
150
151 {
152 return m_nRefCount;
153 }
154
155 /************************************************************************/
156 /* OGR_L_GetRefCount() */
157 /************************************************************************/
158
OGR_L_GetRefCount(OGRLayerH hLayer)159 int OGR_L_GetRefCount( OGRLayerH hLayer )
160
161 {
162 VALIDATE_POINTER1( hLayer, "OGR_L_GetRefCount", 0 );
163
164 return ((OGRLayer *) hLayer)->GetRefCount();
165 }
166
167 /************************************************************************/
168 /* GetFeatureCount() */
169 /************************************************************************/
170
GetFeatureCount(int bForce)171 GIntBig OGRLayer::GetFeatureCount( int bForce )
172
173 {
174 OGRFeature *poFeature;
175 GIntBig nFeatureCount = 0;
176
177 if( !bForce )
178 return -1;
179
180 ResetReading();
181 while( (poFeature = GetNextFeature()) != NULL )
182 {
183 nFeatureCount++;
184 delete poFeature;
185 }
186 ResetReading();
187
188 return nFeatureCount;
189 }
190
191 /************************************************************************/
192 /* OGR_L_GetFeatureCount() */
193 /************************************************************************/
194
OGR_L_GetFeatureCount(OGRLayerH hLayer,int bForce)195 GIntBig OGR_L_GetFeatureCount( OGRLayerH hLayer, int bForce )
196
197 {
198 VALIDATE_POINTER1( hLayer, "OGR_L_GetFeatureCount", 0 );
199
200 #ifdef OGRAPISPY_ENABLED
201 if( bOGRAPISpyEnabled )
202 OGRAPISpy_L_GetFeatureCount(hLayer, bForce);
203 #endif
204
205 return ((OGRLayer *) hLayer)->GetFeatureCount(bForce);
206 }
207
208 /************************************************************************/
209 /* GetExtent() */
210 /************************************************************************/
211
GetExtent(OGREnvelope * psExtent,int bForce)212 OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
213
214 {
215 return GetExtentInternal(0, psExtent, bForce);
216 }
217
GetExtent(int iGeomField,OGREnvelope * psExtent,int bForce)218 OGRErr OGRLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce )
219
220 {
221 if( iGeomField == 0 )
222 return GetExtent(psExtent, bForce);
223 else
224 return GetExtentInternal(iGeomField, psExtent, bForce);
225 }
226
GetExtentInternal(int iGeomField,OGREnvelope * psExtent,int bForce)227 OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bForce )
228
229 {
230 OGRFeature *poFeature;
231 OGREnvelope oEnv;
232 GBool bExtentSet = FALSE;
233
234 psExtent->MinX = 0.0;
235 psExtent->MaxX = 0.0;
236 psExtent->MinY = 0.0;
237 psExtent->MaxY = 0.0;
238
239 /* -------------------------------------------------------------------- */
240 /* If this layer has a none geometry type, then we can */
241 /* reasonably assume there are not extents available. */
242 /* -------------------------------------------------------------------- */
243 if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
244 GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
245 {
246 if( iGeomField != 0 )
247 {
248 CPLError(CE_Failure, CPLE_AppDefined,
249 "Invalid geometry field index : %d", iGeomField);
250 }
251 return OGRERR_FAILURE;
252 }
253
254 /* -------------------------------------------------------------------- */
255 /* If not forced, we should avoid having to scan all the */
256 /* features and just return a failure. */
257 /* -------------------------------------------------------------------- */
258 if( !bForce )
259 return OGRERR_FAILURE;
260
261 /* -------------------------------------------------------------------- */
262 /* OK, we hate to do this, but go ahead and read through all */
263 /* the features to collect geometries and build extents. */
264 /* -------------------------------------------------------------------- */
265 ResetReading();
266 while( (poFeature = GetNextFeature()) != NULL )
267 {
268 OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
269 if (poGeom == NULL || poGeom->IsEmpty())
270 {
271 /* Do nothing */
272 }
273 else if (!bExtentSet)
274 {
275 poGeom->getEnvelope(psExtent);
276 if( !(CPLIsNan(psExtent->MinX) || CPLIsNan(psExtent->MinY) ||
277 CPLIsNan(psExtent->MaxX) || CPLIsNan(psExtent->MaxY)) )
278 {
279 bExtentSet = TRUE;
280 }
281 }
282 else
283 {
284 poGeom->getEnvelope(&oEnv);
285 if (oEnv.MinX < psExtent->MinX)
286 psExtent->MinX = oEnv.MinX;
287 if (oEnv.MinY < psExtent->MinY)
288 psExtent->MinY = oEnv.MinY;
289 if (oEnv.MaxX > psExtent->MaxX)
290 psExtent->MaxX = oEnv.MaxX;
291 if (oEnv.MaxY > psExtent->MaxY)
292 psExtent->MaxY = oEnv.MaxY;
293 }
294 delete poFeature;
295 }
296 ResetReading();
297
298 return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
299 }
300
301 /************************************************************************/
302 /* OGR_L_GetExtent() */
303 /************************************************************************/
304
OGR_L_GetExtent(OGRLayerH hLayer,OGREnvelope * psExtent,int bForce)305 OGRErr OGR_L_GetExtent( OGRLayerH hLayer, OGREnvelope *psExtent, int bForce )
306
307 {
308 VALIDATE_POINTER1( hLayer, "OGR_L_GetExtent", OGRERR_INVALID_HANDLE );
309
310 #ifdef OGRAPISPY_ENABLED
311 if( bOGRAPISpyEnabled )
312 OGRAPISpy_L_GetExtent(hLayer, bForce);
313 #endif
314
315 return ((OGRLayer *) hLayer)->GetExtent( psExtent, bForce );
316 }
317
318 /************************************************************************/
319 /* OGR_L_GetExtentEx() */
320 /************************************************************************/
321
OGR_L_GetExtentEx(OGRLayerH hLayer,int iGeomField,OGREnvelope * psExtent,int bForce)322 OGRErr OGR_L_GetExtentEx( OGRLayerH hLayer, int iGeomField,
323 OGREnvelope *psExtent, int bForce )
324
325 {
326 VALIDATE_POINTER1( hLayer, "OGR_L_GetExtentEx", OGRERR_INVALID_HANDLE );
327
328 #ifdef OGRAPISPY_ENABLED
329 if( bOGRAPISpyEnabled )
330 OGRAPISpy_L_GetExtentEx(hLayer, iGeomField, bForce);
331 #endif
332
333 return ((OGRLayer *) hLayer)->GetExtent( iGeomField, psExtent, bForce );
334 }
335
336 /************************************************************************/
337 /* SetAttributeFilter() */
338 /************************************************************************/
339
SetAttributeFilter(const char * pszQuery)340 OGRErr OGRLayer::SetAttributeFilter( const char *pszQuery )
341
342 {
343 CPLFree(m_pszAttrQueryString);
344 m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
345
346 /* -------------------------------------------------------------------- */
347 /* Are we just clearing any existing query? */
348 /* -------------------------------------------------------------------- */
349 if( pszQuery == NULL || strlen(pszQuery) == 0 )
350 {
351 if( m_poAttrQuery )
352 {
353 delete m_poAttrQuery;
354 m_poAttrQuery = NULL;
355 ResetReading();
356 }
357 return OGRERR_NONE;
358 }
359
360 /* -------------------------------------------------------------------- */
361 /* Or are we installing a new query? */
362 /* -------------------------------------------------------------------- */
363 OGRErr eErr;
364
365 if( !m_poAttrQuery )
366 m_poAttrQuery = new OGRFeatureQuery();
367
368 eErr = m_poAttrQuery->Compile( GetLayerDefn(), pszQuery );
369 if( eErr != OGRERR_NONE )
370 {
371 delete m_poAttrQuery;
372 m_poAttrQuery = NULL;
373 }
374
375 ResetReading();
376
377 return eErr;
378 }
379
380 /************************************************************************/
381 /* ContainGeomSpecialField() */
382 /************************************************************************/
383
ContainGeomSpecialField(swq_expr_node * expr,int nLayerFieldCount)384 static int ContainGeomSpecialField(swq_expr_node* expr,
385 int nLayerFieldCount)
386 {
387 if (expr->eNodeType == SNT_COLUMN)
388 {
389 if( expr->table_index == 0 && expr->field_index != -1 )
390 {
391 int nSpecialFieldIdx = expr->field_index -
392 nLayerFieldCount;
393 return nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
394 nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
395 nSpecialFieldIdx == SPF_OGR_GEOM_AREA;
396 }
397 }
398 else if (expr->eNodeType == SNT_OPERATION)
399 {
400 for( int i = 0; i < expr->nSubExprCount; i++ )
401 {
402 if (ContainGeomSpecialField(expr->papoSubExpr[i],
403 nLayerFieldCount))
404 return TRUE;
405 }
406 }
407 return FALSE;
408 }
409
410 /************************************************************************/
411 /* AttributeFilterEvaluationNeedsGeometry() */
412 /************************************************************************/
413
AttributeFilterEvaluationNeedsGeometry()414 int OGRLayer::AttributeFilterEvaluationNeedsGeometry()
415 {
416 if( !m_poAttrQuery )
417 return FALSE;
418
419 swq_expr_node* expr = (swq_expr_node *) m_poAttrQuery->GetSWQExpr();
420 int nLayerFieldCount = GetLayerDefn()->GetFieldCount();
421
422 return ContainGeomSpecialField(expr, nLayerFieldCount);
423 }
424
425 /************************************************************************/
426 /* OGR_L_SetAttributeFilter() */
427 /************************************************************************/
428
OGR_L_SetAttributeFilter(OGRLayerH hLayer,const char * pszQuery)429 OGRErr OGR_L_SetAttributeFilter( OGRLayerH hLayer, const char *pszQuery )
430
431 {
432 VALIDATE_POINTER1( hLayer, "OGR_L_SetAttributeFilter", OGRERR_INVALID_HANDLE );
433
434 #ifdef OGRAPISPY_ENABLED
435 if( bOGRAPISpyEnabled )
436 OGRAPISpy_L_SetAttributeFilter(hLayer, pszQuery);
437 #endif
438
439 return ((OGRLayer *) hLayer)->SetAttributeFilter( pszQuery );
440 }
441
442 /************************************************************************/
443 /* GetFeature() */
444 /************************************************************************/
445
GetFeature(GIntBig nFID)446 OGRFeature *OGRLayer::GetFeature( GIntBig nFID )
447
448 {
449 OGRFeature *poFeature;
450
451 /* Save old attribute and spatial filters */
452 char* pszOldFilter = m_pszAttrQueryString ? CPLStrdup(m_pszAttrQueryString) : NULL;
453 OGRGeometry* poOldFilterGeom = ( m_poFilterGeom != NULL ) ? m_poFilterGeom->clone() : NULL;
454 int iOldGeomFieldFilter = m_iGeomFieldFilter;
455 /* Unset filters */
456 SetAttributeFilter(NULL);
457 SetSpatialFilter(0, NULL);
458
459 ResetReading();
460 while( (poFeature = GetNextFeature()) != NULL )
461 {
462 if( poFeature->GetFID() == nFID )
463 break;
464 else
465 delete poFeature;
466 }
467
468 /* Restore filters */
469 SetAttributeFilter(pszOldFilter);
470 CPLFree(pszOldFilter);
471 SetSpatialFilter(iOldGeomFieldFilter, poOldFilterGeom);
472 delete poOldFilterGeom;
473
474 return poFeature;
475 }
476
477 /************************************************************************/
478 /* OGR_L_GetFeature() */
479 /************************************************************************/
480
OGR_L_GetFeature(OGRLayerH hLayer,GIntBig nFeatureId)481 OGRFeatureH OGR_L_GetFeature( OGRLayerH hLayer, GIntBig nFeatureId )
482
483 {
484 VALIDATE_POINTER1( hLayer, "OGR_L_GetFeature", NULL );
485
486 #ifdef OGRAPISPY_ENABLED
487 if( bOGRAPISpyEnabled )
488 OGRAPISpy_L_GetFeature(hLayer, nFeatureId);
489 #endif
490
491 return (OGRFeatureH) ((OGRLayer *)hLayer)->GetFeature( nFeatureId );
492 }
493
494 /************************************************************************/
495 /* SetNextByIndex() */
496 /************************************************************************/
497
SetNextByIndex(GIntBig nIndex)498 OGRErr OGRLayer::SetNextByIndex( GIntBig nIndex )
499
500 {
501 OGRFeature *poFeature;
502
503 if( nIndex < 0 )
504 return OGRERR_FAILURE;
505
506 ResetReading();
507 while( nIndex-- > 0 )
508 {
509 poFeature = GetNextFeature();
510 if( poFeature == NULL )
511 return OGRERR_FAILURE;
512
513 delete poFeature;
514 }
515
516 return OGRERR_NONE;
517 }
518
519 /************************************************************************/
520 /* OGR_L_SetNextByIndex() */
521 /************************************************************************/
522
OGR_L_SetNextByIndex(OGRLayerH hLayer,GIntBig nIndex)523 OGRErr OGR_L_SetNextByIndex( OGRLayerH hLayer, GIntBig nIndex )
524
525 {
526 VALIDATE_POINTER1( hLayer, "OGR_L_SetNextByIndex", OGRERR_INVALID_HANDLE );
527
528 #ifdef OGRAPISPY_ENABLED
529 if( bOGRAPISpyEnabled )
530 OGRAPISpy_L_SetNextByIndex(hLayer, nIndex);
531 #endif
532
533 return ((OGRLayer *)hLayer)->SetNextByIndex( nIndex );
534 }
535
536 /************************************************************************/
537 /* OGR_L_GetNextFeature() */
538 /************************************************************************/
539
OGR_L_GetNextFeature(OGRLayerH hLayer)540 OGRFeatureH OGR_L_GetNextFeature( OGRLayerH hLayer )
541
542 {
543 VALIDATE_POINTER1( hLayer, "OGR_L_GetNextFeature", NULL );
544
545 #ifdef OGRAPISPY_ENABLED
546 if( bOGRAPISpyEnabled )
547 OGRAPISpy_L_GetNextFeature(hLayer);
548 #endif
549
550 return (OGRFeatureH) ((OGRLayer *)hLayer)->GetNextFeature();
551 }
552
553 /************************************************************************/
554 /* ConvertNonLinearGeomsIfNecessary() */
555 /************************************************************************/
556
ConvertNonLinearGeomsIfNecessary(OGRFeature * poFeature)557 void OGRLayer::ConvertNonLinearGeomsIfNecessary( OGRFeature *poFeature )
558 {
559 if( !TestCapability(OLCCurveGeometries) )
560 {
561 int nGeomFieldCount = GetLayerDefn()->GetGeomFieldCount();
562 for(int i=0;i<nGeomFieldCount;i++)
563 {
564 OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
565 if( poGeom != NULL && OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
566 {
567 OGRwkbGeometryType eTargetType = OGR_GT_GetLinear(poGeom->getGeometryType());
568 poFeature->SetGeomFieldDirectly(i,
569 OGRGeometryFactory::forceTo(poFeature->StealGeometry(i), eTargetType));
570 }
571 }
572 }
573 }
574
575 /************************************************************************/
576 /* SetFeature() */
577 /************************************************************************/
578
SetFeature(OGRFeature * poFeature)579 OGRErr OGRLayer::SetFeature( OGRFeature *poFeature )
580
581 {
582 ConvertNonLinearGeomsIfNecessary(poFeature);
583 return ISetFeature(poFeature);
584 }
585
586 /************************************************************************/
587 /* ISetFeature() */
588 /************************************************************************/
589
ISetFeature(OGRFeature *)590 OGRErr OGRLayer::ISetFeature( OGRFeature * )
591
592 {
593 return OGRERR_UNSUPPORTED_OPERATION;
594 }
595
596 /************************************************************************/
597 /* OGR_L_SetFeature() */
598 /************************************************************************/
599
OGR_L_SetFeature(OGRLayerH hLayer,OGRFeatureH hFeat)600 OGRErr OGR_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
601
602 {
603 VALIDATE_POINTER1( hLayer, "OGR_L_SetFeature", OGRERR_INVALID_HANDLE );
604 VALIDATE_POINTER1( hFeat, "OGR_L_SetFeature", OGRERR_INVALID_HANDLE );
605
606 #ifdef OGRAPISPY_ENABLED
607 if( bOGRAPISpyEnabled )
608 OGRAPISpy_L_SetFeature(hLayer, hFeat);
609 #endif
610
611 return ((OGRLayer *)hLayer)->SetFeature( (OGRFeature *) hFeat );
612 }
613
614 /************************************************************************/
615 /* CreateFeature() */
616 /************************************************************************/
617
CreateFeature(OGRFeature * poFeature)618 OGRErr OGRLayer::CreateFeature( OGRFeature *poFeature )
619
620 {
621 ConvertNonLinearGeomsIfNecessary(poFeature);
622 return ICreateFeature(poFeature);
623 }
624
625 /************************************************************************/
626 /* ICreateFeature() */
627 /************************************************************************/
628
ICreateFeature(OGRFeature *)629 OGRErr OGRLayer::ICreateFeature( OGRFeature * )
630
631 {
632 return OGRERR_UNSUPPORTED_OPERATION;
633 }
634
635 /************************************************************************/
636 /* OGR_L_CreateFeature() */
637 /************************************************************************/
638
OGR_L_CreateFeature(OGRLayerH hLayer,OGRFeatureH hFeat)639 OGRErr OGR_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
640
641 {
642 VALIDATE_POINTER1( hLayer, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
643 VALIDATE_POINTER1( hFeat, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
644
645 #ifdef OGRAPISPY_ENABLED
646 if( bOGRAPISpyEnabled )
647 OGRAPISpy_L_CreateFeature(hLayer, hFeat);
648 #endif
649
650 return ((OGRLayer *) hLayer)->CreateFeature( (OGRFeature *) hFeat );
651 }
652
653 /************************************************************************/
654 /* CreateField() */
655 /************************************************************************/
656
CreateField(OGRFieldDefn * poField,int bApproxOK)657 OGRErr OGRLayer::CreateField( OGRFieldDefn * poField, int bApproxOK )
658
659 {
660 (void) poField;
661 (void) bApproxOK;
662
663 CPLError( CE_Failure, CPLE_NotSupported,
664 "CreateField() not supported by this layer.\n" );
665
666 return OGRERR_UNSUPPORTED_OPERATION;
667 }
668
669 /************************************************************************/
670 /* OGR_L_CreateField() */
671 /************************************************************************/
672
OGR_L_CreateField(OGRLayerH hLayer,OGRFieldDefnH hField,int bApproxOK)673 OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
674 int bApproxOK )
675
676 {
677 VALIDATE_POINTER1( hLayer, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
678 VALIDATE_POINTER1( hField, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
679
680 #ifdef OGRAPISPY_ENABLED
681 if( bOGRAPISpyEnabled )
682 OGRAPISpy_L_CreateField(hLayer, hField, bApproxOK);
683 #endif
684
685 return ((OGRLayer *) hLayer)->CreateField( (OGRFieldDefn *) hField,
686 bApproxOK );
687 }
688
689 /************************************************************************/
690 /* DeleteField() */
691 /************************************************************************/
692
DeleteField(int iField)693 OGRErr OGRLayer::DeleteField( int iField )
694
695 {
696 (void) iField;
697
698 CPLError( CE_Failure, CPLE_NotSupported,
699 "DeleteField() not supported by this layer.\n" );
700
701 return OGRERR_UNSUPPORTED_OPERATION;
702 }
703
704 /************************************************************************/
705 /* OGR_L_DeleteField() */
706 /************************************************************************/
707
OGR_L_DeleteField(OGRLayerH hLayer,int iField)708 OGRErr OGR_L_DeleteField( OGRLayerH hLayer, int iField )
709
710 {
711 VALIDATE_POINTER1( hLayer, "OGR_L_DeleteField", OGRERR_INVALID_HANDLE );
712
713 #ifdef OGRAPISPY_ENABLED
714 if( bOGRAPISpyEnabled )
715 OGRAPISpy_L_DeleteField(hLayer, iField);
716 #endif
717
718 return ((OGRLayer *) hLayer)->DeleteField( iField );
719 }
720
721 /************************************************************************/
722 /* ReorderFields() */
723 /************************************************************************/
724
ReorderFields(int * panMap)725 OGRErr OGRLayer::ReorderFields( int* panMap )
726
727 {
728 (void) panMap;
729
730 CPLError( CE_Failure, CPLE_NotSupported,
731 "ReorderFields() not supported by this layer.\n" );
732
733 return OGRERR_UNSUPPORTED_OPERATION;
734 }
735
736 /************************************************************************/
737 /* OGR_L_ReorderFields() */
738 /************************************************************************/
739
OGR_L_ReorderFields(OGRLayerH hLayer,int * panMap)740 OGRErr OGR_L_ReorderFields( OGRLayerH hLayer, int* panMap )
741
742 {
743 VALIDATE_POINTER1( hLayer, "OGR_L_ReorderFields", OGRERR_INVALID_HANDLE );
744
745 #ifdef OGRAPISPY_ENABLED
746 if( bOGRAPISpyEnabled )
747 OGRAPISpy_L_ReorderFields(hLayer, panMap);
748 #endif
749
750 return ((OGRLayer *) hLayer)->ReorderFields( panMap );
751 }
752
753 /************************************************************************/
754 /* ReorderField() */
755 /************************************************************************/
756
ReorderField(int iOldFieldPos,int iNewFieldPos)757 OGRErr OGRLayer::ReorderField( int iOldFieldPos, int iNewFieldPos )
758
759 {
760 OGRErr eErr;
761
762 int nFieldCount = GetLayerDefn()->GetFieldCount();
763
764 if (iOldFieldPos < 0 || iOldFieldPos >= nFieldCount)
765 {
766 CPLError( CE_Failure, CPLE_NotSupported,
767 "Invalid field index");
768 return OGRERR_FAILURE;
769 }
770 if (iNewFieldPos < 0 || iNewFieldPos >= nFieldCount)
771 {
772 CPLError( CE_Failure, CPLE_NotSupported,
773 "Invalid field index");
774 return OGRERR_FAILURE;
775 }
776 if (iNewFieldPos == iOldFieldPos)
777 return OGRERR_NONE;
778
779 int* panMap = (int*) CPLMalloc(sizeof(int) * nFieldCount);
780 int i;
781 if (iOldFieldPos < iNewFieldPos)
782 {
783 /* "0","1","2","3","4" (1,3) -> "0","2","3","1","4" */
784 for(i=0;i<iOldFieldPos;i++)
785 panMap[i] = i;
786 for(;i<iNewFieldPos;i++)
787 panMap[i] = i + 1;
788 panMap[iNewFieldPos] = iOldFieldPos;
789 for(i=iNewFieldPos+1;i<nFieldCount;i++)
790 panMap[i] = i;
791 }
792 else
793 {
794 /* "0","1","2","3","4" (3,1) -> "0","3","1","2","4" */
795 for(i=0;i<iNewFieldPos;i++)
796 panMap[i] = i;
797 panMap[iNewFieldPos] = iOldFieldPos;
798 for(i=iNewFieldPos+1;i<=iOldFieldPos;i++)
799 panMap[i] = i - 1;
800 for(;i<nFieldCount;i++)
801 panMap[i] = i;
802 }
803
804 eErr = ReorderFields(panMap);
805
806 CPLFree(panMap);
807
808 return eErr;
809 }
810
811 /************************************************************************/
812 /* OGR_L_ReorderField() */
813 /************************************************************************/
814
OGR_L_ReorderField(OGRLayerH hLayer,int iOldFieldPos,int iNewFieldPos)815 OGRErr OGR_L_ReorderField( OGRLayerH hLayer, int iOldFieldPos, int iNewFieldPos )
816
817 {
818 VALIDATE_POINTER1( hLayer, "OGR_L_ReorderField", OGRERR_INVALID_HANDLE );
819
820 #ifdef OGRAPISPY_ENABLED
821 if( bOGRAPISpyEnabled )
822 OGRAPISpy_L_ReorderField(hLayer, iOldFieldPos, iNewFieldPos);
823 #endif
824
825 return ((OGRLayer *) hLayer)->ReorderField( iOldFieldPos, iNewFieldPos );
826 }
827
828 /************************************************************************/
829 /* AlterFieldDefn() */
830 /************************************************************************/
831
AlterFieldDefn(int iField,OGRFieldDefn * poNewFieldDefn,int nFlags)832 OGRErr OGRLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
833 int nFlags )
834
835 {
836 (void) iField;
837 (void) poNewFieldDefn;
838 (void) nFlags;
839
840 CPLError( CE_Failure, CPLE_NotSupported,
841 "AlterFieldDefn() not supported by this layer.\n" );
842
843 return OGRERR_UNSUPPORTED_OPERATION;
844 }
845
846 /************************************************************************/
847 /* OGR_L_AlterFieldDefn() */
848 /************************************************************************/
849
OGR_L_AlterFieldDefn(OGRLayerH hLayer,int iField,OGRFieldDefnH hNewFieldDefn,int nFlags)850 OGRErr OGR_L_AlterFieldDefn( OGRLayerH hLayer, int iField, OGRFieldDefnH hNewFieldDefn,
851 int nFlags )
852
853 {
854 VALIDATE_POINTER1( hLayer, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE );
855 VALIDATE_POINTER1( hNewFieldDefn, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE );
856
857 #ifdef OGRAPISPY_ENABLED
858 if( bOGRAPISpyEnabled )
859 OGRAPISpy_L_AlterFieldDefn(hLayer, iField, hNewFieldDefn, nFlags);
860 #endif
861
862 return ((OGRLayer *) hLayer)->AlterFieldDefn( iField, (OGRFieldDefn*) hNewFieldDefn, nFlags );
863 }
864
865 /************************************************************************/
866 /* CreateGeomField() */
867 /************************************************************************/
868
CreateGeomField(OGRGeomFieldDefn * poField,int bApproxOK)869 OGRErr OGRLayer::CreateGeomField( OGRGeomFieldDefn * poField, int bApproxOK )
870
871 {
872 (void) poField;
873 (void) bApproxOK;
874
875 CPLError( CE_Failure, CPLE_NotSupported,
876 "CreateGeomField() not supported by this layer.\n" );
877
878 return OGRERR_UNSUPPORTED_OPERATION;
879 }
880
881 /************************************************************************/
882 /* OGR_L_CreateGeomField() */
883 /************************************************************************/
884
OGR_L_CreateGeomField(OGRLayerH hLayer,OGRGeomFieldDefnH hField,int bApproxOK)885 OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
886 int bApproxOK )
887
888 {
889 VALIDATE_POINTER1( hLayer, "OGR_L_CreateGeomField", OGRERR_INVALID_HANDLE );
890 VALIDATE_POINTER1( hField, "OGR_L_CreateGeomField", OGRERR_INVALID_HANDLE );
891
892 #ifdef OGRAPISPY_ENABLED
893 if( bOGRAPISpyEnabled )
894 OGRAPISpy_L_CreateGeomField(hLayer, hField, bApproxOK);
895 #endif
896
897 return ((OGRLayer *) hLayer)->CreateGeomField( (OGRGeomFieldDefn *) hField,
898 bApproxOK );
899 }
900
901 /************************************************************************/
902 /* StartTransaction() */
903 /************************************************************************/
904
StartTransaction()905 OGRErr OGRLayer::StartTransaction()
906
907 {
908 return OGRERR_NONE;
909 }
910
911 /************************************************************************/
912 /* OGR_L_StartTransaction() */
913 /************************************************************************/
914
OGR_L_StartTransaction(OGRLayerH hLayer)915 OGRErr OGR_L_StartTransaction( OGRLayerH hLayer )
916
917 {
918 VALIDATE_POINTER1( hLayer, "OGR_L_StartTransaction", OGRERR_INVALID_HANDLE );
919
920 #ifdef OGRAPISPY_ENABLED
921 if( bOGRAPISpyEnabled )
922 OGRAPISpy_L_StartTransaction(hLayer);
923 #endif
924
925 return ((OGRLayer *)hLayer)->StartTransaction();
926 }
927
928 /************************************************************************/
929 /* CommitTransaction() */
930 /************************************************************************/
931
CommitTransaction()932 OGRErr OGRLayer::CommitTransaction()
933
934 {
935 return OGRERR_NONE;
936 }
937
938 /************************************************************************/
939 /* OGR_L_CommitTransaction() */
940 /************************************************************************/
941
OGR_L_CommitTransaction(OGRLayerH hLayer)942 OGRErr OGR_L_CommitTransaction( OGRLayerH hLayer )
943
944 {
945 VALIDATE_POINTER1( hLayer, "OGR_L_CommitTransaction", OGRERR_INVALID_HANDLE );
946
947 #ifdef OGRAPISPY_ENABLED
948 if( bOGRAPISpyEnabled )
949 OGRAPISpy_L_CommitTransaction(hLayer);
950 #endif
951
952 return ((OGRLayer *)hLayer)->CommitTransaction();
953 }
954
955 /************************************************************************/
956 /* RollbackTransaction() */
957 /************************************************************************/
958
RollbackTransaction()959 OGRErr OGRLayer::RollbackTransaction()
960
961 {
962 return OGRERR_UNSUPPORTED_OPERATION;
963 }
964
965 /************************************************************************/
966 /* OGR_L_RollbackTransaction() */
967 /************************************************************************/
968
OGR_L_RollbackTransaction(OGRLayerH hLayer)969 OGRErr OGR_L_RollbackTransaction( OGRLayerH hLayer )
970
971 {
972 VALIDATE_POINTER1( hLayer, "OGR_L_RollbackTransaction", OGRERR_INVALID_HANDLE );
973
974 #ifdef OGRAPISPY_ENABLED
975 if( bOGRAPISpyEnabled )
976 OGRAPISpy_L_RollbackTransaction(hLayer);
977 #endif
978
979 return ((OGRLayer *)hLayer)->RollbackTransaction();
980 }
981
982 /************************************************************************/
983 /* OGR_L_GetLayerDefn() */
984 /************************************************************************/
985
OGR_L_GetLayerDefn(OGRLayerH hLayer)986 OGRFeatureDefnH OGR_L_GetLayerDefn( OGRLayerH hLayer )
987
988 {
989 VALIDATE_POINTER1( hLayer, "OGR_L_GetLayerDefn", NULL );
990
991 #ifdef OGRAPISPY_ENABLED
992 if( bOGRAPISpyEnabled )
993 OGRAPISpy_L_GetLayerDefn(hLayer);
994 #endif
995
996 return (OGRFeatureDefnH) ((OGRLayer *)hLayer)->GetLayerDefn();
997 }
998
999 /************************************************************************/
1000 /* OGR_L_FindFieldIndex() */
1001 /************************************************************************/
1002
OGR_L_FindFieldIndex(OGRLayerH hLayer,const char * pszFieldName,int bExactMatch)1003 int OGR_L_FindFieldIndex( OGRLayerH hLayer, const char *pszFieldName, int bExactMatch )
1004
1005 {
1006 VALIDATE_POINTER1( hLayer, "OGR_L_FindFieldIndex", -1 );
1007
1008 #ifdef OGRAPISPY_ENABLED
1009 if( bOGRAPISpyEnabled )
1010 OGRAPISpy_L_FindFieldIndex(hLayer, pszFieldName, bExactMatch);
1011 #endif
1012
1013 return ((OGRLayer *)hLayer)->FindFieldIndex( pszFieldName, bExactMatch );
1014 }
1015
1016 /************************************************************************/
1017 /* FindFieldIndex() */
1018 /************************************************************************/
1019
FindFieldIndex(const char * pszFieldName,CPL_UNUSED int bExactMatch)1020 int OGRLayer::FindFieldIndex( const char *pszFieldName, CPL_UNUSED int bExactMatch )
1021 {
1022 return GetLayerDefn()->GetFieldIndex( pszFieldName );
1023 }
1024
1025 /************************************************************************/
1026 /* GetSpatialRef() */
1027 /************************************************************************/
1028
GetSpatialRef()1029 OGRSpatialReference *OGRLayer::GetSpatialRef()
1030 {
1031 if( GetLayerDefn()->GetGeomFieldCount() > 0 )
1032 return GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef();
1033 else
1034 return NULL;
1035 }
1036
1037 /************************************************************************/
1038 /* OGR_L_GetSpatialRef() */
1039 /************************************************************************/
1040
OGR_L_GetSpatialRef(OGRLayerH hLayer)1041 OGRSpatialReferenceH OGR_L_GetSpatialRef( OGRLayerH hLayer )
1042
1043 {
1044 VALIDATE_POINTER1( hLayer, "OGR_L_GetSpatialRef", NULL );
1045
1046 #ifdef OGRAPISPY_ENABLED
1047 if( bOGRAPISpyEnabled )
1048 OGRAPISpy_L_GetSpatialRef(hLayer);
1049 #endif
1050
1051 return (OGRSpatialReferenceH) ((OGRLayer *) hLayer)->GetSpatialRef();
1052 }
1053
1054 /************************************************************************/
1055 /* OGR_L_TestCapability() */
1056 /************************************************************************/
1057
OGR_L_TestCapability(OGRLayerH hLayer,const char * pszCap)1058 int OGR_L_TestCapability( OGRLayerH hLayer, const char *pszCap )
1059
1060 {
1061 VALIDATE_POINTER1( hLayer, "OGR_L_TestCapability", 0 );
1062 VALIDATE_POINTER1( pszCap, "OGR_L_TestCapability", 0 );
1063
1064 #ifdef OGRAPISPY_ENABLED
1065 if( bOGRAPISpyEnabled )
1066 OGRAPISpy_L_TestCapability(hLayer, pszCap);
1067 #endif
1068
1069 return ((OGRLayer *) hLayer)->TestCapability( pszCap );
1070 }
1071
1072 /************************************************************************/
1073 /* GetSpatialFilter() */
1074 /************************************************************************/
1075
GetSpatialFilter()1076 OGRGeometry *OGRLayer::GetSpatialFilter()
1077
1078 {
1079 return m_poFilterGeom;
1080 }
1081
1082 /************************************************************************/
1083 /* OGR_L_GetSpatialFilter() */
1084 /************************************************************************/
1085
OGR_L_GetSpatialFilter(OGRLayerH hLayer)1086 OGRGeometryH OGR_L_GetSpatialFilter( OGRLayerH hLayer )
1087
1088 {
1089 VALIDATE_POINTER1( hLayer, "OGR_L_GetSpatialFilter", NULL );
1090
1091 #ifdef OGRAPISPY_ENABLED
1092 if( bOGRAPISpyEnabled )
1093 OGRAPISpy_L_GetSpatialFilter(hLayer);
1094 #endif
1095
1096 return (OGRGeometryH) ((OGRLayer *) hLayer)->GetSpatialFilter();
1097 }
1098
1099 /************************************************************************/
1100 /* SetSpatialFilter() */
1101 /************************************************************************/
1102
SetSpatialFilter(OGRGeometry * poGeomIn)1103 void OGRLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
1104
1105 {
1106 m_iGeomFieldFilter = 0;
1107 if( InstallFilter( poGeomIn ) )
1108 ResetReading();
1109 }
1110
1111
SetSpatialFilter(int iGeomField,OGRGeometry * poGeomIn)1112 void OGRLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
1113
1114 {
1115 if( iGeomField == 0 )
1116 {
1117 m_iGeomFieldFilter = iGeomField;
1118 SetSpatialFilter( poGeomIn );
1119 }
1120 else
1121 {
1122 if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
1123 {
1124 CPLError(CE_Failure, CPLE_AppDefined,
1125 "Invalid geometry field index : %d", iGeomField);
1126 return;
1127 }
1128
1129 m_iGeomFieldFilter = iGeomField;
1130 if( InstallFilter( poGeomIn ) )
1131 ResetReading();
1132 }
1133 }
1134
1135 /************************************************************************/
1136 /* OGR_L_SetSpatialFilter() */
1137 /************************************************************************/
1138
OGR_L_SetSpatialFilter(OGRLayerH hLayer,OGRGeometryH hGeom)1139 void OGR_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom )
1140
1141 {
1142 VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilter" );
1143
1144 #ifdef OGRAPISPY_ENABLED
1145 if( bOGRAPISpyEnabled )
1146 OGRAPISpy_L_SetSpatialFilter(hLayer, hGeom);
1147 #endif
1148
1149 ((OGRLayer *) hLayer)->SetSpatialFilter( (OGRGeometry *) hGeom );
1150 }
1151
1152 /************************************************************************/
1153 /* OGR_L_SetSpatialFilterEx() */
1154 /************************************************************************/
1155
OGR_L_SetSpatialFilterEx(OGRLayerH hLayer,int iGeomField,OGRGeometryH hGeom)1156 void OGR_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField,
1157 OGRGeometryH hGeom )
1158
1159 {
1160 VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterEx" );
1161
1162 #ifdef OGRAPISPY_ENABLED
1163 if( bOGRAPISpyEnabled )
1164 OGRAPISpy_L_SetSpatialFilterEx(hLayer, iGeomField, hGeom);
1165 #endif
1166
1167 ((OGRLayer *) hLayer)->SetSpatialFilter( iGeomField, (OGRGeometry *) hGeom );
1168 }
1169 /************************************************************************/
1170 /* SetSpatialFilterRect() */
1171 /************************************************************************/
1172
SetSpatialFilterRect(double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1173 void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
1174 double dfMaxX, double dfMaxY )
1175
1176 {
1177 SetSpatialFilterRect( 0, dfMinX, dfMinY, dfMaxX, dfMaxY );
1178 }
1179
1180
SetSpatialFilterRect(int iGeomField,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1181 void OGRLayer::SetSpatialFilterRect( int iGeomField,
1182 double dfMinX, double dfMinY,
1183 double dfMaxX, double dfMaxY )
1184
1185 {
1186 OGRLinearRing oRing;
1187 OGRPolygon oPoly;
1188
1189 oRing.addPoint( dfMinX, dfMinY );
1190 oRing.addPoint( dfMinX, dfMaxY );
1191 oRing.addPoint( dfMaxX, dfMaxY );
1192 oRing.addPoint( dfMaxX, dfMinY );
1193 oRing.addPoint( dfMinX, dfMinY );
1194
1195 oPoly.addRing( &oRing );
1196
1197 if( iGeomField == 0 )
1198 /* for drivers that only overload SetSpatialFilter(OGRGeometry*) */
1199 SetSpatialFilter( &oPoly );
1200 else
1201 SetSpatialFilter( iGeomField, &oPoly );
1202 }
1203
1204 /************************************************************************/
1205 /* OGR_L_SetSpatialFilterRect() */
1206 /************************************************************************/
1207
OGR_L_SetSpatialFilterRect(OGRLayerH hLayer,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1208 void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer,
1209 double dfMinX, double dfMinY,
1210 double dfMaxX, double dfMaxY )
1211
1212 {
1213 VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterRect" );
1214
1215 #ifdef OGRAPISPY_ENABLED
1216 if( bOGRAPISpyEnabled )
1217 OGRAPISpy_L_SetSpatialFilterRect(hLayer, dfMinX, dfMinY, dfMaxX, dfMaxY);
1218 #endif
1219
1220 ((OGRLayer *) hLayer)->SetSpatialFilterRect( dfMinX, dfMinY,
1221 dfMaxX, dfMaxY );
1222 }
1223
1224 /************************************************************************/
1225 /* OGR_L_SetSpatialFilterRectEx() */
1226 /************************************************************************/
1227
OGR_L_SetSpatialFilterRectEx(OGRLayerH hLayer,int iGeomField,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1228 void OGR_L_SetSpatialFilterRectEx( OGRLayerH hLayer,
1229 int iGeomField,
1230 double dfMinX, double dfMinY,
1231 double dfMaxX, double dfMaxY )
1232
1233 {
1234 VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterRectEx" );
1235
1236 #ifdef OGRAPISPY_ENABLED
1237 if( bOGRAPISpyEnabled )
1238 OGRAPISpy_L_SetSpatialFilterRectEx(hLayer, iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
1239 #endif
1240
1241 ((OGRLayer *) hLayer)->SetSpatialFilterRect( iGeomField,
1242 dfMinX, dfMinY,
1243 dfMaxX, dfMaxY );
1244 }
1245
1246 /************************************************************************/
1247 /* InstallFilter() */
1248 /* */
1249 /* This method is only intended to be used from within */
1250 /* drivers, normally from the SetSpatialFilter() method. */
1251 /* It installs a filter, and also tests it to see if it is */
1252 /* rectangular. If so, it this is kept track of alongside the */
1253 /* filter geometry itself so we can do cheaper comparisons in */
1254 /* the FilterGeometry() call. */
1255 /* */
1256 /* Returns TRUE if the newly installed filter differs in some */
1257 /* way from the current one. */
1258 /************************************************************************/
1259
InstallFilter(OGRGeometry * poFilter)1260 int OGRLayer::InstallFilter( OGRGeometry * poFilter )
1261
1262 {
1263 if( m_poFilterGeom == NULL && poFilter == NULL )
1264 return FALSE;
1265
1266 /* -------------------------------------------------------------------- */
1267 /* Replace the existing filter. */
1268 /* -------------------------------------------------------------------- */
1269 if( m_poFilterGeom != NULL )
1270 {
1271 delete m_poFilterGeom;
1272 m_poFilterGeom = NULL;
1273 }
1274
1275 if( m_pPreparedFilterGeom != NULL )
1276 {
1277 OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
1278 m_pPreparedFilterGeom = NULL;
1279 }
1280
1281 if( poFilter != NULL )
1282 m_poFilterGeom = poFilter->clone();
1283
1284 m_bFilterIsEnvelope = FALSE;
1285
1286 if( m_poFilterGeom == NULL )
1287 return TRUE;
1288
1289 if( m_poFilterGeom != NULL )
1290 m_poFilterGeom->getEnvelope( &m_sFilterEnvelope );
1291
1292 /* Compile geometry filter as a prepared geometry */
1293 m_pPreparedFilterGeom = OGRCreatePreparedGeometry(m_poFilterGeom);
1294
1295 /* -------------------------------------------------------------------- */
1296 /* Now try to determine if the filter is really a rectangle. */
1297 /* -------------------------------------------------------------------- */
1298 if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
1299 return TRUE;
1300
1301 OGRPolygon *poPoly = (OGRPolygon *) m_poFilterGeom;
1302
1303 if( poPoly->getNumInteriorRings() != 0 )
1304 return TRUE;
1305
1306 OGRLinearRing *poRing = poPoly->getExteriorRing();
1307 if (poRing == NULL)
1308 return TRUE;
1309
1310 if( poRing->getNumPoints() > 5 || poRing->getNumPoints() < 4 )
1311 return TRUE;
1312
1313 // If the ring has 5 points, the last should be the first.
1314 if( poRing->getNumPoints() == 5
1315 && ( poRing->getX(0) != poRing->getX(4)
1316 || poRing->getY(0) != poRing->getY(4) ) )
1317 return TRUE;
1318
1319 // Polygon with first segment in "y" direction.
1320 if( poRing->getX(0) == poRing->getX(1)
1321 && poRing->getY(1) == poRing->getY(2)
1322 && poRing->getX(2) == poRing->getX(3)
1323 && poRing->getY(3) == poRing->getY(0) )
1324 m_bFilterIsEnvelope = TRUE;
1325
1326 // Polygon with first segment in "x" direction.
1327 if( poRing->getY(0) == poRing->getY(1)
1328 && poRing->getX(1) == poRing->getX(2)
1329 && poRing->getY(2) == poRing->getY(3)
1330 && poRing->getX(3) == poRing->getX(0) )
1331 m_bFilterIsEnvelope = TRUE;
1332
1333 return TRUE;
1334 }
1335
1336 /************************************************************************/
1337 /* FilterGeometry() */
1338 /* */
1339 /* Compare the passed in geometry to the currently installed */
1340 /* filter. Optimize for case where filter is just an */
1341 /* envelope. */
1342 /************************************************************************/
1343
FilterGeometry(OGRGeometry * poGeometry)1344 int OGRLayer::FilterGeometry( OGRGeometry *poGeometry )
1345
1346 {
1347 /* -------------------------------------------------------------------- */
1348 /* In trivial cases of new filter or target geometry, we accept */
1349 /* an intersection. No geometry is taken to mean "the whole */
1350 /* world". */
1351 /* -------------------------------------------------------------------- */
1352 if( m_poFilterGeom == NULL )
1353 return TRUE;
1354
1355 if( poGeometry == NULL )
1356 return TRUE;
1357
1358 /* -------------------------------------------------------------------- */
1359 /* Compute the target geometry envelope, and if there is no */
1360 /* intersection between the envelopes we are sure not to have */
1361 /* any intersection. */
1362 /* -------------------------------------------------------------------- */
1363 OGREnvelope sGeomEnv;
1364
1365 poGeometry->getEnvelope( &sGeomEnv );
1366
1367 if( sGeomEnv.MaxX < m_sFilterEnvelope.MinX
1368 || sGeomEnv.MaxY < m_sFilterEnvelope.MinY
1369 || m_sFilterEnvelope.MaxX < sGeomEnv.MinX
1370 || m_sFilterEnvelope.MaxY < sGeomEnv.MinY )
1371 return FALSE;
1372
1373
1374 /* -------------------------------------------------------------------- */
1375 /* If the filter geometry is its own envelope and if the */
1376 /* envelope of the geometry is inside the filter geometry, */
1377 /* the geometry itself is inside the filter geometry */
1378 /* -------------------------------------------------------------------- */
1379 if( m_bFilterIsEnvelope &&
1380 sGeomEnv.MinX >= m_sFilterEnvelope.MinX &&
1381 sGeomEnv.MinY >= m_sFilterEnvelope.MinY &&
1382 sGeomEnv.MaxX <= m_sFilterEnvelope.MaxX &&
1383 sGeomEnv.MaxY <= m_sFilterEnvelope.MaxY)
1384 {
1385 return TRUE;
1386 }
1387 else
1388 {
1389 /* -------------------------------------------------------------------- */
1390 /* If the filter geometry is its own envelope and if the */
1391 /* the geometry (line, or polygon without hole) h has at least one */
1392 /* point inside the filter geometry, the geometry itself is inside */
1393 /* the filter geometry. */
1394 /* -------------------------------------------------------------------- */
1395 if( m_bFilterIsEnvelope )
1396 {
1397 OGRLineString* poLS = NULL;
1398
1399 switch( wkbFlatten(poGeometry->getGeometryType()) )
1400 {
1401 case wkbPolygon:
1402 {
1403 OGRPolygon* poPoly = (OGRPolygon* )poGeometry;
1404 OGRLinearRing* poRing = poPoly->getExteriorRing();
1405 if (poRing != NULL && poPoly->getNumInteriorRings() == 0)
1406 {
1407 poLS = poRing;
1408 }
1409 break;
1410 }
1411
1412 case wkbLineString:
1413 poLS = (OGRLineString* )poGeometry;
1414 break;
1415
1416 default:
1417 break;
1418 }
1419
1420 if( poLS != NULL )
1421 {
1422 int nNumPoints = poLS->getNumPoints();
1423 for(int i = 0; i < nNumPoints; i++)
1424 {
1425 double x = poLS->getX(i);
1426 double y = poLS->getY(i);
1427 if (x >= m_sFilterEnvelope.MinX &&
1428 y >= m_sFilterEnvelope.MinY &&
1429 x <= m_sFilterEnvelope.MaxX &&
1430 y <= m_sFilterEnvelope.MaxY)
1431 {
1432 return TRUE;
1433 }
1434 }
1435 }
1436 }
1437
1438 /* -------------------------------------------------------------------- */
1439 /* Fallback to full intersect test (using GEOS) if we still */
1440 /* don't know for sure. */
1441 /* -------------------------------------------------------------------- */
1442 if( OGRGeometryFactory::haveGEOS() )
1443 {
1444 //CPLDebug("OGRLayer", "GEOS intersection");
1445 if( m_pPreparedFilterGeom != NULL )
1446 return OGRPreparedGeometryIntersects(m_pPreparedFilterGeom,
1447 poGeometry);
1448 else
1449 return m_poFilterGeom->Intersects( poGeometry );
1450 }
1451 else
1452 return TRUE;
1453 }
1454 }
1455
1456 /************************************************************************/
1457 /* OGR_L_ResetReading() */
1458 /************************************************************************/
1459
OGR_L_ResetReading(OGRLayerH hLayer)1460 void OGR_L_ResetReading( OGRLayerH hLayer )
1461
1462 {
1463 VALIDATE_POINTER0( hLayer, "OGR_L_ResetReading" );
1464
1465 #ifdef OGRAPISPY_ENABLED
1466 if( bOGRAPISpyEnabled )
1467 OGRAPISpy_L_ResetReading(hLayer);
1468 #endif
1469
1470 ((OGRLayer *) hLayer)->ResetReading();
1471 }
1472
1473 /************************************************************************/
1474 /* InitializeIndexSupport() */
1475 /* */
1476 /* This is only intended to be called by driver layer */
1477 /* implementations but we don't make it protected so that the */
1478 /* datasources can do it too if that is more appropriate. */
1479 /************************************************************************/
1480
InitializeIndexSupport(const char * pszFilename)1481 OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
1482
1483 {
1484 OGRErr eErr;
1485
1486 if (m_poAttrIndex != NULL)
1487 return OGRERR_NONE;
1488
1489 m_poAttrIndex = OGRCreateDefaultLayerIndex();
1490
1491 eErr = m_poAttrIndex->Initialize( pszFilename, this );
1492 if( eErr != OGRERR_NONE )
1493 {
1494 delete m_poAttrIndex;
1495 m_poAttrIndex = NULL;
1496 }
1497
1498 return eErr;
1499 }
1500
1501 /************************************************************************/
1502 /* SyncToDisk() */
1503 /************************************************************************/
1504
SyncToDisk()1505 OGRErr OGRLayer::SyncToDisk()
1506
1507 {
1508 return OGRERR_NONE;
1509 }
1510
1511 /************************************************************************/
1512 /* OGR_L_SyncToDisk() */
1513 /************************************************************************/
1514
OGR_L_SyncToDisk(OGRLayerH hLayer)1515 OGRErr OGR_L_SyncToDisk( OGRLayerH hLayer )
1516
1517 {
1518 VALIDATE_POINTER1( hLayer, "OGR_L_SyncToDisk", OGRERR_INVALID_HANDLE );
1519
1520 #ifdef OGRAPISPY_ENABLED
1521 if( bOGRAPISpyEnabled )
1522 OGRAPISpy_L_SyncToDisk(hLayer);
1523 #endif
1524
1525 return ((OGRLayer *) hLayer)->SyncToDisk();
1526 }
1527
1528 /************************************************************************/
1529 /* DeleteFeature() */
1530 /************************************************************************/
1531
DeleteFeature(CPL_UNUSED GIntBig nFID)1532 OGRErr OGRLayer::DeleteFeature( CPL_UNUSED GIntBig nFID )
1533 {
1534 return OGRERR_UNSUPPORTED_OPERATION;
1535 }
1536
1537 /************************************************************************/
1538 /* OGR_L_DeleteFeature() */
1539 /************************************************************************/
1540
OGR_L_DeleteFeature(OGRLayerH hLayer,GIntBig nFID)1541 OGRErr OGR_L_DeleteFeature( OGRLayerH hLayer, GIntBig nFID )
1542
1543 {
1544 VALIDATE_POINTER1( hLayer, "OGR_L_DeleteFeature", OGRERR_INVALID_HANDLE );
1545
1546 #ifdef OGRAPISPY_ENABLED
1547 if( bOGRAPISpyEnabled )
1548 OGRAPISpy_L_DeleteFeature(hLayer, nFID);
1549 #endif
1550
1551 return ((OGRLayer *) hLayer)->DeleteFeature( nFID );
1552 }
1553
1554 /************************************************************************/
1555 /* GetFeaturesRead() */
1556 /************************************************************************/
1557
GetFeaturesRead()1558 GIntBig OGRLayer::GetFeaturesRead()
1559
1560 {
1561 return m_nFeaturesRead;
1562 }
1563
1564 /************************************************************************/
1565 /* OGR_L_GetFeaturesRead() */
1566 /************************************************************************/
1567
OGR_L_GetFeaturesRead(OGRLayerH hLayer)1568 GIntBig OGR_L_GetFeaturesRead( OGRLayerH hLayer )
1569
1570 {
1571 VALIDATE_POINTER1( hLayer, "OGR_L_GetFeaturesRead", 0 );
1572
1573 return ((OGRLayer *) hLayer)->GetFeaturesRead();
1574 }
1575
1576 /************************************************************************/
1577 /* GetFIDColumn */
1578 /************************************************************************/
1579
GetFIDColumn()1580 const char *OGRLayer::GetFIDColumn()
1581
1582 {
1583 return "";
1584 }
1585
1586 /************************************************************************/
1587 /* OGR_L_GetFIDColumn() */
1588 /************************************************************************/
1589
OGR_L_GetFIDColumn(OGRLayerH hLayer)1590 const char *OGR_L_GetFIDColumn( OGRLayerH hLayer )
1591
1592 {
1593 VALIDATE_POINTER1( hLayer, "OGR_L_GetFIDColumn", NULL );
1594
1595 #ifdef OGRAPISPY_ENABLED
1596 if( bOGRAPISpyEnabled )
1597 OGRAPISpy_L_GetFIDColumn(hLayer);
1598 #endif
1599
1600 return ((OGRLayer *) hLayer)->GetFIDColumn();
1601 }
1602
1603 /************************************************************************/
1604 /* GetGeometryColumn() */
1605 /************************************************************************/
1606
GetGeometryColumn()1607 const char *OGRLayer::GetGeometryColumn()
1608
1609 {
1610 if( GetLayerDefn()->GetGeomFieldCount() > 0 )
1611 return GetLayerDefn()->GetGeomFieldDefn(0)->GetNameRef();
1612 else
1613 return "";
1614 }
1615
1616 /************************************************************************/
1617 /* OGR_L_GetGeometryColumn() */
1618 /************************************************************************/
1619
OGR_L_GetGeometryColumn(OGRLayerH hLayer)1620 const char *OGR_L_GetGeometryColumn( OGRLayerH hLayer )
1621
1622 {
1623 VALIDATE_POINTER1( hLayer, "OGR_L_GetGeometryColumn", NULL );
1624
1625 #ifdef OGRAPISPY_ENABLED
1626 if( bOGRAPISpyEnabled )
1627 OGRAPISpy_L_GetGeometryColumn(hLayer);
1628 #endif
1629
1630 return ((OGRLayer *) hLayer)->GetGeometryColumn();
1631 }
1632
1633 /************************************************************************/
1634 /* GetStyleTable() */
1635 /************************************************************************/
1636
GetStyleTable()1637 OGRStyleTable *OGRLayer::GetStyleTable()
1638 {
1639 return m_poStyleTable;
1640 }
1641
1642 /************************************************************************/
1643 /* SetStyleTableDirectly() */
1644 /************************************************************************/
1645
SetStyleTableDirectly(OGRStyleTable * poStyleTable)1646 void OGRLayer::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
1647 {
1648 if ( m_poStyleTable )
1649 delete m_poStyleTable;
1650 m_poStyleTable = poStyleTable;
1651 }
1652
1653 /************************************************************************/
1654 /* SetStyleTable() */
1655 /************************************************************************/
1656
SetStyleTable(OGRStyleTable * poStyleTable)1657 void OGRLayer::SetStyleTable(OGRStyleTable *poStyleTable)
1658 {
1659 if ( m_poStyleTable )
1660 delete m_poStyleTable;
1661 if ( poStyleTable )
1662 m_poStyleTable = poStyleTable->Clone();
1663 }
1664
1665 /************************************************************************/
1666 /* OGR_L_GetStyleTable() */
1667 /************************************************************************/
1668
OGR_L_GetStyleTable(OGRLayerH hLayer)1669 OGRStyleTableH OGR_L_GetStyleTable( OGRLayerH hLayer )
1670
1671 {
1672 VALIDATE_POINTER1( hLayer, "OGR_L_GetStyleTable", NULL );
1673
1674 return (OGRStyleTableH) ((OGRLayer *) hLayer)->GetStyleTable( );
1675 }
1676
1677 /************************************************************************/
1678 /* OGR_L_SetStyleTableDirectly() */
1679 /************************************************************************/
1680
OGR_L_SetStyleTableDirectly(OGRLayerH hLayer,OGRStyleTableH hStyleTable)1681 void OGR_L_SetStyleTableDirectly( OGRLayerH hLayer,
1682 OGRStyleTableH hStyleTable )
1683
1684 {
1685 VALIDATE_POINTER0( hLayer, "OGR_L_SetStyleTableDirectly" );
1686
1687 ((OGRLayer *) hLayer)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
1688 }
1689
1690 /************************************************************************/
1691 /* OGR_L_SetStyleTable() */
1692 /************************************************************************/
1693
OGR_L_SetStyleTable(OGRLayerH hLayer,OGRStyleTableH hStyleTable)1694 void OGR_L_SetStyleTable( OGRLayerH hLayer,
1695 OGRStyleTableH hStyleTable )
1696
1697 {
1698 VALIDATE_POINTER0( hLayer, "OGR_L_SetStyleTable" );
1699 VALIDATE_POINTER0( hStyleTable, "OGR_L_SetStyleTable" );
1700
1701 ((OGRLayer *) hLayer)->SetStyleTable( (OGRStyleTable *) hStyleTable);
1702 }
1703
1704 /************************************************************************/
1705 /* GetName() */
1706 /************************************************************************/
1707
GetName()1708 const char *OGRLayer::GetName()
1709
1710 {
1711 return GetLayerDefn()->GetName();
1712 }
1713
1714 /************************************************************************/
1715 /* OGR_L_GetName() */
1716 /************************************************************************/
1717
OGR_L_GetName(OGRLayerH hLayer)1718 const char* OGR_L_GetName( OGRLayerH hLayer )
1719
1720 {
1721 VALIDATE_POINTER1( hLayer, "OGR_L_GetName", "" );
1722
1723 #ifdef OGRAPISPY_ENABLED
1724 if( bOGRAPISpyEnabled )
1725 OGRAPISpy_L_GetName(hLayer);
1726 #endif
1727
1728 return ((OGRLayer *) hLayer)->GetName();
1729 }
1730
1731 /************************************************************************/
1732 /* GetGeomType() */
1733 /************************************************************************/
1734
GetGeomType()1735 OGRwkbGeometryType OGRLayer::GetGeomType()
1736 {
1737 OGRFeatureDefn* poLayerDefn = GetLayerDefn();
1738 if( poLayerDefn == NULL )
1739 {
1740 CPLDebug("OGR", "GetLayerType() returns NULL !");
1741 return wkbUnknown;
1742 }
1743 return poLayerDefn->GetGeomType();
1744 }
1745
1746 /************************************************************************/
1747 /* OGR_L_GetGeomType() */
1748 /************************************************************************/
1749
OGR_L_GetGeomType(OGRLayerH hLayer)1750 OGRwkbGeometryType OGR_L_GetGeomType( OGRLayerH hLayer )
1751
1752 {
1753 VALIDATE_POINTER1( hLayer, "OGR_L_GetGeomType", wkbUnknown );
1754
1755 #ifdef OGRAPISPY_ENABLED
1756 if( bOGRAPISpyEnabled )
1757 OGRAPISpy_L_GetGeomType(hLayer);
1758 #endif
1759
1760 OGRwkbGeometryType eType = ((OGRLayer *) hLayer)->GetGeomType();
1761 if( OGR_GT_IsNonLinear(eType) && !OGRGetNonLinearGeometriesEnabledFlag() )
1762 {
1763 eType = OGR_GT_GetLinear(eType);
1764 }
1765 return eType;
1766 }
1767
1768 /************************************************************************/
1769 /* SetIgnoredFields() */
1770 /************************************************************************/
1771
SetIgnoredFields(const char ** papszFields)1772 OGRErr OGRLayer::SetIgnoredFields( const char **papszFields )
1773 {
1774 OGRFeatureDefn *poDefn = GetLayerDefn();
1775
1776 // first set everything as *not* ignored
1777 for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
1778 {
1779 poDefn->GetFieldDefn(iField)->SetIgnored( FALSE );
1780 }
1781 poDefn->SetGeometryIgnored( FALSE );
1782 poDefn->SetStyleIgnored( FALSE );
1783
1784 if ( papszFields == NULL )
1785 return OGRERR_NONE;
1786
1787 // ignore some fields
1788 while ( *papszFields )
1789 {
1790 const char* pszFieldName = *papszFields;
1791 // check special fields
1792 if ( EQUAL(pszFieldName, "OGR_GEOMETRY") )
1793 poDefn->SetGeometryIgnored( TRUE );
1794 else if ( EQUAL(pszFieldName, "OGR_STYLE") )
1795 poDefn->SetStyleIgnored( TRUE );
1796 else
1797 {
1798 // check ordinary fields
1799 int iField = poDefn->GetFieldIndex(pszFieldName);
1800 if ( iField == -1 )
1801 {
1802 // check geometry field
1803 iField = poDefn->GetGeomFieldIndex(pszFieldName);
1804 if ( iField == -1 )
1805 {
1806 return OGRERR_FAILURE;
1807 }
1808 else
1809 poDefn->GetGeomFieldDefn(iField)->SetIgnored( TRUE );
1810 }
1811 else
1812 poDefn->GetFieldDefn(iField)->SetIgnored( TRUE );
1813 }
1814 papszFields++;
1815 }
1816
1817 return OGRERR_NONE;
1818 }
1819
1820 /************************************************************************/
1821 /* OGR_L_SetIgnoredFields() */
1822 /************************************************************************/
1823
OGR_L_SetIgnoredFields(OGRLayerH hLayer,const char ** papszFields)1824 OGRErr OGR_L_SetIgnoredFields( OGRLayerH hLayer, const char **papszFields )
1825
1826 {
1827 VALIDATE_POINTER1( hLayer, "OGR_L_SetIgnoredFields", OGRERR_INVALID_HANDLE );
1828
1829 #ifdef OGRAPISPY_ENABLED
1830 if( bOGRAPISpyEnabled )
1831 OGRAPISpy_L_SetIgnoredFields(hLayer, papszFields);
1832 #endif
1833
1834 return ((OGRLayer *) hLayer)->SetIgnoredFields( papszFields );
1835 }
1836
1837 /************************************************************************/
1838 /* helper functions for layer overlay methods */
1839 /************************************************************************/
1840
1841 static
clone_spatial_filter(OGRLayer * pLayer,OGRGeometry ** ppGeometry)1842 OGRErr clone_spatial_filter(OGRLayer *pLayer, OGRGeometry **ppGeometry)
1843 {
1844 OGRErr ret = OGRERR_NONE;
1845 OGRGeometry *g = pLayer->GetSpatialFilter();
1846 *ppGeometry = g ? g->clone() : NULL;
1847 return ret;
1848 }
1849
1850 static
create_field_map(OGRFeatureDefn * poDefn,int ** map)1851 OGRErr create_field_map(OGRFeatureDefn *poDefn, int **map)
1852 {
1853 OGRErr ret = OGRERR_NONE;
1854 int n = poDefn->GetFieldCount();
1855 if (n > 0) {
1856 *map = (int*)VSIMalloc(sizeof(int) * n);
1857 if (!(*map)) return OGRERR_NOT_ENOUGH_MEMORY;
1858 for(int i=0;i<n;i++)
1859 (*map)[i] = -1;
1860 }
1861 return ret;
1862 }
1863
1864 static
set_result_schema(OGRLayer * pLayerResult,OGRFeatureDefn * poDefnInput,OGRFeatureDefn * poDefnMethod,int * mapInput,int * mapMethod,int combined,char ** papszOptions)1865 OGRErr set_result_schema(OGRLayer *pLayerResult,
1866 OGRFeatureDefn *poDefnInput,
1867 OGRFeatureDefn *poDefnMethod,
1868 int *mapInput,
1869 int *mapMethod,
1870 int combined,
1871 char** papszOptions)
1872 {
1873 OGRErr ret = OGRERR_NONE;
1874 OGRFeatureDefn *poDefnResult = pLayerResult->GetLayerDefn();
1875 const char* pszInputPrefix = CSLFetchNameValue(papszOptions, "INPUT_PREFIX");
1876 const char* pszMethodPrefix = CSLFetchNameValue(papszOptions, "METHOD_PREFIX");
1877 int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
1878 if (poDefnResult->GetFieldCount() > 0) {
1879 // the user has defined the schema of the output layer
1880 for( int iField = 0; iField < poDefnInput->GetFieldCount(); iField++ ) {
1881 CPLString osName(poDefnInput->GetFieldDefn(iField)->GetNameRef());
1882 if( pszInputPrefix != NULL )
1883 osName = pszInputPrefix + osName;
1884 mapInput[iField] = poDefnResult->GetFieldIndex(osName);
1885 }
1886 if (!mapMethod) return ret;
1887 for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
1888 CPLString osName(poDefnMethod->GetFieldDefn(iField)->GetNameRef());
1889 if( pszMethodPrefix != NULL )
1890 osName = pszMethodPrefix + osName;
1891 mapMethod[iField] = poDefnResult->GetFieldIndex(osName);
1892 }
1893 } else {
1894 // use schema from the input layer or from input and method layers
1895 int nFieldsInput = poDefnInput->GetFieldCount();
1896 for( int iField = 0; iField < nFieldsInput; iField++ ) {
1897 OGRFieldDefn oFieldDefn(poDefnInput->GetFieldDefn(iField));
1898 if( pszInputPrefix != NULL )
1899 oFieldDefn.SetName(CPLSPrintf("%s%s", pszInputPrefix, oFieldDefn.GetNameRef()));
1900 ret = pLayerResult->CreateField(&oFieldDefn);
1901 if (ret != OGRERR_NONE) {
1902 if (!bSkipFailures)
1903 return ret;
1904 else {
1905 CPLErrorReset();
1906 ret = OGRERR_NONE;
1907 }
1908 }
1909 mapInput[iField] = iField;
1910 }
1911 if (!combined) return ret;
1912 if (!mapMethod) return ret;
1913 for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
1914 OGRFieldDefn oFieldDefn(poDefnMethod->GetFieldDefn(iField));
1915 if( pszMethodPrefix != NULL )
1916 oFieldDefn.SetName(CPLSPrintf("%s%s", pszMethodPrefix, oFieldDefn.GetNameRef()));
1917 ret = pLayerResult->CreateField(&oFieldDefn);
1918 if (ret != OGRERR_NONE) {
1919 if (!bSkipFailures)
1920 return ret;
1921 else {
1922 CPLErrorReset();
1923 ret = OGRERR_NONE;
1924 }
1925 }
1926 mapMethod[iField] = nFieldsInput+iField;
1927 }
1928 }
1929 return ret;
1930 }
1931
1932 static
set_filter_from(OGRLayer * pLayer,OGRGeometry * pGeometryExistingFilter,OGRFeature * pFeature)1933 OGRGeometry *set_filter_from(OGRLayer *pLayer, OGRGeometry *pGeometryExistingFilter, OGRFeature *pFeature)
1934 {
1935 OGRGeometry *geom = pFeature->GetGeometryRef();
1936 if (!geom) return NULL;
1937 if (pGeometryExistingFilter) {
1938 if (!geom->Intersects(pGeometryExistingFilter)) return NULL;
1939 OGRGeometry *intersection = geom->Intersection(pGeometryExistingFilter);
1940 pLayer->SetSpatialFilter(intersection);
1941 if (intersection) delete intersection;
1942 } else {
1943 pLayer->SetSpatialFilter(geom);
1944 }
1945 return geom;
1946 }
1947
promote_to_multi(OGRGeometry * poGeom)1948 static OGRGeometry* promote_to_multi(OGRGeometry* poGeom)
1949 {
1950 OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1951 if( eType == wkbPolygon )
1952 return OGRGeometryFactory::forceToMultiPolygon(poGeom);
1953 else if( eType == wkbLineString )
1954 return OGRGeometryFactory::forceToMultiLineString(poGeom);
1955 else
1956 return poGeom;
1957 }
1958
1959 /************************************************************************/
1960 /* Intersection() */
1961 /************************************************************************/
1962 /**
1963 * \brief Intersection of two layers.
1964 *
1965 * The result layer contains features whose geometries represent areas
1966 * that are common between features in the input layer and in the
1967 * method layer. The features in the result layer have attributes from
1968 * both input and method layers. The schema of the result layer can be
1969 * set by the user or, if it is empty, is initialized to contain all
1970 * fields in the input and method layers.
1971 *
1972 * \note If the schema of the result is set by user and contains
1973 * fields that have the same name as a field in input and in method
1974 * layer, then the attribute in the result feature will get the value
1975 * from the feature of the method layer.
1976 *
1977 * \note For best performance use the minimum amount of features in
1978 * the method layer and copy it into a memory layer.
1979 *
1980 * \note This method relies on GEOS support. Do not use unless the
1981 * GEOS support is compiled in.
1982 *
1983 * The recognized list of options is :
1984 * <ul>
1985 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
1986 * feature could not be inserted.
1987 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
1988 * into MultiPolygons, or LineStrings to MultiLineStrings.
1989 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
1990 * will be created from the fields of the input layer.
1991 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
1992 * will be created from the fields of the method layer.
1993 * </ul>
1994 *
1995 * This method is the same as the C function OGR_L_Intersection().
1996 *
1997 * @param pLayerMethod the method layer. Should not be NULL.
1998 *
1999 * @param pLayerResult the layer where the features resulting from the
2000 * operation are inserted. Should not be NULL. See above the note
2001 * about the schema.
2002 *
2003 * @param papszOptions NULL terminated list of options (may be NULL).
2004 *
2005 * @param pfnProgress a GDALProgressFunc() compatible callback function for
2006 * reporting progress or NULL.
2007 *
2008 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2009 *
2010 * @return an error code if there was an error or the execution was
2011 * interrupted, OGRERR_NONE otherwise.
2012 *
2013 * @since OGR 1.10
2014 */
2015
Intersection(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2016 OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
2017 OGRLayer *pLayerResult,
2018 char** papszOptions,
2019 GDALProgressFunc pfnProgress,
2020 void * pProgressArg )
2021 {
2022 OGRErr ret = OGRERR_NONE;
2023 OGRFeatureDefn *poDefnInput = GetLayerDefn();
2024 OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2025 OGRFeatureDefn *poDefnResult = NULL;
2026 OGRGeometry *pGeometryMethodFilter = NULL;
2027 int *mapInput = NULL;
2028 int *mapMethod = NULL;
2029 OGREnvelope sEnvelopeMethod;
2030 GBool bEnvelopeSet;
2031 double progress_max = (double) GetFeatureCount(0);
2032 double progress_counter = 0;
2033 double progress_ticker = 0;
2034 int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
2035 int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
2036
2037 // check for GEOS
2038 if (!OGRGeometryFactory::haveGEOS()) {
2039 return OGRERR_UNSUPPORTED_OPERATION;
2040 }
2041
2042 // get resources
2043 ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2044 if (ret != OGRERR_NONE) goto done;
2045 ret = create_field_map(poDefnInput, &mapInput);
2046 if (ret != OGRERR_NONE) goto done;
2047 ret = create_field_map(poDefnMethod, &mapMethod);
2048 if (ret != OGRERR_NONE) goto done;
2049 ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
2050 if (ret != OGRERR_NONE) goto done;
2051 poDefnResult = pLayerResult->GetLayerDefn();
2052 bEnvelopeSet = pLayerMethod->GetExtent(&sEnvelopeMethod, 1) == OGRERR_NONE;
2053
2054 ResetReading();
2055 while (OGRFeature *x = GetNextFeature()) {
2056
2057 if (pfnProgress) {
2058 double p = progress_counter/progress_max;
2059 if (p > progress_ticker) {
2060 if (!pfnProgress(p, "", pProgressArg)) {
2061 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2062 ret = OGRERR_FAILURE;
2063 delete x;
2064 goto done;
2065 }
2066 }
2067 progress_counter += 1.0;
2068 }
2069
2070 // is it worth to proceed?
2071 if (bEnvelopeSet) {
2072 OGRGeometry *x_geom = x->GetGeometryRef();
2073 if (x_geom) {
2074 OGREnvelope x_env;
2075 x_geom->getEnvelope(&x_env);
2076 if (x_env.MaxX < sEnvelopeMethod.MinX
2077 || x_env.MaxY < sEnvelopeMethod.MinY
2078 || sEnvelopeMethod.MaxX < x_env.MinX
2079 || sEnvelopeMethod.MaxY < x_env.MinY) {
2080 delete x;
2081 continue;
2082 }
2083 } else {
2084 delete x;
2085 continue;
2086 }
2087 }
2088
2089 // set up the filter for method layer
2090 OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2091 if (!x_geom) {
2092 delete x;
2093 continue;
2094 }
2095
2096 pLayerMethod->ResetReading();
2097 while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2098 OGRGeometry *y_geom = y->GetGeometryRef();
2099 if (!y_geom) {delete y; continue;}
2100 OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
2101 if( poIntersection == NULL || poIntersection->IsEmpty() ||
2102 (x_geom->getDimension() == 2 &&
2103 y_geom->getDimension() == 2 &&
2104 poIntersection->getDimension() < 2) )
2105 {
2106 delete poIntersection;
2107 delete y;
2108 }
2109 else
2110 {
2111 OGRFeature *z = new OGRFeature(poDefnResult);
2112 z->SetFieldsFrom(x, mapInput);
2113 z->SetFieldsFrom(y, mapMethod);
2114 if( bPromoteToMulti )
2115 poIntersection = promote_to_multi(poIntersection);
2116 z->SetGeometryDirectly(poIntersection);
2117 delete y;
2118 ret = pLayerResult->CreateFeature(z);
2119 delete z;
2120 if (ret != OGRERR_NONE) {
2121 if (!bSkipFailures) {
2122 delete x;
2123 goto done;
2124 } else {
2125 CPLErrorReset();
2126 ret = OGRERR_NONE;
2127 }
2128 }
2129 }
2130 }
2131
2132 delete x;
2133 }
2134 if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2135 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2136 ret = OGRERR_FAILURE;
2137 goto done;
2138 }
2139 done:
2140 // release resources
2141 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2142 if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2143 if (mapInput) VSIFree(mapInput);
2144 if (mapMethod) VSIFree(mapMethod);
2145 return ret;
2146 }
2147
2148 /************************************************************************/
2149 /* OGR_L_Intersection() */
2150 /************************************************************************/
2151 /**
2152 * \brief Intersection of two layers.
2153 *
2154 * The result layer contains features whose geometries represent areas
2155 * that are common between features in the input layer and in the
2156 * method layer. The features in the result layer have attributes from
2157 * both input and method layers. The schema of the result layer can be
2158 * set by the user or, if it is empty, is initialized to contain all
2159 * fields in the input and method layers.
2160 *
2161 * \note If the schema of the result is set by user and contains
2162 * fields that have the same name as a field in input and in method
2163 * layer, then the attribute in the result feature will get the value
2164 * from the feature of the method layer.
2165 *
2166 * \note For best performance use the minimum amount of features in
2167 * the method layer and copy it into a memory layer.
2168 *
2169 * \note This method relies on GEOS support. Do not use unless the
2170 * GEOS support is compiled in.
2171 *
2172 * The recognized list of options is :
2173 * <ul>
2174 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2175 * feature could not be inserted.
2176 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2177 * into MultiPolygons, or LineStrings to MultiLineStrings.
2178 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2179 * will be created from the fields of the input layer.
2180 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2181 * will be created from the fields of the method layer.
2182 * </ul>
2183 *
2184 * This function is the same as the C++ method OGRLayer::Intersection().
2185 *
2186 * @param pLayerInput the input layer. Should not be NULL.
2187 *
2188 * @param pLayerMethod the method layer. Should not be NULL.
2189 *
2190 * @param pLayerResult the layer where the features resulting from the
2191 * operation are inserted. Should not be NULL. See above the note
2192 * about the schema.
2193 *
2194 * @param papszOptions NULL terminated list of options (may be NULL).
2195 *
2196 * @param pfnProgress a GDALProgressFunc() compatible callback function for
2197 * reporting progress or NULL.
2198 *
2199 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2200 *
2201 * @return an error code if there was an error or the execution was
2202 * interrupted, OGRERR_NONE otherwise.
2203 *
2204 * @since OGR 1.10
2205 */
2206
OGR_L_Intersection(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2207 OGRErr OGR_L_Intersection( OGRLayerH pLayerInput,
2208 OGRLayerH pLayerMethod,
2209 OGRLayerH pLayerResult,
2210 char** papszOptions,
2211 GDALProgressFunc pfnProgress,
2212 void * pProgressArg )
2213
2214 {
2215 VALIDATE_POINTER1( pLayerInput, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
2216 VALIDATE_POINTER1( pLayerMethod, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
2217 VALIDATE_POINTER1( pLayerResult, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
2218
2219 return ((OGRLayer *)pLayerInput)->Intersection( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2220 }
2221
2222 /************************************************************************/
2223 /* Union() */
2224 /************************************************************************/
2225
2226 /**
2227 * \brief Union of two layers.
2228 *
2229 * The result layer contains features whose geometries represent areas
2230 * that are in either in the input layer or in the method layer. The
2231 * features in the result layer have attributes from both input and
2232 * method layers. For features which represent areas that are only in
2233 * the input or in the method layer the respective attributes have
2234 * undefined values. The schema of the result layer can be set by the
2235 * user or, if it is empty, is initialized to contain all fields in
2236 * the input and method layers.
2237 *
2238 * \note If the schema of the result is set by user and contains
2239 * fields that have the same name as a field in input and in method
2240 * layer, then the attribute in the result feature will get the value
2241 * from the feature of the method layer (even if it is undefined).
2242 *
2243 * \note For best performance use the minimum amount of features in
2244 * the method layer and copy it into a memory layer.
2245 *
2246 * \note This method relies on GEOS support. Do not use unless the
2247 * GEOS support is compiled in.
2248 *
2249 * The recognized list of options is :
2250 * <ul>
2251 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2252 * feature could not be inserted.
2253 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2254 * into MultiPolygons, or LineStrings to MultiLineStrings.
2255 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2256 * will be created from the fields of the input layer.
2257 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2258 * will be created from the fields of the method layer.
2259 * </ul>
2260 *
2261 * This method is the same as the C function OGR_L_Union().
2262 *
2263 * @param pLayerMethod the method layer. Should not be NULL.
2264 *
2265 * @param pLayerResult the layer where the features resulting from the
2266 * operation are inserted. Should not be NULL. See above the note
2267 * about the schema.
2268 *
2269 * @param papszOptions NULL terminated list of options (may be NULL).
2270 *
2271 * @param pfnProgress a GDALProgressFunc() compatible callback function for
2272 * reporting progress or NULL.
2273 *
2274 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2275 *
2276 * @return an error code if there was an error or the execution was
2277 * interrupted, OGRERR_NONE otherwise.
2278 *
2279 * @since OGR 1.10
2280 */
2281
Union(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2282 OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
2283 OGRLayer *pLayerResult,
2284 char** papszOptions,
2285 GDALProgressFunc pfnProgress,
2286 void * pProgressArg )
2287 {
2288 OGRErr ret = OGRERR_NONE;
2289 OGRFeatureDefn *poDefnInput = GetLayerDefn();
2290 OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2291 OGRFeatureDefn *poDefnResult = NULL;
2292 OGRGeometry *pGeometryMethodFilter = NULL;
2293 OGRGeometry *pGeometryInputFilter = NULL;
2294 int *mapInput = NULL;
2295 int *mapMethod = NULL;
2296 double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
2297 double progress_counter = 0;
2298 double progress_ticker = 0;
2299 int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
2300 int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
2301
2302 // check for GEOS
2303 if (!OGRGeometryFactory::haveGEOS()) {
2304 return OGRERR_UNSUPPORTED_OPERATION;
2305 }
2306
2307 // get resources
2308 ret = clone_spatial_filter(this, &pGeometryInputFilter);
2309 if (ret != OGRERR_NONE) goto done;
2310 ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2311 if (ret != OGRERR_NONE) goto done;
2312 ret = create_field_map(poDefnInput, &mapInput);
2313 if (ret != OGRERR_NONE) goto done;
2314 ret = create_field_map(poDefnMethod, &mapMethod);
2315 if (ret != OGRERR_NONE) goto done;
2316 ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
2317 if (ret != OGRERR_NONE) goto done;
2318 poDefnResult = pLayerResult->GetLayerDefn();
2319
2320 // add features based on input layer
2321 ResetReading();
2322 while (OGRFeature *x = GetNextFeature()) {
2323
2324 if (pfnProgress) {
2325 double p = progress_counter/progress_max;
2326 if (p > progress_ticker) {
2327 if (!pfnProgress(p, "", pProgressArg)) {
2328 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2329 ret = OGRERR_FAILURE;
2330 delete x;
2331 goto done;
2332 }
2333 }
2334 progress_counter += 1.0;
2335 }
2336
2337 // set up the filter on method layer
2338 OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2339 if (!x_geom) {
2340 delete x;
2341 continue;
2342 }
2343
2344 OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
2345 pLayerMethod->ResetReading();
2346 while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2347 OGRGeometry *y_geom = y->GetGeometryRef();
2348 if (!y_geom) {delete y; continue;}
2349 OGRGeometry *poIntersection = x_geom->Intersection(y_geom);
2350 if( poIntersection == NULL || poIntersection->IsEmpty() ||
2351 (x_geom->getDimension() == 2 &&
2352 y_geom->getDimension() == 2 &&
2353 poIntersection->getDimension() < 2) )
2354 {
2355 delete poIntersection;
2356 delete y;
2357 }
2358 else
2359 {
2360 OGRFeature *z = new OGRFeature(poDefnResult);
2361 z->SetFieldsFrom(x, mapInput);
2362 z->SetFieldsFrom(y, mapMethod);
2363 if( bPromoteToMulti )
2364 poIntersection = promote_to_multi(poIntersection);
2365 z->SetGeometryDirectly(poIntersection);
2366 OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
2367 if (x_geom_diff) delete x_geom_diff;
2368 x_geom_diff = x_geom_diff_new;
2369 delete y;
2370 ret = pLayerResult->CreateFeature(z);
2371 delete z;
2372 if (ret != OGRERR_NONE) {
2373 if (!bSkipFailures) {
2374 delete x;
2375 if (x_geom_diff)
2376 delete x_geom_diff;
2377 goto done;
2378 } else {
2379 CPLErrorReset();
2380 ret = OGRERR_NONE;
2381 }
2382 }
2383 }
2384 }
2385
2386 if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
2387 {
2388 delete x_geom_diff;
2389 delete x;
2390 }
2391 else
2392 {
2393 OGRFeature *z = new OGRFeature(poDefnResult);
2394 z->SetFieldsFrom(x, mapInput);
2395 if( bPromoteToMulti )
2396 x_geom_diff = promote_to_multi(x_geom_diff);
2397 z->SetGeometryDirectly(x_geom_diff);
2398 delete x;
2399 ret = pLayerResult->CreateFeature(z);
2400 delete z;
2401 if (ret != OGRERR_NONE) {
2402 if (!bSkipFailures) {
2403 goto done;
2404 } else {
2405 CPLErrorReset();
2406 ret = OGRERR_NONE;
2407 }
2408 }
2409 }
2410 }
2411
2412 // restore filter on method layer and add features based on it
2413 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2414 pLayerMethod->ResetReading();
2415 while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
2416
2417 if (pfnProgress) {
2418 double p = progress_counter/progress_max;
2419 if (p > progress_ticker) {
2420 if (!pfnProgress(p, "", pProgressArg)) {
2421 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2422 ret = OGRERR_FAILURE;
2423 delete x;
2424 goto done;
2425 }
2426 }
2427 progress_counter += 1.0;
2428 }
2429
2430 // set up the filter on input layer
2431 OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
2432 if (!x_geom) {
2433 delete x;
2434 continue;
2435 }
2436
2437 OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
2438 ResetReading();
2439 while (OGRFeature *y = GetNextFeature()) {
2440 OGRGeometry *y_geom = y->GetGeometryRef();
2441 if (!y_geom) {delete y; continue;}
2442 OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
2443 if (x_geom_diff) delete x_geom_diff;
2444 x_geom_diff = x_geom_diff_new;
2445 delete y;
2446 }
2447
2448 if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
2449 {
2450 delete x_geom_diff;
2451 delete x;
2452 }
2453 else
2454 {
2455 OGRFeature *z = new OGRFeature(poDefnResult);
2456 z->SetFieldsFrom(x, mapMethod);
2457 if( bPromoteToMulti )
2458 x_geom_diff = promote_to_multi(x_geom_diff);
2459 z->SetGeometryDirectly(x_geom_diff);
2460 delete x;
2461 ret = pLayerResult->CreateFeature(z);
2462 delete z;
2463 if (ret != OGRERR_NONE) {
2464 if (!bSkipFailures) {
2465 goto done;
2466 } else {
2467 CPLErrorReset();
2468 ret = OGRERR_NONE;
2469 }
2470 }
2471 }
2472 }
2473 if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2474 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2475 ret = OGRERR_FAILURE;
2476 goto done;
2477 }
2478 done:
2479 // release resources
2480 SetSpatialFilter(pGeometryInputFilter);
2481 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2482 if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2483 if (pGeometryInputFilter) delete pGeometryInputFilter;
2484 if (mapInput) VSIFree(mapInput);
2485 if (mapMethod) VSIFree(mapMethod);
2486 return ret;
2487 }
2488
2489 /************************************************************************/
2490 /* OGR_L_Union() */
2491 /************************************************************************/
2492
2493 /**
2494 * \brief Union of two layers.
2495 *
2496 * The result layer contains features whose geometries represent areas
2497 * that are in either in the input layer or in the method layer. The
2498 * features in the result layer have attributes from both input and
2499 * method layers. For features which represent areas that are only in
2500 * the input or in the method layer the respective attributes have
2501 * undefined values. The schema of the result layer can be set by the
2502 * user or, if it is empty, is initialized to contain all fields in
2503 * the input and method layers.
2504 *
2505 * \note If the schema of the result is set by user and contains
2506 * fields that have the same name as a field in input and in method
2507 * layer, then the attribute in the result feature will get the value
2508 * from the feature of the method layer (even if it is undefined).
2509 *
2510 * \note For best performance use the minimum amount of features in
2511 * the method layer and copy it into a memory layer.
2512 *
2513 * \note This method relies on GEOS support. Do not use unless the
2514 * GEOS support is compiled in.
2515 *
2516 * The recognized list of options is :
2517 * <ul>
2518 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2519 * feature could not be inserted.
2520 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2521 * into MultiPolygons, or LineStrings to MultiLineStrings.
2522 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2523 * will be created from the fields of the input layer.
2524 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2525 * will be created from the fields of the method layer.
2526 * </ul>
2527 *
2528 * This function is the same as the C++ method OGRLayer::Union().
2529 *
2530 * @param pLayerInput the input layer. Should not be NULL.
2531 *
2532 * @param pLayerMethod the method layer. Should not be NULL.
2533 *
2534 * @param pLayerResult the layer where the features resulting from the
2535 * operation are inserted. Should not be NULL. See above the note
2536 * about the schema.
2537 *
2538 * @param papszOptions NULL terminated list of options (may be NULL).
2539 *
2540 * @param pfnProgress a GDALProgressFunc() compatible callback function for
2541 * reporting progress or NULL.
2542 *
2543 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2544 *
2545 * @return an error code if there was an error or the execution was
2546 * interrupted, OGRERR_NONE otherwise.
2547 *
2548 * @since OGR 1.10
2549 */
2550
OGR_L_Union(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2551 OGRErr OGR_L_Union( OGRLayerH pLayerInput,
2552 OGRLayerH pLayerMethod,
2553 OGRLayerH pLayerResult,
2554 char** papszOptions,
2555 GDALProgressFunc pfnProgress,
2556 void * pProgressArg )
2557
2558 {
2559 VALIDATE_POINTER1( pLayerInput, "OGR_L_Union", OGRERR_INVALID_HANDLE );
2560 VALIDATE_POINTER1( pLayerMethod, "OGR_L_Union", OGRERR_INVALID_HANDLE );
2561 VALIDATE_POINTER1( pLayerResult, "OGR_L_Union", OGRERR_INVALID_HANDLE );
2562
2563 return ((OGRLayer *)pLayerInput)->Union( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2564 }
2565
2566 /************************************************************************/
2567 /* SymDifference() */
2568 /************************************************************************/
2569
2570 /**
2571 * \brief Symmetrical difference of two layers.
2572 *
2573 * The result layer contains features whose geometries represent areas
2574 * that are in either in the input layer or in the method layer but
2575 * not in both. The features in the result layer have attributes from
2576 * both input and method layers. For features which represent areas
2577 * that are only in the input or in the method layer the respective
2578 * attributes have undefined values. The schema of the result layer
2579 * can be set by the user or, if it is empty, is initialized to
2580 * contain all fields in the input and method layers.
2581 *
2582 * \note If the schema of the result is set by user and contains
2583 * fields that have the same name as a field in input and in method
2584 * layer, then the attribute in the result feature will get the value
2585 * from the feature of the method layer (even if it is undefined).
2586 *
2587 * \note For best performance use the minimum amount of features in
2588 * the method layer and copy it into a memory layer.
2589 *
2590 * \note This method relies on GEOS support. Do not use unless the
2591 * GEOS support is compiled in.
2592 *
2593 * The recognized list of options is :
2594 * <ul>
2595 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2596 * feature could not be inserted.
2597 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2598 * into MultiPolygons, or LineStrings to MultiLineStrings.
2599 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2600 * will be created from the fields of the input layer.
2601 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2602 * will be created from the fields of the method layer.
2603 * </ul>
2604 *
2605 * This method is the same as the C function OGR_L_SymDifference().
2606 *
2607 * @param pLayerMethod the method layer. Should not be NULL.
2608 *
2609 * @param pLayerResult the layer where the features resulting from the
2610 * operation are inserted. Should not be NULL. See above the note
2611 * about the schema.
2612 *
2613 * @param papszOptions NULL terminated list of options (may be NULL).
2614 *
2615 * @param pfnProgress a GDALProgressFunc() compatible callback function for
2616 * reporting progress or NULL.
2617 *
2618 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2619 *
2620 * @return an error code if there was an error or the execution was
2621 * interrupted, OGRERR_NONE otherwise.
2622 *
2623 * @since OGR 1.10
2624 */
2625
SymDifference(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2626 OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
2627 OGRLayer *pLayerResult,
2628 char** papszOptions,
2629 GDALProgressFunc pfnProgress,
2630 void * pProgressArg )
2631 {
2632 OGRErr ret = OGRERR_NONE;
2633 OGRFeatureDefn *poDefnInput = GetLayerDefn();
2634 OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2635 OGRFeatureDefn *poDefnResult = NULL;
2636 OGRGeometry *pGeometryMethodFilter = NULL;
2637 OGRGeometry *pGeometryInputFilter = NULL;
2638 int *mapInput = NULL;
2639 int *mapMethod = NULL;
2640 double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
2641 double progress_counter = 0;
2642 double progress_ticker = 0;
2643 int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
2644 int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
2645
2646 // check for GEOS
2647 if (!OGRGeometryFactory::haveGEOS()) {
2648 return OGRERR_UNSUPPORTED_OPERATION;
2649 }
2650
2651 // get resources
2652 ret = clone_spatial_filter(this, &pGeometryInputFilter);
2653 if (ret != OGRERR_NONE) goto done;
2654 ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2655 if (ret != OGRERR_NONE) goto done;
2656 ret = create_field_map(poDefnInput, &mapInput);
2657 if (ret != OGRERR_NONE) goto done;
2658 ret = create_field_map(poDefnMethod, &mapMethod);
2659 if (ret != OGRERR_NONE) goto done;
2660 ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
2661 if (ret != OGRERR_NONE) goto done;
2662 poDefnResult = pLayerResult->GetLayerDefn();
2663
2664 // add features based on input layer
2665 ResetReading();
2666 while (OGRFeature *x = GetNextFeature()) {
2667
2668 if (pfnProgress) {
2669 double p = progress_counter/progress_max;
2670 if (p > progress_ticker) {
2671 if (!pfnProgress(p, "", pProgressArg)) {
2672 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2673 ret = OGRERR_FAILURE;
2674 delete x;
2675 goto done;
2676 }
2677 }
2678 progress_counter += 1.0;
2679 }
2680
2681 // set up the filter on method layer
2682 OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2683 if (!x_geom) {
2684 delete x;
2685 continue;
2686 }
2687
2688 OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
2689 pLayerMethod->ResetReading();
2690 while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2691 OGRGeometry *y_geom = y->GetGeometryRef();
2692 if (!y_geom) {delete y; continue;}
2693 OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
2694 if (geom) delete geom;
2695 geom = geom_new;
2696 delete y;
2697 if (geom && geom->IsEmpty()) break;
2698 }
2699
2700 OGRFeature *z = NULL;
2701 if (geom && !geom->IsEmpty()) {
2702 z = new OGRFeature(poDefnResult);
2703 z->SetFieldsFrom(x, mapInput);
2704 if( bPromoteToMulti )
2705 geom = promote_to_multi(geom);
2706 z->SetGeometryDirectly(geom);
2707 } else {
2708 if (geom) delete geom;
2709 }
2710 delete x;
2711 if (z) {
2712 ret = pLayerResult->CreateFeature(z);
2713 delete z;
2714 if (ret != OGRERR_NONE) {
2715 if (!bSkipFailures) {
2716 goto done;
2717 } else {
2718 CPLErrorReset();
2719 ret = OGRERR_NONE;
2720 }
2721 }
2722 }
2723 }
2724
2725 // restore filter on method layer and add features based on it
2726 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2727 pLayerMethod->ResetReading();
2728 while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
2729
2730 if (pfnProgress) {
2731 double p = progress_counter/progress_max;
2732 if (p > progress_ticker) {
2733 if (!pfnProgress(p, "", pProgressArg)) {
2734 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2735 ret = OGRERR_FAILURE;
2736 delete x;
2737 goto done;
2738 }
2739 }
2740 progress_counter += 1.0;
2741 }
2742
2743 // set up the filter on input layer
2744 OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
2745 if (!x_geom) {
2746 delete x;
2747 continue;
2748 }
2749
2750 OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
2751 ResetReading();
2752 while (OGRFeature *y = GetNextFeature()) {
2753 OGRGeometry *y_geom = y->GetGeometryRef();
2754 if (!y_geom) {delete y; continue;}
2755 OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
2756 if (geom) delete geom;
2757 geom = geom_new;
2758 delete y;
2759 if (geom == NULL || geom->IsEmpty()) break;
2760 }
2761
2762 OGRFeature *z = NULL;
2763 if (geom && !geom->IsEmpty()) {
2764 z = new OGRFeature(poDefnResult);
2765 z->SetFieldsFrom(x, mapMethod);
2766 if( bPromoteToMulti )
2767 geom = promote_to_multi(geom);
2768 z->SetGeometryDirectly(geom);
2769 } else {
2770 if (geom) delete geom;
2771 }
2772 delete x;
2773 if (z) {
2774 ret = pLayerResult->CreateFeature(z);
2775 delete z;
2776 if (ret != OGRERR_NONE) {
2777 if (!bSkipFailures) {
2778 goto done;
2779 } else {
2780 CPLErrorReset();
2781 ret = OGRERR_NONE;
2782 }
2783 }
2784 }
2785 }
2786 if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2787 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2788 ret = OGRERR_FAILURE;
2789 goto done;
2790 }
2791 done:
2792 // release resources
2793 SetSpatialFilter(pGeometryInputFilter);
2794 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2795 if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2796 if (pGeometryInputFilter) delete pGeometryInputFilter;
2797 if (mapInput) VSIFree(mapInput);
2798 if (mapMethod) VSIFree(mapMethod);
2799 return ret;
2800 }
2801
2802 /************************************************************************/
2803 /* OGR_L_SymDifference() */
2804 /************************************************************************/
2805
2806 /**
2807 * \brief Symmetrical difference of two layers.
2808 *
2809 * The result layer contains features whose geometries represent areas
2810 * that are in either in the input layer or in the method layer but
2811 * not in both. The features in the result layer have attributes from
2812 * both input and method layers. For features which represent areas
2813 * that are only in the input or in the method layer the respective
2814 * attributes have undefined values. The schema of the result layer
2815 * can be set by the user or, if it is empty, is initialized to
2816 * contain all fields in the input and method layers.
2817 *
2818 * \note If the schema of the result is set by user and contains
2819 * fields that have the same name as a field in input and in method
2820 * layer, then the attribute in the result feature will get the value
2821 * from the feature of the method layer (even if it is undefined).
2822 *
2823 * \note For best performance use the minimum amount of features in
2824 * the method layer and copy it into a memory layer.
2825 *
2826 * \note This method relies on GEOS support. Do not use unless the
2827 * GEOS support is compiled in.
2828 *
2829 * The recognized list of options is :
2830 * <ul>
2831 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2832 * feature could not be inserted.
2833 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2834 * into MultiPolygons, or LineStrings to MultiLineStrings.
2835 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2836 * will be created from the fields of the input layer.
2837 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2838 * will be created from the fields of the method layer.
2839 * </ul>
2840 *
2841 * This function is the same as the C++ method OGRLayer::SymDifference().
2842 *
2843 * @param pLayerInput the input layer. Should not be NULL.
2844 *
2845 * @param pLayerMethod the method layer. Should not be NULL.
2846 *
2847 * @param pLayerResult the layer where the features resulting from the
2848 * operation are inserted. Should not be NULL. See above the note
2849 * about the schema.
2850 *
2851 * @param papszOptions NULL terminated list of options (may be NULL).
2852 *
2853 * @param pfnProgress a GDALProgressFunc() compatible callback function for
2854 * reporting progress or NULL.
2855 *
2856 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2857 *
2858 * @return an error code if there was an error or the execution was
2859 * interrupted, OGRERR_NONE otherwise.
2860 *
2861 * @since OGR 1.10
2862 */
2863
OGR_L_SymDifference(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2864 OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput,
2865 OGRLayerH pLayerMethod,
2866 OGRLayerH pLayerResult,
2867 char** papszOptions,
2868 GDALProgressFunc pfnProgress,
2869 void * pProgressArg )
2870
2871 {
2872 VALIDATE_POINTER1( pLayerInput, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2873 VALIDATE_POINTER1( pLayerMethod, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2874 VALIDATE_POINTER1( pLayerResult, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2875
2876 return ((OGRLayer *)pLayerInput)->SymDifference( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2877 }
2878
2879 /************************************************************************/
2880 /* Identity() */
2881 /************************************************************************/
2882
2883 /**
2884 * \brief Identify the features of this layer with the ones from the
2885 * identity layer.
2886 *
2887 * The result layer contains features whose geometries represent areas
2888 * that are in the input layer. The features in the result layer have
2889 * attributes from both input and method layers. The schema of the
2890 * result layer can be set by the user or, if it is empty, is
2891 * initialized to contain all fields in input and method layers.
2892 *
2893 * \note If the schema of the result is set by user and contains
2894 * fields that have the same name as a field in input and in method
2895 * layer, then the attribute in the result feature will get the value
2896 * from the feature of the method layer (even if it is undefined).
2897 *
2898 * \note For best performance use the minimum amount of features in
2899 * the method layer and copy it into a memory layer.
2900 *
2901 * \note This method relies on GEOS support. Do not use unless the
2902 * GEOS support is compiled in.
2903 *
2904 * The recognized list of options is :
2905 * <ul>
2906 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2907 * feature could not be inserted.
2908 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2909 * into MultiPolygons, or LineStrings to MultiLineStrings.
2910 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2911 * will be created from the fields of the input layer.
2912 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2913 * will be created from the fields of the method layer.
2914 * </ul>
2915 *
2916 * This method is the same as the C function OGR_L_Identity().
2917 *
2918 * @param pLayerMethod the method layer. Should not be NULL.
2919 *
2920 * @param pLayerResult the layer where the features resulting from the
2921 * operation are inserted. Should not be NULL. See above the note
2922 * about the schema.
2923 *
2924 * @param papszOptions NULL terminated list of options (may be NULL).
2925 *
2926 * @param pfnProgress a GDALProgressFunc() compatible callback function for
2927 * reporting progress or NULL.
2928 *
2929 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2930 *
2931 * @return an error code if there was an error or the execution was
2932 * interrupted, OGRERR_NONE otherwise.
2933 *
2934 * @since OGR 1.10
2935 */
2936
Identity(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2937 OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
2938 OGRLayer *pLayerResult,
2939 char** papszOptions,
2940 GDALProgressFunc pfnProgress,
2941 void * pProgressArg )
2942 {
2943 OGRErr ret = OGRERR_NONE;
2944 OGRFeatureDefn *poDefnInput = GetLayerDefn();
2945 OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2946 OGRFeatureDefn *poDefnResult = NULL;
2947 OGRGeometry *pGeometryMethodFilter = NULL;
2948 int *mapInput = NULL;
2949 int *mapMethod = NULL;
2950 double progress_max = (double) GetFeatureCount(0);
2951 double progress_counter = 0;
2952 double progress_ticker = 0;
2953 int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
2954 int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
2955
2956 // check for GEOS
2957 if (!OGRGeometryFactory::haveGEOS()) {
2958 return OGRERR_UNSUPPORTED_OPERATION;
2959 }
2960
2961 // get resources
2962 ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2963 if (ret != OGRERR_NONE) goto done;
2964 ret = create_field_map(poDefnInput, &mapInput);
2965 if (ret != OGRERR_NONE) goto done;
2966 ret = create_field_map(poDefnMethod, &mapMethod);
2967 if (ret != OGRERR_NONE) goto done;
2968 ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
2969 if (ret != OGRERR_NONE) goto done;
2970 poDefnResult = pLayerResult->GetLayerDefn();
2971
2972 // split the features in input layer to the result layer
2973 ResetReading();
2974 while (OGRFeature *x = GetNextFeature()) {
2975
2976 if (pfnProgress) {
2977 double p = progress_counter/progress_max;
2978 if (p > progress_ticker) {
2979 if (!pfnProgress(p, "", pProgressArg)) {
2980 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2981 ret = OGRERR_FAILURE;
2982 delete x;
2983 goto done;
2984 }
2985 }
2986 progress_counter += 1.0;
2987 }
2988
2989 // set up the filter on method layer
2990 OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2991 if (!x_geom) {
2992 delete x;
2993 continue;
2994 }
2995
2996 OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
2997 pLayerMethod->ResetReading();
2998 while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2999 OGRGeometry *y_geom = y->GetGeometryRef();
3000 if (!y_geom) {delete y; continue;}
3001 OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
3002 if( poIntersection == NULL || poIntersection->IsEmpty() ||
3003 (x_geom->getDimension() == 2 &&
3004 y_geom->getDimension() == 2 &&
3005 poIntersection->getDimension() < 2) )
3006 {
3007 delete poIntersection;
3008 delete y;
3009 }
3010 else
3011 {
3012 OGRFeature *z = new OGRFeature(poDefnResult);
3013 z->SetFieldsFrom(x, mapInput);
3014 z->SetFieldsFrom(y, mapMethod);
3015 if( bPromoteToMulti )
3016 poIntersection = promote_to_multi(poIntersection);
3017 z->SetGeometryDirectly(poIntersection);
3018 OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
3019 if (x_geom_diff) delete x_geom_diff;
3020 x_geom_diff = x_geom_diff_new;
3021 delete y;
3022 ret = pLayerResult->CreateFeature(z);
3023 delete z;
3024 if (ret != OGRERR_NONE) {
3025 if (!bSkipFailures) {
3026 delete x;
3027 delete x_geom_diff;
3028 goto done;
3029 } else {
3030 CPLErrorReset();
3031 ret = OGRERR_NONE;
3032 }
3033 }
3034 }
3035 }
3036
3037 if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
3038 {
3039 delete x_geom_diff;
3040 delete x;
3041 }
3042 else
3043 {
3044 OGRFeature *z = new OGRFeature(poDefnResult);
3045 z->SetFieldsFrom(x, mapInput);
3046 if( bPromoteToMulti )
3047 x_geom_diff = promote_to_multi(x_geom_diff);
3048 z->SetGeometryDirectly(x_geom_diff);
3049 delete x;
3050 ret = pLayerResult->CreateFeature(z);
3051 delete z;
3052 if (ret != OGRERR_NONE) {
3053 if (!bSkipFailures) {
3054 goto done;
3055 } else {
3056 CPLErrorReset();
3057 ret = OGRERR_NONE;
3058 }
3059 }
3060 }
3061 }
3062 if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3063 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3064 ret = OGRERR_FAILURE;
3065 goto done;
3066 }
3067 done:
3068 // release resources
3069 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3070 if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3071 if (mapInput) VSIFree(mapInput);
3072 if (mapMethod) VSIFree(mapMethod);
3073 return ret;
3074 }
3075
3076 /************************************************************************/
3077 /* OGR_L_Identity() */
3078 /************************************************************************/
3079
3080 /**
3081 * \brief Identify the features of this layer with the ones from the
3082 * identity layer.
3083 *
3084 * The result layer contains features whose geometries represent areas
3085 * that are in the input layer. The features in the result layer have
3086 * attributes from both input and method layers. The schema of the
3087 * result layer can be set by the user or, if it is empty, is
3088 * initialized to contain all fields in input and method layers.
3089 *
3090 * \note If the schema of the result is set by user and contains
3091 * fields that have the same name as a field in input and in method
3092 * layer, then the attribute in the result feature will get the value
3093 * from the feature of the method layer (even if it is undefined).
3094 *
3095 * \note For best performance use the minimum amount of features in
3096 * the method layer and copy it into a memory layer.
3097 *
3098 * \note This method relies on GEOS support. Do not use unless the
3099 * GEOS support is compiled in.
3100 *
3101 * The recognized list of options is :
3102 * <ul>
3103 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3104 * feature could not be inserted.
3105 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3106 * into MultiPolygons, or LineStrings to MultiLineStrings.
3107 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3108 * will be created from the fields of the input layer.
3109 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3110 * will be created from the fields of the method layer.
3111 * </ul>
3112 *
3113 * This function is the same as the C++ method OGRLayer::Identity().
3114 *
3115 * @param pLayerInput the input layer. Should not be NULL.
3116 *
3117 * @param pLayerMethod the method layer. Should not be NULL.
3118 *
3119 * @param pLayerResult the layer where the features resulting from the
3120 * operation are inserted. Should not be NULL. See above the note
3121 * about the schema.
3122 *
3123 * @param papszOptions NULL terminated list of options (may be NULL).
3124 *
3125 * @param pfnProgress a GDALProgressFunc() compatible callback function for
3126 * reporting progress or NULL.
3127 *
3128 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3129 *
3130 * @return an error code if there was an error or the execution was
3131 * interrupted, OGRERR_NONE otherwise.
3132 *
3133 * @since OGR 1.10
3134 */
3135
OGR_L_Identity(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3136 OGRErr OGR_L_Identity( OGRLayerH pLayerInput,
3137 OGRLayerH pLayerMethod,
3138 OGRLayerH pLayerResult,
3139 char** papszOptions,
3140 GDALProgressFunc pfnProgress,
3141 void * pProgressArg )
3142
3143 {
3144 VALIDATE_POINTER1( pLayerInput, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
3145 VALIDATE_POINTER1( pLayerMethod, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
3146 VALIDATE_POINTER1( pLayerResult, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
3147
3148 return ((OGRLayer *)pLayerInput)->Identity( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3149 }
3150
3151 /************************************************************************/
3152 /* Update() */
3153 /************************************************************************/
3154
3155 /**
3156 * \brief Update this layer with features from the update layer.
3157 *
3158 * The result layer contains features whose geometries represent areas
3159 * that are either in the input layer or in the method layer. The
3160 * features in the result layer have areas of the features of the
3161 * method layer or those ares of the features of the input layer that
3162 * are not covered by the method layer. The features of the result
3163 * layer get their attributes from the input layer. The schema of the
3164 * result layer can be set by the user or, if it is empty, is
3165 * initialized to contain all fields in the input layer.
3166 *
3167 * \note If the schema of the result is set by user and contains
3168 * fields that have the same name as a field in the method layer, then
3169 * the attribute in the result feature the originates from the method
3170 * layer will get the value from the feature of the method layer.
3171 *
3172 * \note For best performance use the minimum amount of features in
3173 * the method layer and copy it into a memory layer.
3174 *
3175 * \note This method relies on GEOS support. Do not use unless the
3176 * GEOS support is compiled in.
3177 *
3178 * The recognized list of options is :
3179 * <ul>
3180 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3181 * feature could not be inserted.
3182 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3183 * into MultiPolygons, or LineStrings to MultiLineStrings.
3184 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3185 * will be created from the fields of the input layer.
3186 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3187 * will be created from the fields of the method layer.
3188 * </ul>
3189 *
3190 * This method is the same as the C function OGR_L_Update().
3191 *
3192 * @param pLayerMethod the method layer. Should not be NULL.
3193 *
3194 * @param pLayerResult the layer where the features resulting from the
3195 * operation are inserted. Should not be NULL. See above the note
3196 * about the schema.
3197 *
3198 * @param papszOptions NULL terminated list of options (may be NULL).
3199 *
3200 * @param pfnProgress a GDALProgressFunc() compatible callback function for
3201 * reporting progress or NULL.
3202 *
3203 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3204 *
3205 * @return an error code if there was an error or the execution was
3206 * interrupted, OGRERR_NONE otherwise.
3207 *
3208 * @since OGR 1.10
3209 */
3210
Update(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3211 OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
3212 OGRLayer *pLayerResult,
3213 char** papszOptions,
3214 GDALProgressFunc pfnProgress,
3215 void * pProgressArg )
3216 {
3217 OGRErr ret = OGRERR_NONE;
3218 OGRFeatureDefn *poDefnInput = GetLayerDefn();
3219 OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
3220 OGRFeatureDefn *poDefnResult = NULL;
3221 OGRGeometry *pGeometryMethodFilter = NULL;
3222 int *mapInput = NULL;
3223 int *mapMethod = NULL;
3224 double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
3225 double progress_counter = 0;
3226 double progress_ticker = 0;
3227 int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
3228 int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
3229
3230 // check for GEOS
3231 if (!OGRGeometryFactory::haveGEOS()) {
3232 return OGRERR_UNSUPPORTED_OPERATION;
3233 }
3234
3235 // get resources
3236 ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
3237 if (ret != OGRERR_NONE) goto done;
3238 ret = create_field_map(poDefnInput, &mapInput);
3239 if (ret != OGRERR_NONE) goto done;
3240 ret = create_field_map(poDefnMethod, &mapMethod);
3241 if (ret != OGRERR_NONE) goto done;
3242 ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 0, papszOptions);
3243 if (ret != OGRERR_NONE) goto done;
3244 poDefnResult = pLayerResult->GetLayerDefn();
3245
3246 // add clipped features from the input layer
3247 ResetReading();
3248 while (OGRFeature *x = GetNextFeature()) {
3249
3250 if (pfnProgress) {
3251 double p = progress_counter/progress_max;
3252 if (p > progress_ticker) {
3253 if (!pfnProgress(p, "", pProgressArg)) {
3254 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3255 ret = OGRERR_FAILURE;
3256 delete x;
3257 goto done;
3258 }
3259 }
3260 progress_counter += 1.0;
3261 }
3262
3263 // set up the filter on method layer
3264 OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
3265 if (!x_geom) {
3266 delete x;
3267 continue;
3268 }
3269
3270 OGRGeometry *x_geom_diff = x_geom->clone(); //this will be the geometry of a result feature
3271 pLayerMethod->ResetReading();
3272 while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
3273 OGRGeometry *y_geom = y->GetGeometryRef();
3274 if (!y_geom) {delete y; continue;}
3275 OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
3276 if (x_geom_diff) delete x_geom_diff;
3277 x_geom_diff = x_geom_diff_new;
3278 delete y;
3279 }
3280
3281 if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
3282 {
3283 delete x_geom_diff;
3284 delete x;
3285 }
3286 else
3287 {
3288 OGRFeature *z = new OGRFeature(poDefnResult);
3289 z->SetFieldsFrom(x, mapInput);
3290 if( bPromoteToMulti )
3291 x_geom_diff = promote_to_multi(x_geom_diff);
3292 z->SetGeometryDirectly(x_geom_diff);
3293 delete x;
3294 ret = pLayerResult->CreateFeature(z);
3295 delete z;
3296 if (ret != OGRERR_NONE) {
3297 if (!bSkipFailures) {
3298 goto done;
3299 } else {
3300 CPLErrorReset();
3301 ret = OGRERR_NONE;
3302 }
3303 }
3304 }
3305 }
3306
3307 // restore the original filter and add features from the update layer
3308 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3309 pLayerMethod->ResetReading();
3310 while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
3311
3312 if (pfnProgress) {
3313 double p = progress_counter/progress_max;
3314 if (p > progress_ticker) {
3315 if (!pfnProgress(p, "", pProgressArg)) {
3316 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3317 ret = OGRERR_FAILURE;
3318 delete y;
3319 goto done;
3320 }
3321 }
3322 progress_counter += 1.0;
3323 }
3324
3325 OGRGeometry *y_geom = y->GetGeometryRef();
3326 if (!y_geom) {delete y; continue;}
3327 OGRFeature *z = new OGRFeature(poDefnResult);
3328 if (mapMethod) z->SetFieldsFrom(y, mapMethod);
3329 z->SetGeometry(y_geom);
3330 delete y;
3331 ret = pLayerResult->CreateFeature(z);
3332 delete z;
3333 if (ret != OGRERR_NONE) {
3334 if (!bSkipFailures) {
3335 goto done;
3336 } else {
3337 CPLErrorReset();
3338 ret = OGRERR_NONE;
3339 }
3340 }
3341 }
3342 if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3343 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3344 ret = OGRERR_FAILURE;
3345 goto done;
3346 }
3347 done:
3348 // release resources
3349 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3350 if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3351 if (mapInput) VSIFree(mapInput);
3352 if (mapMethod) VSIFree(mapMethod);
3353 return ret;
3354 }
3355
3356 /************************************************************************/
3357 /* OGR_L_Update() */
3358 /************************************************************************/
3359
3360 /**
3361 * \brief Update this layer with features from the update layer.
3362 *
3363 * The result layer contains features whose geometries represent areas
3364 * that are either in the input layer or in the method layer. The
3365 * features in the result layer have areas of the features of the
3366 * method layer or those ares of the features of the input layer that
3367 * are not covered by the method layer. The features of the result
3368 * layer get their attributes from the input layer. The schema of the
3369 * result layer can be set by the user or, if it is empty, is
3370 * initialized to contain all fields in the input layer.
3371 *
3372 * \note If the schema of the result is set by user and contains
3373 * fields that have the same name as a field in the method layer, then
3374 * the attribute in the result feature the originates from the method
3375 * layer will get the value from the feature of the method layer.
3376 *
3377 * \note For best performance use the minimum amount of features in
3378 * the method layer and copy it into a memory layer.
3379 *
3380 * \note This method relies on GEOS support. Do not use unless the
3381 * GEOS support is compiled in.
3382 *
3383 * The recognized list of options is :
3384 * <ul>
3385 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3386 * feature could not be inserted.
3387 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3388 * into MultiPolygons, or LineStrings to MultiLineStrings.
3389 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3390 * will be created from the fields of the input layer.
3391 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3392 * will be created from the fields of the method layer.
3393 * </ul>
3394 *
3395 * This function is the same as the C++ method OGRLayer::Update().
3396 *
3397 * @param pLayerInput the input layer. Should not be NULL.
3398 *
3399 * @param pLayerMethod the method layer. Should not be NULL.
3400 *
3401 * @param pLayerResult the layer where the features resulting from the
3402 * operation are inserted. Should not be NULL. See above the note
3403 * about the schema.
3404 *
3405 * @param papszOptions NULL terminated list of options (may be NULL).
3406 *
3407 * @param pfnProgress a GDALProgressFunc() compatible callback function for
3408 * reporting progress or NULL.
3409 *
3410 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3411 *
3412 * @return an error code if there was an error or the execution was
3413 * interrupted, OGRERR_NONE otherwise.
3414 *
3415 * @since OGR 1.10
3416 */
3417
OGR_L_Update(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3418 OGRErr OGR_L_Update( OGRLayerH pLayerInput,
3419 OGRLayerH pLayerMethod,
3420 OGRLayerH pLayerResult,
3421 char** papszOptions,
3422 GDALProgressFunc pfnProgress,
3423 void * pProgressArg )
3424
3425 {
3426 VALIDATE_POINTER1( pLayerInput, "OGR_L_Update", OGRERR_INVALID_HANDLE );
3427 VALIDATE_POINTER1( pLayerMethod, "OGR_L_Update", OGRERR_INVALID_HANDLE );
3428 VALIDATE_POINTER1( pLayerResult, "OGR_L_Update", OGRERR_INVALID_HANDLE );
3429
3430 return ((OGRLayer *)pLayerInput)->Update( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3431 }
3432
3433 /************************************************************************/
3434 /* Clip() */
3435 /************************************************************************/
3436
3437 /**
3438 * \brief Clip off areas that are not covered by the method layer.
3439 *
3440 * The result layer contains features whose geometries represent areas
3441 * that are in the input layer and in the method layer. The features
3442 * in the result layer have the (possibly clipped) areas of features
3443 * in the input layer and the attributes from the same features. The
3444 * schema of the result layer can be set by the user or, if it is
3445 * empty, is initialized to contain all fields in the input layer.
3446 *
3447 * \note For best performance use the minimum amount of features in
3448 * the method layer and copy it into a memory layer.
3449 *
3450 * \note This method relies on GEOS support. Do not use unless the
3451 * GEOS support is compiled in.
3452 *
3453 * The recognized list of options is :
3454 * <ul>
3455 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3456 * feature could not be inserted.
3457 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3458 * into MultiPolygons, or LineStrings to MultiLineStrings.
3459 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3460 * will be created from the fields of the input layer.
3461 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3462 * will be created from the fields of the method layer.
3463 * </ul>
3464 *
3465 * This method is the same as the C function OGR_L_Clip().
3466 *
3467 * @param pLayerMethod the method layer. Should not be NULL.
3468 *
3469 * @param pLayerResult the layer where the features resulting from the
3470 * operation are inserted. Should not be NULL. See above the note
3471 * about the schema.
3472 *
3473 * @param papszOptions NULL terminated list of options (may be NULL).
3474 *
3475 * @param pfnProgress a GDALProgressFunc() compatible callback function for
3476 * reporting progress or NULL.
3477 *
3478 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3479 *
3480 * @return an error code if there was an error or the execution was
3481 * interrupted, OGRERR_NONE otherwise.
3482 *
3483 * @since OGR 1.10
3484 */
3485
Clip(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3486 OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
3487 OGRLayer *pLayerResult,
3488 char** papszOptions,
3489 GDALProgressFunc pfnProgress,
3490 void * pProgressArg )
3491 {
3492 OGRErr ret = OGRERR_NONE;
3493 OGRFeatureDefn *poDefnInput = GetLayerDefn();
3494 OGRFeatureDefn *poDefnResult = NULL;
3495 OGRGeometry *pGeometryMethodFilter = NULL;
3496 int *mapInput = NULL;
3497 double progress_max = (double) GetFeatureCount(0);
3498 double progress_counter = 0;
3499 double progress_ticker = 0;
3500 int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
3501 int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
3502
3503 // check for GEOS
3504 if (!OGRGeometryFactory::haveGEOS()) {
3505 return OGRERR_UNSUPPORTED_OPERATION;
3506 }
3507
3508 ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
3509 if (ret != OGRERR_NONE) goto done;
3510 ret = create_field_map(poDefnInput, &mapInput);
3511 if (ret != OGRERR_NONE) goto done;
3512 ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0, papszOptions);
3513 if (ret != OGRERR_NONE) goto done;
3514
3515 poDefnResult = pLayerResult->GetLayerDefn();
3516 ResetReading();
3517 while (OGRFeature *x = GetNextFeature()) {
3518
3519 if (pfnProgress) {
3520 double p = progress_counter/progress_max;
3521 if (p > progress_ticker) {
3522 if (!pfnProgress(p, "", pProgressArg)) {
3523 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3524 ret = OGRERR_FAILURE;
3525 delete x;
3526 goto done;
3527 }
3528 }
3529 progress_counter += 1.0;
3530 }
3531
3532 // set up the filter on method layer
3533 OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
3534 if (!x_geom) {
3535 delete x;
3536 continue;
3537 }
3538
3539 OGRGeometry *geom = NULL; // this will be the geometry of the result feature
3540 pLayerMethod->ResetReading();
3541 // incrementally add area from y to geom
3542 while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
3543 OGRGeometry *y_geom = y->GetGeometryRef();
3544 if (!y_geom) {delete y; continue;}
3545 if (!geom) {
3546 geom = y_geom->clone();
3547 } else {
3548 OGRGeometry *geom_new = geom->Union(y_geom);
3549 delete geom;
3550 geom = geom_new;
3551 }
3552 delete y;
3553 }
3554
3555 // possibly add a new feature with area x intersection sum of y
3556 OGRFeature *z = NULL;
3557 if (geom) {
3558 OGRGeometry* poIntersection = x_geom->Intersection(geom);
3559 if( poIntersection != NULL && !poIntersection->IsEmpty() )
3560 {
3561 z = new OGRFeature(poDefnResult);
3562 z->SetFieldsFrom(x, mapInput);
3563 if( bPromoteToMulti )
3564 poIntersection = promote_to_multi(poIntersection);
3565 z->SetGeometryDirectly(poIntersection);
3566 }
3567 else
3568 delete poIntersection;
3569 delete geom;
3570 }
3571 delete x;
3572 if (z) {
3573 if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
3574 ret = pLayerResult->CreateFeature(z);
3575 delete z;
3576 if (ret != OGRERR_NONE) {
3577 if (!bSkipFailures) {
3578 goto done;
3579 } else {
3580 CPLErrorReset();
3581 ret = OGRERR_NONE;
3582 }
3583 }
3584 }
3585 }
3586 if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3587 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3588 ret = OGRERR_FAILURE;
3589 goto done;
3590 }
3591 done:
3592 // release resources
3593 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3594 if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3595 if (mapInput) VSIFree(mapInput);
3596 return ret;
3597 }
3598
3599 /************************************************************************/
3600 /* OGR_L_Clip() */
3601 /************************************************************************/
3602
3603 /**
3604 * \brief Clip off areas that are not covered by the method layer.
3605 *
3606 * The result layer contains features whose geometries represent areas
3607 * that are in the input layer and in the method layer. The features
3608 * in the result layer have the (possibly clipped) areas of features
3609 * in the input layer and the attributes from the same features. The
3610 * schema of the result layer can be set by the user or, if it is
3611 * empty, is initialized to contain all fields in the input layer.
3612 *
3613 * \note For best performance use the minimum amount of features in
3614 * the method layer and copy it into a memory layer.
3615 *
3616 * \note This method relies on GEOS support. Do not use unless the
3617 * GEOS support is compiled in.
3618 *
3619 * The recognized list of options is :
3620 * <ul>
3621 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3622 * feature could not be inserted.
3623 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3624 * into MultiPolygons, or LineStrings to MultiLineStrings.
3625 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3626 * will be created from the fields of the input layer.
3627 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3628 * will be created from the fields of the method layer.
3629 * </ul>
3630 *
3631 * This function is the same as the C++ method OGRLayer::Clip().
3632 *
3633 * @param pLayerInput the input layer. Should not be NULL.
3634 *
3635 * @param pLayerMethod the method layer. Should not be NULL.
3636 *
3637 * @param pLayerResult the layer where the features resulting from the
3638 * operation are inserted. Should not be NULL. See above the note
3639 * about the schema.
3640 *
3641 * @param papszOptions NULL terminated list of options (may be NULL).
3642 *
3643 * @param pfnProgress a GDALProgressFunc() compatible callback function for
3644 * reporting progress or NULL.
3645 *
3646 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3647 *
3648 * @return an error code if there was an error or the execution was
3649 * interrupted, OGRERR_NONE otherwise.
3650 *
3651 * @since OGR 1.10
3652 */
3653
OGR_L_Clip(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3654 OGRErr OGR_L_Clip( OGRLayerH pLayerInput,
3655 OGRLayerH pLayerMethod,
3656 OGRLayerH pLayerResult,
3657 char** papszOptions,
3658 GDALProgressFunc pfnProgress,
3659 void * pProgressArg )
3660
3661 {
3662 VALIDATE_POINTER1( pLayerInput, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
3663 VALIDATE_POINTER1( pLayerMethod, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
3664 VALIDATE_POINTER1( pLayerResult, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
3665
3666 return ((OGRLayer *)pLayerInput)->Clip( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3667 }
3668
3669 /************************************************************************/
3670 /* Erase() */
3671 /************************************************************************/
3672
3673 /**
3674 * \brief Remove areas that are covered by the method layer.
3675 *
3676 * The result layer contains features whose geometries represent areas
3677 * that are in the input layer but not in the method layer. The
3678 * features in the result layer have attributes from the input
3679 * layer. The schema of the result layer can be set by the user or, if
3680 * it is empty, is initialized to contain all fields in the input
3681 * layer.
3682 *
3683 * \note For best performance use the minimum amount of features in
3684 * the method layer and copy it into a memory layer.
3685 *
3686 * \note This method relies on GEOS support. Do not use unless the
3687 * GEOS support is compiled in.
3688 *
3689 * The recognized list of options is :
3690 * <ul>
3691 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3692 * feature could not be inserted.
3693 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3694 * into MultiPolygons, or LineStrings to MultiLineStrings.
3695 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3696 * will be created from the fields of the input layer.
3697 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3698 * will be created from the fields of the method layer.
3699 * </ul>
3700 *
3701 * This method is the same as the C function OGR_L_Erase().
3702 *
3703 * @param pLayerMethod the method layer. Should not be NULL.
3704 *
3705 * @param pLayerResult the layer where the features resulting from the
3706 * operation are inserted. Should not be NULL. See above the note
3707 * about the schema.
3708 *
3709 * @param papszOptions NULL terminated list of options (may be NULL).
3710 *
3711 * @param pfnProgress a GDALProgressFunc() compatible callback function for
3712 * reporting progress or NULL.
3713 *
3714 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3715 *
3716 * @return an error code if there was an error or the execution was
3717 * interrupted, OGRERR_NONE otherwise.
3718 *
3719 * @since OGR 1.10
3720 */
3721
Erase(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3722 OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
3723 OGRLayer *pLayerResult,
3724 char** papszOptions,
3725 GDALProgressFunc pfnProgress,
3726 void * pProgressArg )
3727 {
3728 OGRErr ret = OGRERR_NONE;
3729 OGRFeatureDefn *poDefnInput = GetLayerDefn();
3730 OGRFeatureDefn *poDefnResult = NULL;
3731 OGRGeometry *pGeometryMethodFilter = NULL;
3732 int *mapInput = NULL;
3733 double progress_max = (double) GetFeatureCount(0);
3734 double progress_counter = 0;
3735 double progress_ticker = 0;
3736 int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
3737 int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
3738
3739 // check for GEOS
3740 if (!OGRGeometryFactory::haveGEOS()) {
3741 return OGRERR_UNSUPPORTED_OPERATION;
3742 }
3743
3744 // get resources
3745 ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
3746 if (ret != OGRERR_NONE) goto done;
3747 ret = create_field_map(poDefnInput, &mapInput);
3748 if (ret != OGRERR_NONE) goto done;
3749 ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0, papszOptions);
3750 if (ret != OGRERR_NONE) goto done;
3751 poDefnResult = pLayerResult->GetLayerDefn();
3752
3753 ResetReading();
3754 while (OGRFeature *x = GetNextFeature()) {
3755
3756 if (pfnProgress) {
3757 double p = progress_counter/progress_max;
3758 if (p > progress_ticker) {
3759 if (!pfnProgress(p, "", pProgressArg)) {
3760 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3761 ret = OGRERR_FAILURE;
3762 delete x;
3763 goto done;
3764 }
3765 }
3766 progress_counter += 1.0;
3767 }
3768
3769 // set up the filter on the method layer
3770 OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
3771 if (!x_geom) {
3772 delete x;
3773 continue;
3774 }
3775
3776 OGRGeometry *geom = NULL; // this will be the geometry of the result feature
3777 pLayerMethod->ResetReading();
3778 // incrementally add area from y to geom
3779 while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
3780 OGRGeometry *y_geom = y->GetGeometryRef();
3781 if (!y_geom) {delete y; continue;}
3782 if (!geom) {
3783 geom = y_geom->clone();
3784 } else {
3785 OGRGeometry *geom_new = geom->Union(y_geom);
3786 delete geom;
3787 geom = geom_new;
3788 }
3789 delete y;
3790 }
3791
3792 // possibly add a new feature with area x minus sum of y
3793 OGRFeature *z = NULL;
3794 if (geom) {
3795 OGRGeometry* x_geom_diff = x_geom->Difference(geom);
3796 if( x_geom_diff != NULL && !x_geom_diff->IsEmpty() )
3797 {
3798 z = new OGRFeature(poDefnResult);
3799 z->SetFieldsFrom(x, mapInput);
3800 if( bPromoteToMulti )
3801 x_geom_diff = promote_to_multi(x_geom_diff);
3802 z->SetGeometryDirectly(x_geom_diff);
3803 }
3804 else
3805 delete x_geom_diff;
3806 delete geom;
3807 }
3808 delete x;
3809 if (z) {
3810 if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
3811 ret = pLayerResult->CreateFeature(z);
3812 delete z;
3813 if (ret != OGRERR_NONE) {
3814 if (!bSkipFailures) {
3815 goto done;
3816 } else {
3817 CPLErrorReset();
3818 ret = OGRERR_NONE;
3819 }
3820 }
3821 }
3822 }
3823 if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3824 CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3825 ret = OGRERR_FAILURE;
3826 goto done;
3827 }
3828 done:
3829 // release resources
3830 pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3831 if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3832 if (mapInput) VSIFree(mapInput);
3833 return ret;
3834 }
3835
3836 /************************************************************************/
3837 /* OGR_L_Erase() */
3838 /************************************************************************/
3839
3840 /**
3841 * \brief Remove areas that are covered by the method layer.
3842 *
3843 * The result layer contains features whose geometries represent areas
3844 * that are in the input layer but not in the method layer. The
3845 * features in the result layer have attributes from the input
3846 * layer. The schema of the result layer can be set by the user or, if
3847 * it is empty, is initialized to contain all fields in the input
3848 * layer.
3849 *
3850 * \note For best performance use the minimum amount of features in
3851 * the method layer and copy it into a memory layer.
3852 *
3853 * \note This method relies on GEOS support. Do not use unless the
3854 * GEOS support is compiled in.
3855 *
3856 * The recognized list of options is :
3857 * <ul>
3858 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3859 * feature could not be inserted.
3860 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3861 * into MultiPolygons, or LineStrings to MultiLineStrings.
3862 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3863 * will be created from the fields of the input layer.
3864 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3865 * will be created from the fields of the method layer.
3866 * </ul>
3867 *
3868 * This function is the same as the C++ method OGRLayer::Erase().
3869 *
3870 * @param pLayerInput the input layer. Should not be NULL.
3871 *
3872 * @param pLayerMethod the method layer. Should not be NULL.
3873 *
3874 * @param pLayerResult the layer where the features resulting from the
3875 * operation are inserted. Should not be NULL. See above the note
3876 * about the schema.
3877 *
3878 * @param papszOptions NULL terminated list of options (may be NULL).
3879 *
3880 * @param pfnProgress a GDALProgressFunc() compatible callback function for
3881 * reporting progress or NULL.
3882 *
3883 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3884 *
3885 * @return an error code if there was an error or the execution was
3886 * interrupted, OGRERR_NONE otherwise.
3887 *
3888 * @since OGR 1.10
3889 */
3890
OGR_L_Erase(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3891 OGRErr OGR_L_Erase( OGRLayerH pLayerInput,
3892 OGRLayerH pLayerMethod,
3893 OGRLayerH pLayerResult,
3894 char** papszOptions,
3895 GDALProgressFunc pfnProgress,
3896 void * pProgressArg )
3897
3898 {
3899 VALIDATE_POINTER1( pLayerInput, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3900 VALIDATE_POINTER1( pLayerMethod, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3901 VALIDATE_POINTER1( pLayerResult, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3902
3903 return ((OGRLayer *)pLayerInput)->Erase( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3904 }
3905