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