1 : /******************************************************************************
2 : * $Id: ogrlayer.cpp 25268 2012-11-29 20:21:41Z 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 25268 2012-11-29 20:21:41Z rouault $");
37 :
38 : /************************************************************************/
39 : /* OGRLayer() */
40 : /************************************************************************/
41 :
42 26188 : OGRLayer::OGRLayer()
43 :
44 : {
45 26188 : m_poStyleTable = NULL;
46 26188 : m_poAttrQuery = NULL;
47 26188 : m_poAttrIndex = NULL;
48 26188 : m_nRefCount = 0;
49 :
50 26188 : m_nFeaturesRead = 0;
51 :
52 26188 : m_poFilterGeom = NULL;
53 26188 : m_bFilterIsEnvelope = FALSE;
54 26188 : m_pPreparedFilterGeom = NULL;
55 26188 : }
56 :
57 : /************************************************************************/
58 : /* ~OGRLayer() */
59 : /************************************************************************/
60 :
61 26188 : OGRLayer::~OGRLayer()
62 :
63 : {
64 26188 : if ( m_poStyleTable )
65 : {
66 3 : delete m_poStyleTable;
67 3 : m_poStyleTable = NULL;
68 : }
69 :
70 26188 : if( m_poAttrIndex != NULL )
71 : {
72 47 : delete m_poAttrIndex;
73 47 : m_poAttrIndex = NULL;
74 : }
75 :
76 26188 : if( m_poAttrQuery != NULL )
77 : {
78 58 : delete m_poAttrQuery;
79 58 : m_poAttrQuery = NULL;
80 : }
81 :
82 26188 : if( m_poFilterGeom )
83 : {
84 86 : delete m_poFilterGeom;
85 86 : m_poFilterGeom = NULL;
86 : }
87 :
88 26188 : if( m_pPreparedFilterGeom != NULL )
89 : {
90 86 : OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
91 86 : m_pPreparedFilterGeom = NULL;
92 : }
93 26188 : }
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 19 : int OGRLayer::GetRefCount() const
144 :
145 : {
146 19 : 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 536 : int OGRLayer::GetFeatureCount( int bForce )
166 :
167 : {
168 : OGRFeature *poFeature;
169 536 : int nFeatureCount = 0;
170 :
171 536 : if( !bForce )
172 0 : return -1;
173 :
174 536 : ResetReading();
175 214063 : while( (poFeature = GetNextFeature()) != NULL )
176 : {
177 212991 : nFeatureCount++;
178 212991 : delete poFeature;
179 : }
180 536 : ResetReading();
181 :
182 536 : return nFeatureCount;
183 : }
184 :
185 : /************************************************************************/
186 : /* OGR_L_GetFeatureCount() */
187 : /************************************************************************/
188 :
189 710 : int OGR_L_GetFeatureCount( OGRLayerH hLayer, int bForce )
190 :
191 : {
192 710 : VALIDATE_POINTER1( hLayer, "OGR_L_GetFeature", 0 );
193 :
194 710 : return ((OGRLayer *) hLayer)->GetFeatureCount(bForce);
195 : }
196 :
197 : /************************************************************************/
198 : /* GetExtent() */
199 : /************************************************************************/
200 :
201 210 : OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
202 :
203 : {
204 : OGRFeature *poFeature;
205 210 : OGREnvelope oEnv;
206 210 : GBool bExtentSet = FALSE;
207 :
208 210 : psExtent->MinX = 0.0;
209 210 : psExtent->MaxX = 0.0;
210 210 : psExtent->MinY = 0.0;
211 210 : 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 210 : 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 142 : 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 142 : ResetReading();
232 70732 : while( (poFeature = GetNextFeature()) != NULL )
233 : {
234 70448 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
235 70448 : if (poGeom == NULL || poGeom->IsEmpty())
236 : {
237 : /* Do nothing */
238 : }
239 70026 : else if (!bExtentSet)
240 : {
241 130 : poGeom->getEnvelope(psExtent);
242 130 : bExtentSet = TRUE;
243 : }
244 : else
245 : {
246 69896 : poGeom->getEnvelope(&oEnv);
247 69896 : if (oEnv.MinX < psExtent->MinX)
248 203 : psExtent->MinX = oEnv.MinX;
249 69896 : if (oEnv.MinY < psExtent->MinY)
250 2063 : psExtent->MinY = oEnv.MinY;
251 69896 : if (oEnv.MaxX > psExtent->MaxX)
252 306 : psExtent->MaxX = oEnv.MaxX;
253 69896 : if (oEnv.MaxY > psExtent->MaxY)
254 177 : psExtent->MaxY = oEnv.MaxY;
255 : }
256 70448 : delete poFeature;
257 : }
258 142 : ResetReading();
259 :
260 142 : 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 2086 : OGRErr OGRLayer::SetAttributeFilter( const char *pszQuery )
280 :
281 : {
282 : /* -------------------------------------------------------------------- */
283 : /* Are we just clearing any existing query? */
284 : /* -------------------------------------------------------------------- */
285 2086 : if( pszQuery == NULL || strlen(pszQuery) == 0 )
286 : {
287 1240 : if( m_poAttrQuery )
288 : {
289 385 : delete m_poAttrQuery;
290 385 : m_poAttrQuery = NULL;
291 385 : ResetReading();
292 : }
293 1240 : return OGRERR_NONE;
294 : }
295 :
296 : /* -------------------------------------------------------------------- */
297 : /* Or are we installing a new query? */
298 : /* -------------------------------------------------------------------- */
299 : OGRErr eErr;
300 :
301 846 : if( !m_poAttrQuery )
302 443 : m_poAttrQuery = new OGRFeatureQuery();
303 :
304 846 : eErr = m_poAttrQuery->Compile( GetLayerDefn(), pszQuery );
305 846 : if( eErr != OGRERR_NONE )
306 : {
307 0 : delete m_poAttrQuery;
308 0 : m_poAttrQuery = NULL;
309 : }
310 :
311 846 : ResetReading();
312 :
313 846 : 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 240 : OGRErr OGR_L_SetAttributeFilter( OGRLayerH hLayer, const char *pszQuery )
366 :
367 : {
368 240 : VALIDATE_POINTER1( hLayer, "OGR_L_SetAttributeFilter", OGRERR_INVALID_HANDLE );
369 :
370 240 : 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 48332 : while( (poFeature = GetNextFeature()) != NULL )
384 : {
385 48171 : if( poFeature->GetFID() == nFID )
386 13 : return poFeature;
387 : else
388 48158 : delete poFeature;
389 : }
390 :
391 74 : return NULL;
392 : }
393 :
394 : /************************************************************************/
395 : /* OGR_L_GetFeature() */
396 : /************************************************************************/
397 :
398 97 : OGRFeatureH OGR_L_GetFeature( OGRLayerH hLayer, long nFeatureId )
399 :
400 : {
401 97 : VALIDATE_POINTER1( hLayer, "OGR_L_GetFeature", NULL );
402 :
403 97 : 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 87206 : OGRFeatureH OGR_L_GetNextFeature( OGRLayerH hLayer )
448 :
449 : {
450 87206 : VALIDATE_POINTER1( hLayer, "OGR_L_GetNextFeature", NULL );
451 :
452 87206 : 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 33973 : OGRErr OGR_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
493 :
494 : {
495 33973 : VALIDATE_POINTER1( hLayer, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
496 33973 : VALIDATE_POINTER1( hFeat, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
497 :
498 33973 : 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 4754 : OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
533 : int bApproxOK )
534 :
535 : {
536 4754 : VALIDATE_POINTER1( hLayer, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
537 4754 : VALIDATE_POINTER1( hField, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
538 :
539 : return ((OGRLayer *) hLayer)->CreateField( (OGRFieldDefn *) hField,
540 4754 : 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 807 : OGRErr OGRLayer::StartTransaction()
704 :
705 : {
706 807 : return OGRERR_NONE;
707 : }
708 :
709 : /************************************************************************/
710 : /* OGR_L_StartTransaction() */
711 : /************************************************************************/
712 :
713 71 : OGRErr OGR_L_StartTransaction( OGRLayerH hLayer )
714 :
715 : {
716 71 : VALIDATE_POINTER1( hLayer, "OGR_L_StartTransaction", OGRERR_INVALID_HANDLE );
717 :
718 71 : return ((OGRLayer *)hLayer)->StartTransaction();
719 : }
720 :
721 : /************************************************************************/
722 : /* CommitTransaction() */
723 : /************************************************************************/
724 :
725 784 : OGRErr OGRLayer::CommitTransaction()
726 :
727 : {
728 784 : return OGRERR_NONE;
729 : }
730 :
731 : /************************************************************************/
732 : /* OGR_L_CommitTransaction() */
733 : /************************************************************************/
734 :
735 68 : OGRErr OGR_L_CommitTransaction( OGRLayerH hLayer )
736 :
737 : {
738 68 : VALIDATE_POINTER1( hLayer, "OGR_L_CommitTransaction", OGRERR_INVALID_HANDLE );
739 :
740 68 : 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 33274 : OGRFeatureDefnH OGR_L_GetLayerDefn( OGRLayerH hLayer )
770 :
771 : {
772 33274 : VALIDATE_POINTER1( hLayer, "OGR_L_GetLayerDefn", NULL );
773 :
774 33274 : return (OGRFeatureDefnH) ((OGRLayer *)hLayer)->GetLayerDefn();
775 : }
776 :
777 : /************************************************************************/
778 : /* OGR_L_GetSpatialRef() */
779 : /************************************************************************/
780 :
781 322 : OGRSpatialReferenceH OGR_L_GetSpatialRef( OGRLayerH hLayer )
782 :
783 : {
784 322 : VALIDATE_POINTER1( hLayer, "OGR_L_GetSpatialRef", NULL );
785 :
786 322 : return (OGRSpatialReferenceH) ((OGRLayer *) hLayer)->GetSpatialRef();
787 : }
788 :
789 : /************************************************************************/
790 : /* OGR_L_TestCapability() */
791 : /************************************************************************/
792 :
793 129 : int OGR_L_TestCapability( OGRLayerH hLayer, const char *pszCap )
794 :
795 : {
796 129 : VALIDATE_POINTER1( hLayer, "OGR_L_TestCapability", 0 );
797 129 : VALIDATE_POINTER1( pszCap, "OGR_L_TestCapability", 0 );
798 :
799 129 : return ((OGRLayer *) hLayer)->TestCapability( pszCap );
800 : }
801 :
802 : /************************************************************************/
803 : /* GetSpatialFilter() */
804 : /************************************************************************/
805 :
806 119 : OGRGeometry *OGRLayer::GetSpatialFilter()
807 :
808 : {
809 119 : 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 19326 : void OGRLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
829 :
830 : {
831 19326 : if( InstallFilter( poGeomIn ) )
832 17774 : ResetReading();
833 19326 : }
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 19524 : int OGRLayer::InstallFilter( OGRGeometry * poFilter )
899 :
900 : {
901 19524 : if( m_poFilterGeom == NULL && poFilter == NULL )
902 1656 : return FALSE;
903 :
904 : /* -------------------------------------------------------------------- */
905 : /* Replace the existing filter. */
906 : /* -------------------------------------------------------------------- */
907 17868 : if( m_poFilterGeom != NULL )
908 : {
909 17680 : delete m_poFilterGeom;
910 17680 : m_poFilterGeom = NULL;
911 : }
912 :
913 17868 : if( m_pPreparedFilterGeom != NULL )
914 : {
915 17680 : OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
916 17680 : m_pPreparedFilterGeom = NULL;
917 : }
918 :
919 17868 : if( poFilter != NULL )
920 17766 : m_poFilterGeom = poFilter->clone();
921 :
922 17868 : m_bFilterIsEnvelope = FALSE;
923 :
924 17868 : if( m_poFilterGeom == NULL )
925 102 : return TRUE;
926 :
927 17766 : if( m_poFilterGeom != NULL )
928 17766 : m_poFilterGeom->getEnvelope( &m_sFilterEnvelope );
929 :
930 : /* Compile geometry filter as a prepared geometry */
931 17766 : m_pPreparedFilterGeom = OGRCreatePreparedGeometry(m_poFilterGeom);
932 :
933 : /* -------------------------------------------------------------------- */
934 : /* Now try to determine if the filter is really a rectangle. */
935 : /* -------------------------------------------------------------------- */
936 17766 : if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
937 12 : return TRUE;
938 :
939 17754 : OGRPolygon *poPoly = (OGRPolygon *) m_poFilterGeom;
940 :
941 17754 : if( poPoly->getNumInteriorRings() != 0 )
942 0 : return TRUE;
943 :
944 17754 : OGRLinearRing *poRing = poPoly->getExteriorRing();
945 17754 : if (poRing == NULL)
946 0 : return TRUE;
947 :
948 17754 : 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 17754 : 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 17754 : 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 17669 : m_bFilterIsEnvelope = TRUE;
963 :
964 : // Polygon with first segment in "x" direction.
965 17754 : 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 1146 : m_bFilterIsEnvelope = TRUE;
970 :
971 17754 : 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 178502 : 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 178502 : if( m_poFilterGeom == NULL )
991 28 : return TRUE;
992 :
993 178474 : 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 178047 : OGREnvelope sGeomEnv;
1002 :
1003 178047 : poGeometry->getEnvelope( &sGeomEnv );
1004 :
1005 178047 : 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 69449 : 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 56041 : 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 13408 : if( m_bFilterIsEnvelope )
1034 : {
1035 13394 : OGRLineString* poLS = NULL;
1036 :
1037 13394 : switch( wkbFlatten(poGeometry->getGeometryType()) )
1038 : {
1039 : case wkbPolygon:
1040 : {
1041 5767 : OGRPolygon* poPoly = (OGRPolygon* )poGeometry;
1042 5767 : OGRLinearRing* poRing = poPoly->getExteriorRing();
1043 5767 : if (poRing != NULL && poPoly->getNumInteriorRings() == 0)
1044 : {
1045 5444 : poLS = poRing;
1046 : }
1047 5767 : break;
1048 : }
1049 :
1050 : case wkbLineString:
1051 7626 : poLS = (OGRLineString* )poGeometry;
1052 : break;
1053 :
1054 : default:
1055 : break;
1056 : }
1057 :
1058 13394 : if( poLS != NULL )
1059 : {
1060 13070 : int nNumPoints = poLS->getNumPoints();
1061 426447 : for(int i = 0; i < nNumPoints; i++)
1062 : {
1063 424453 : double x = poLS->getX(i);
1064 424453 : double y = poLS->getY(i);
1065 424453 : if (x >= m_sFilterEnvelope.MinX &&
1066 : y >= m_sFilterEnvelope.MinY &&
1067 : x <= m_sFilterEnvelope.MaxX &&
1068 : y <= m_sFilterEnvelope.MaxY)
1069 : {
1070 11076 : 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 2332 : if( OGRGeometryFactory::haveGEOS() )
1081 : {
1082 : //CPLDebug("OGRLayer", "GEOS intersection");
1083 2332 : if( m_pPreparedFilterGeom != NULL )
1084 : return OGRPreparedGeometryIntersects(m_pPreparedFilterGeom,
1085 2332 : 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 18975 : void OGR_L_ResetReading( OGRLayerH hLayer )
1099 :
1100 : {
1101 18975 : VALIDATE_POINTER0( hLayer, "OGR_L_ResetReading" );
1102 :
1103 18975 : ((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 477 : OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
1115 :
1116 : {
1117 : OGRErr eErr;
1118 :
1119 477 : if (m_poAttrIndex != NULL)
1120 430 : 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 38 : OGRErr OGR_L_DeleteFeature( OGRLayerH hDS, long nFID )
1171 :
1172 : {
1173 38 : VALIDATE_POINTER1( hDS, "OGR_L_DeleteFeature", OGRERR_INVALID_HANDLE );
1174 :
1175 38 : 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 759 : const char *OGRLayer::GetGeometryColumn()
1227 :
1228 : {
1229 759 : return "";
1230 : }
1231 :
1232 : /************************************************************************/
1233 : /* OGR_L_GetGeometryColumn() */
1234 : /************************************************************************/
1235 :
1236 29 : const char *OGR_L_GetGeometryColumn( OGRLayerH hLayer )
1237 :
1238 : {
1239 29 : VALIDATE_POINTER1( hLayer, "OGR_L_GetGeometryColumn", NULL );
1240 :
1241 29 : return ((OGRLayer *) hLayer)->GetGeometryColumn();
1242 : }
1243 :
1244 : /************************************************************************/
1245 : /* GetStyleTable() */
1246 : /************************************************************************/
1247 :
1248 124 : OGRStyleTable *OGRLayer::GetStyleTable()
1249 : {
1250 124 : 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 124 : void OGRLayer::SetStyleTable(OGRStyleTable *poStyleTable)
1269 : {
1270 124 : if ( m_poStyleTable )
1271 0 : delete m_poStyleTable;
1272 124 : if ( poStyleTable )
1273 0 : m_poStyleTable = poStyleTable->Clone();
1274 124 : }
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 1059405 : const char *OGRLayer::GetName()
1320 :
1321 : {
1322 1059405 : return GetLayerDefn()->GetName();
1323 : }
1324 :
1325 : /************************************************************************/
1326 : /* OGR_L_GetName() */
1327 : /************************************************************************/
1328 :
1329 4158 : const char* OGR_L_GetName( OGRLayerH hLayer )
1330 :
1331 : {
1332 4158 : VALIDATE_POINTER1( hLayer, "OGR_L_GetName", "" );
1333 :
1334 4158 : return ((OGRLayer *) hLayer)->GetName();
1335 : }
1336 :
1337 : /************************************************************************/
1338 : /* GetGeomType() */
1339 : /************************************************************************/
1340 :
1341 1937 : OGRwkbGeometryType OGRLayer::GetGeomType()
1342 : {
1343 1937 : return GetLayerDefn()->GetGeomType();
1344 : }
1345 : /************************************************************************/
1346 : /* OGR_L_GetGeomType() */
1347 : /************************************************************************/
1348 :
1349 116 : OGRwkbGeometryType OGR_L_GetGeomType( OGRLayerH hLayer )
1350 :
1351 : {
1352 116 : VALIDATE_POINTER1( hLayer, "OGR_L_GetGeomType", wkbUnknown );
1353 :
1354 116 : return ((OGRLayer *) hLayer)->GetGeomType();
1355 : }
1356 :
1357 : /************************************************************************/
1358 : /* SetIgnoredFields() */
1359 : /************************************************************************/
1360 :
1361 1490 : OGRErr OGRLayer::SetIgnoredFields( const char **papszFields )
1362 : {
1363 1490 : OGRFeatureDefn *poDefn = GetLayerDefn();
1364 :
1365 : // first set everything as *not* ignored
1366 7634 : for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
1367 : {
1368 6144 : poDefn->GetFieldDefn(iField)->SetIgnored( FALSE );
1369 : }
1370 1490 : poDefn->SetGeometryIgnored( FALSE );
1371 1490 : poDefn->SetStyleIgnored( FALSE );
1372 :
1373 1490 : if ( papszFields == NULL )
1374 1255 : 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 9 : OGRErr clone_spatial_filter(OGRLayer *pLayer, OGRGeometry **ppGeometry)
1417 : {
1418 9 : OGRErr ret = OGRERR_NONE;
1419 9 : OGRGeometry *g = pLayer->GetSpatialFilter();
1420 9 : *ppGeometry = g ? g->clone() : NULL;
1421 9 : return ret;
1422 : }
1423 :
1424 12 : OGRErr create_field_map(OGRFeatureDefn *poDefn, int **map)
1425 : {
1426 12 : OGRErr ret = OGRERR_NONE;
1427 12 : int n = poDefn->GetFieldCount();
1428 12 : if (n > 0) {
1429 0 : *map = (int*)VSIMalloc(sizeof(int) * n);
1430 0 : if (!(*map)) return OGRERR_NOT_ENOUGH_MEMORY;
1431 : }
1432 12 : return ret;
1433 : }
1434 :
1435 7 : OGRErr set_result_schema(OGRLayer *pLayerResult,
1436 : OGRFeatureDefn *poDefnInput,
1437 : OGRFeatureDefn *poDefnMethod,
1438 : int *mapInput,
1439 : int *mapMethod,
1440 : int combined)
1441 : {
1442 7 : OGRErr ret = OGRERR_NONE;
1443 7 : OGRFeatureDefn *poDefnResult = pLayerResult->GetLayerDefn();
1444 7 : if (poDefnResult->GetFieldCount() > 0) {
1445 : // the user has defined the schema of the output layer
1446 0 : for( int iField = 0; iField < poDefnInput->GetFieldCount(); iField++ ) {
1447 0 : mapInput[iField] = poDefnResult->GetFieldIndex(poDefnInput->GetFieldDefn(iField)->GetNameRef());
1448 : }
1449 0 : if (!mapMethod) return ret;
1450 0 : for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
1451 0 : mapMethod[iField] = poDefnResult->GetFieldIndex(poDefnMethod->GetFieldDefn(iField)->GetNameRef());
1452 : }
1453 : } else {
1454 : // use schema from the input layer or from input and method layers
1455 7 : int nFieldsInput = poDefnInput->GetFieldCount();
1456 7 : for( int iField = 0; iField < nFieldsInput; iField++ ) {
1457 0 : ret = pLayerResult->CreateField(poDefnInput->GetFieldDefn(iField));
1458 0 : if (ret != OGRERR_NONE) return ret;
1459 0 : mapInput[iField] = iField;
1460 : }
1461 7 : if (!combined) return ret;
1462 4 : if (!mapMethod) return ret;
1463 0 : for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
1464 0 : ret = pLayerResult->CreateField(poDefnMethod->GetFieldDefn(iField));
1465 0 : if (ret != OGRERR_NONE) return ret;
1466 0 : mapMethod[iField] = nFieldsInput+iField;
1467 : }
1468 : }
1469 0 : return ret;
1470 : }
1471 :
1472 16 : OGRGeometry *set_filter_from(OGRLayer *pLayer, OGRGeometry *pGeometryExistingFilter, OGRFeature *pFeature)
1473 : {
1474 16 : OGRGeometry *geom = pFeature->GetGeometryRef();
1475 16 : if (!geom) return NULL;
1476 16 : if (pGeometryExistingFilter) {
1477 0 : if (!geom->Intersects(pGeometryExistingFilter)) return NULL;
1478 0 : OGRGeometry *intersection = geom->Intersection(pGeometryExistingFilter);
1479 0 : pLayer->SetSpatialFilter(intersection);
1480 0 : if (intersection) delete intersection;
1481 : } else {
1482 16 : pLayer->SetSpatialFilter(geom);
1483 : }
1484 16 : return geom;
1485 : }
1486 :
1487 : /************************************************************************/
1488 : /* Intersection() */
1489 : /************************************************************************/
1490 : /**
1491 : * \brief Intersection of two layers.
1492 : *
1493 : * The result layer contains features whose geometries represent areas
1494 : * that are common between features in the input layer and in the
1495 : * method layer. The features in the result layer have attributes from
1496 : * both input and method layers. The schema of the result layer can be
1497 : * set by the user or, if it is empty, is initialized to contain all
1498 : * fields in the input and method layers.
1499 : *
1500 : * \note If the schema of the result is set by user and contains
1501 : * fields that have the same name as a field in input and in method
1502 : * layer, then the attribute in the result feature will get the value
1503 : * from the feature of the method layer.
1504 : *
1505 : * \note For best performance use the minimum amount of features in
1506 : * the method layer and copy it into a memory layer.
1507 : *
1508 : * \note This method relies on GEOS support. Do not use unless the
1509 : * GEOS support is compiled in.
1510 : *
1511 : * This method is the same as the C function OGR_L_Intersection().
1512 : *
1513 : * @param pLayerMethod the method layer. Should not be NULL.
1514 : *
1515 : * @param pLayerResult the layer where the features resulting from the
1516 : * operation are inserted. Should not be NULL. See above the note
1517 : * about the schema.
1518 : *
1519 : * @param papszOptions NULL terminated list of options (may be NULL).
1520 : *
1521 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
1522 : * reporting progress or NULL.
1523 : *
1524 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
1525 : *
1526 : * @return an error code if there was an error or the execution was
1527 : * interrupted, OGRERR_NONE otherwise.
1528 : *
1529 : * @since OGR 1.10
1530 : */
1531 :
1532 1 : OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
1533 : OGRLayer *pLayerResult,
1534 : char** papszOptions,
1535 : GDALProgressFunc pfnProgress,
1536 : void * pProgressArg )
1537 : {
1538 1 : OGRErr ret = OGRERR_NONE;
1539 1 : OGRFeatureDefn *poDefnInput = GetLayerDefn();
1540 1 : OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
1541 1 : OGRFeatureDefn *poDefnResult = NULL;
1542 1 : OGRGeometry *pGeometryMethodFilter = NULL;
1543 1 : int *mapInput = NULL;
1544 1 : int *mapMethod = NULL;
1545 1 : OGREnvelope sEnvelopeMethod;
1546 : GBool bEnvelopeSet;
1547 1 : double progress_max = GetFeatureCount(0);
1548 1 : double progress_counter = 0;
1549 1 : double progress_ticker = 0;
1550 :
1551 : // check for GEOS
1552 1 : if (!OGRGeometryFactory::haveGEOS()) {
1553 0 : return OGRERR_UNSUPPORTED_OPERATION;
1554 : }
1555 :
1556 : // get resources
1557 1 : ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
1558 1 : if (ret != OGRERR_NONE) goto done;
1559 1 : ret = create_field_map(poDefnInput, &mapInput);
1560 1 : if (ret != OGRERR_NONE) goto done;
1561 1 : ret = create_field_map(poDefnMethod, &mapMethod);
1562 1 : if (ret != OGRERR_NONE) goto done;
1563 1 : ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1);
1564 1 : if (ret != OGRERR_NONE) goto done;
1565 1 : poDefnResult = pLayerResult->GetLayerDefn();
1566 1 : bEnvelopeSet = pLayerMethod->GetExtent(&sEnvelopeMethod, 1) == OGRERR_NONE;
1567 :
1568 1 : ResetReading();
1569 5 : while (OGRFeature *x = GetNextFeature()) {
1570 :
1571 2 : if (pfnProgress) {
1572 0 : double p = progress_counter/progress_max;
1573 0 : if (p > progress_ticker) {
1574 0 : if (!pfnProgress(p, "", pProgressArg)) {
1575 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
1576 0 : ret = OGRERR_FAILURE;
1577 0 : delete x;
1578 0 : goto done;
1579 : }
1580 0 : progress_ticker += 0.01;
1581 : }
1582 0 : progress_counter += 1.0;
1583 : }
1584 :
1585 : // is it worth to proceed?
1586 2 : if (bEnvelopeSet) {
1587 2 : OGRGeometry *x_geom = x->GetGeometryRef();
1588 2 : if (x_geom) {
1589 2 : OGREnvelope x_env;
1590 2 : x_geom->getEnvelope(&x_env);
1591 2 : if (x_env.MaxX < sEnvelopeMethod.MinX
1592 : || x_env.MaxY < sEnvelopeMethod.MinY
1593 : || sEnvelopeMethod.MaxX < x_env.MinX
1594 : || sEnvelopeMethod.MaxY < x_env.MinY) {
1595 0 : delete x;
1596 0 : continue;
1597 : }
1598 : } else {
1599 0 : delete x;
1600 0 : continue;
1601 : }
1602 : }
1603 :
1604 : // set up the filter for method layer
1605 2 : OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
1606 2 : if (!x_geom) {
1607 0 : delete x;
1608 0 : continue;
1609 : }
1610 :
1611 2 : pLayerMethod->ResetReading();
1612 6 : while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
1613 2 : OGRGeometry *y_geom = y->GetGeometryRef();
1614 2 : if (!y_geom) {delete y; continue;}
1615 2 : OGRFeature *z = new OGRFeature(poDefnResult);
1616 2 : z->SetFieldsFrom(x, mapInput);
1617 2 : z->SetFieldsFrom(y, mapMethod);
1618 2 : z->SetGeometryDirectly(x_geom->Intersection(y_geom));
1619 4 : delete y;
1620 2 : ret = pLayerResult->CreateFeature(z);
1621 2 : delete z;
1622 2 : if (ret != OGRERR_NONE) {delete x; goto done;}
1623 : }
1624 :
1625 4 : delete x;
1626 : }
1627 1 : if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
1628 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
1629 0 : ret = OGRERR_FAILURE;
1630 : goto done;
1631 : }
1632 : done:
1633 : // release resources
1634 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
1635 1 : if (pGeometryMethodFilter) delete pGeometryMethodFilter;
1636 1 : if (mapInput) VSIFree(mapInput);
1637 1 : if (mapMethod) VSIFree(mapMethod);
1638 1 : return ret;
1639 : }
1640 :
1641 : /************************************************************************/
1642 : /* OGR_L_Intersection() */
1643 : /************************************************************************/
1644 : /**
1645 : * \brief Intersection of two layers.
1646 : *
1647 : * The result layer contains features whose geometries represent areas
1648 : * that are common between features in the input layer and in the
1649 : * method layer. The features in the result layer have attributes from
1650 : * both input and method layers. The schema of the result layer can be
1651 : * set by the user or, if it is empty, is initialized to contain all
1652 : * fields in the input and method layers.
1653 : *
1654 : * \note If the schema of the result is set by user and contains
1655 : * fields that have the same name as a field in input and in method
1656 : * layer, then the attribute in the result feature will get the value
1657 : * from the feature of the method layer.
1658 : *
1659 : * \note For best performance use the minimum amount of features in
1660 : * the method layer and copy it into a memory layer.
1661 : *
1662 : * \note This method relies on GEOS support. Do not use unless the
1663 : * GEOS support is compiled in.
1664 : *
1665 : * This function is the same as the C++ method OGRLayer::Intersection().
1666 : *
1667 : * @param pLayerInput the input layer. Should not be NULL.
1668 : *
1669 : * @param pLayerMethod the method layer. Should not be NULL.
1670 : *
1671 : * @param pLayerResult the layer where the features resulting from the
1672 : * operation are inserted. Should not be NULL. See above the note
1673 : * about the schema.
1674 : *
1675 : * @param papszOptions NULL terminated list of options (may be NULL).
1676 : *
1677 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
1678 : * reporting progress or NULL.
1679 : *
1680 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
1681 : *
1682 : * @return an error code if there was an error or the execution was
1683 : * interrupted, OGRERR_NONE otherwise.
1684 : *
1685 : * @since OGR 1.10
1686 : */
1687 :
1688 1 : OGRErr OGR_L_Intersection( OGRLayerH pLayerInput,
1689 : OGRLayerH pLayerMethod,
1690 : OGRLayerH pLayerResult,
1691 : char** papszOptions,
1692 : GDALProgressFunc pfnProgress,
1693 : void * pProgressArg )
1694 :
1695 : {
1696 1 : VALIDATE_POINTER1( pLayerInput, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
1697 1 : VALIDATE_POINTER1( pLayerMethod, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
1698 1 : VALIDATE_POINTER1( pLayerResult, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
1699 :
1700 1 : return ((OGRLayer *)pLayerInput)->Intersection( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
1701 : }
1702 :
1703 : /************************************************************************/
1704 : /* Union() */
1705 : /************************************************************************/
1706 :
1707 : /**
1708 : * \brief Union of two layers.
1709 : *
1710 : * The result layer contains features whose geometries represent areas
1711 : * that are in either in the input layer or in the method layer. The
1712 : * features in the result layer have attributes from both input and
1713 : * method layers. For features which represent areas that are only in
1714 : * the input or in the method layer the respective attributes have
1715 : * undefined values. The schema of the result layer can be set by the
1716 : * user or, if it is empty, is initialized to contain all fields in
1717 : * the input and method layers.
1718 : *
1719 : * \note If the schema of the result is set by user and contains
1720 : * fields that have the same name as a field in input and in method
1721 : * layer, then the attribute in the result feature will get the value
1722 : * from the feature of the method layer (even if it is undefined).
1723 : *
1724 : * \note For best performance use the minimum amount of features in
1725 : * the method layer and copy it into a memory layer.
1726 : *
1727 : * \note This method relies on GEOS support. Do not use unless the
1728 : * GEOS support is compiled in.
1729 : *
1730 : * This method is the same as the C function OGR_L_Union().
1731 : *
1732 : * @param pLayerMethod the method layer. Should not be NULL.
1733 : *
1734 : * @param pLayerResult the layer where the features resulting from the
1735 : * operation are inserted. Should not be NULL. See above the note
1736 : * about the schema.
1737 : *
1738 : * @param papszOptions NULL terminated list of options (may be NULL).
1739 : *
1740 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
1741 : * reporting progress or NULL.
1742 : *
1743 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
1744 : *
1745 : * @return an error code if there was an error or the execution was
1746 : * interrupted, OGRERR_NONE otherwise.
1747 : *
1748 : * @since OGR 1.10
1749 : */
1750 :
1751 1 : OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
1752 : OGRLayer *pLayerResult,
1753 : char** papszOptions,
1754 : GDALProgressFunc pfnProgress,
1755 : void * pProgressArg )
1756 : {
1757 1 : OGRErr ret = OGRERR_NONE;
1758 1 : OGRFeatureDefn *poDefnInput = GetLayerDefn();
1759 1 : OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
1760 1 : OGRFeatureDefn *poDefnResult = NULL;
1761 1 : OGRGeometry *pGeometryMethodFilter = NULL;
1762 1 : OGRGeometry *pGeometryInputFilter = NULL;
1763 1 : int *mapInput = NULL;
1764 1 : int *mapMethod = NULL;
1765 1 : double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
1766 1 : double progress_counter = 0;
1767 1 : double progress_ticker = 0;
1768 :
1769 : // check for GEOS
1770 1 : if (!OGRGeometryFactory::haveGEOS()) {
1771 0 : return OGRERR_UNSUPPORTED_OPERATION;
1772 : }
1773 :
1774 : // get resources
1775 1 : ret = clone_spatial_filter(this, &pGeometryInputFilter);
1776 1 : if (ret != OGRERR_NONE) goto done;
1777 1 : ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
1778 1 : if (ret != OGRERR_NONE) goto done;
1779 1 : ret = create_field_map(poDefnInput, &mapInput);
1780 1 : if (ret != OGRERR_NONE) goto done;
1781 1 : ret = create_field_map(poDefnMethod, &mapMethod);
1782 1 : if (ret != OGRERR_NONE) goto done;
1783 1 : ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1);
1784 1 : if (ret != OGRERR_NONE) goto done;
1785 1 : poDefnResult = pLayerResult->GetLayerDefn();
1786 :
1787 : // add features based on input layer
1788 1 : ResetReading();
1789 5 : while (OGRFeature *x = GetNextFeature()) {
1790 :
1791 2 : if (pfnProgress) {
1792 0 : double p = progress_counter/progress_max;
1793 0 : if (p > progress_ticker) {
1794 0 : if (!pfnProgress(p, "", pProgressArg)) {
1795 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
1796 0 : ret = OGRERR_FAILURE;
1797 0 : delete x;
1798 0 : goto done;
1799 : }
1800 0 : progress_ticker += 0.01;
1801 : }
1802 0 : progress_counter += 1.0;
1803 : }
1804 :
1805 : // set up the filter on method layer
1806 2 : OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
1807 2 : if (!x_geom) {
1808 0 : delete x;
1809 0 : continue;
1810 : }
1811 :
1812 2 : OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
1813 2 : pLayerMethod->ResetReading();
1814 6 : while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
1815 2 : OGRGeometry *y_geom = y->GetGeometryRef();
1816 2 : if (!y_geom) {delete y; continue;}
1817 2 : OGRFeature *z = new OGRFeature(poDefnResult);
1818 2 : z->SetFieldsFrom(x, mapInput);
1819 2 : z->SetFieldsFrom(y, mapMethod);
1820 2 : z->SetGeometryDirectly(x_geom->Intersection(y_geom));
1821 4 : OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
1822 2 : if (x_geom_diff) delete x_geom_diff;
1823 2 : x_geom_diff = x_geom_diff_new;
1824 2 : delete y;
1825 2 : ret = pLayerResult->CreateFeature(z);
1826 2 : delete z;
1827 2 : if (ret != OGRERR_NONE) {delete x; if (x_geom_diff) delete x_geom_diff; goto done;}
1828 : }
1829 :
1830 4 : OGRFeature *z = new OGRFeature(poDefnResult);
1831 2 : z->SetFieldsFrom(x, mapInput);
1832 2 : z->SetGeometryDirectly(x_geom_diff);
1833 4 : delete x;
1834 2 : ret = pLayerResult->CreateFeature(z);
1835 2 : delete z;
1836 2 : if (ret != OGRERR_NONE) goto done;
1837 : }
1838 :
1839 : // restore filter on method layer and add features based on it
1840 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
1841 1 : pLayerMethod->ResetReading();
1842 3 : while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
1843 :
1844 1 : if (pfnProgress) {
1845 0 : double p = progress_counter/progress_max;
1846 0 : if (p > progress_ticker) {
1847 0 : if (!pfnProgress(p, "", pProgressArg)) {
1848 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
1849 0 : ret = OGRERR_FAILURE;
1850 0 : delete x;
1851 0 : goto done;
1852 : }
1853 0 : progress_ticker += 0.01;
1854 : }
1855 0 : progress_counter += 1.0;
1856 : }
1857 :
1858 : // set up the filter on input layer
1859 1 : OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
1860 1 : if (!x_geom) {
1861 0 : delete x;
1862 0 : continue;
1863 : }
1864 :
1865 1 : OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
1866 1 : ResetReading();
1867 5 : while (OGRFeature *y = GetNextFeature()) {
1868 2 : OGRGeometry *y_geom = y->GetGeometryRef();
1869 2 : if (!y_geom) {delete y; continue;}
1870 2 : OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
1871 2 : if (x_geom_diff) delete x_geom_diff;
1872 2 : x_geom_diff = x_geom_diff_new;
1873 2 : delete y;
1874 : }
1875 :
1876 2 : OGRFeature *z = new OGRFeature(poDefnResult);
1877 1 : z->SetFieldsFrom(x, mapMethod);
1878 1 : z->SetGeometryDirectly(x_geom_diff);
1879 2 : delete x;
1880 1 : ret = pLayerResult->CreateFeature(z);
1881 1 : delete z;
1882 1 : if (ret != OGRERR_NONE) goto done;
1883 : }
1884 1 : if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
1885 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
1886 0 : ret = OGRERR_FAILURE;
1887 : goto done;
1888 : }
1889 : done:
1890 : // release resources
1891 1 : SetSpatialFilter(pGeometryInputFilter);
1892 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
1893 1 : if (pGeometryMethodFilter) delete pGeometryMethodFilter;
1894 1 : if (pGeometryInputFilter) delete pGeometryInputFilter;
1895 1 : if (mapInput) VSIFree(mapInput);
1896 1 : if (mapMethod) VSIFree(mapMethod);
1897 1 : return ret;
1898 : }
1899 :
1900 : /************************************************************************/
1901 : /* OGR_L_Union() */
1902 : /************************************************************************/
1903 :
1904 : /**
1905 : * \brief Union of two layers.
1906 : *
1907 : * The result layer contains features whose geometries represent areas
1908 : * that are in either in the input layer or in the method layer. The
1909 : * features in the result layer have attributes from both input and
1910 : * method layers. For features which represent areas that are only in
1911 : * the input or in the method layer the respective attributes have
1912 : * undefined values. The schema of the result layer can be set by the
1913 : * user or, if it is empty, is initialized to contain all fields in
1914 : * the input and method layers.
1915 : *
1916 : * \note If the schema of the result is set by user and contains
1917 : * fields that have the same name as a field in input and in method
1918 : * layer, then the attribute in the result feature will get the value
1919 : * from the feature of the method layer (even if it is undefined).
1920 : *
1921 : * \note For best performance use the minimum amount of features in
1922 : * the method layer and copy it into a memory layer.
1923 : *
1924 : * \note This method relies on GEOS support. Do not use unless the
1925 : * GEOS support is compiled in.
1926 : *
1927 : * This function is the same as the C++ method OGRLayer::Union().
1928 : *
1929 : * @param pLayerInput the input layer. Should not be NULL.
1930 : *
1931 : * @param pLayerMethod the method layer. Should not be NULL.
1932 : *
1933 : * @param pLayerResult the layer where the features resulting from the
1934 : * operation are inserted. Should not be NULL. See above the note
1935 : * about the schema.
1936 : *
1937 : * @param papszOptions NULL terminated list of options (may be NULL).
1938 : *
1939 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
1940 : * reporting progress or NULL.
1941 : *
1942 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
1943 : *
1944 : * @return an error code if there was an error or the execution was
1945 : * interrupted, OGRERR_NONE otherwise.
1946 : *
1947 : * @since OGR 1.10
1948 : */
1949 :
1950 1 : OGRErr OGR_L_Union( OGRLayerH pLayerInput,
1951 : OGRLayerH pLayerMethod,
1952 : OGRLayerH pLayerResult,
1953 : char** papszOptions,
1954 : GDALProgressFunc pfnProgress,
1955 : void * pProgressArg )
1956 :
1957 : {
1958 1 : VALIDATE_POINTER1( pLayerInput, "OGR_L_Union", OGRERR_INVALID_HANDLE );
1959 1 : VALIDATE_POINTER1( pLayerMethod, "OGR_L_Union", OGRERR_INVALID_HANDLE );
1960 1 : VALIDATE_POINTER1( pLayerResult, "OGR_L_Union", OGRERR_INVALID_HANDLE );
1961 :
1962 1 : return ((OGRLayer *)pLayerInput)->Union( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
1963 : }
1964 :
1965 : /************************************************************************/
1966 : /* SymDifference() */
1967 : /************************************************************************/
1968 :
1969 : /**
1970 : * \brief Symmetrical difference of two layers.
1971 : *
1972 : * The result layer contains features whose geometries represent areas
1973 : * that are in either in the input layer or in the method layer but
1974 : * not in both. The features in the result layer have attributes from
1975 : * both input and method layers. For features which represent areas
1976 : * that are only in the input or in the method layer the respective
1977 : * attributes have undefined values. The schema of the result layer
1978 : * can be set by the user or, if it is empty, is initialized to
1979 : * contain all fields in the input and method layers.
1980 : *
1981 : * \note If the schema of the result is set by user and contains
1982 : * fields that have the same name as a field in input and in method
1983 : * layer, then the attribute in the result feature will get the value
1984 : * from the feature of the method layer (even if it is undefined).
1985 : *
1986 : * \note For best performance use the minimum amount of features in
1987 : * the method layer and copy it into a memory layer.
1988 : *
1989 : * \note This method relies on GEOS support. Do not use unless the
1990 : * GEOS support is compiled in.
1991 : *
1992 : * This method is the same as the C function OGR_L_SymDifference().
1993 : *
1994 : * @param pLayerMethod the method layer. Should not be NULL.
1995 : *
1996 : * @param pLayerResult the layer where the features resulting from the
1997 : * operation are inserted. Should not be NULL. See above the note
1998 : * about the schema.
1999 : *
2000 : * @param papszOptions NULL terminated list of options (may be NULL).
2001 : *
2002 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
2003 : * reporting progress or NULL.
2004 : *
2005 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2006 : *
2007 : * @return an error code if there was an error or the execution was
2008 : * interrupted, OGRERR_NONE otherwise.
2009 : *
2010 : * @since OGR 1.10
2011 : */
2012 :
2013 1 : OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
2014 : OGRLayer *pLayerResult,
2015 : char** papszOptions,
2016 : GDALProgressFunc pfnProgress,
2017 : void * pProgressArg )
2018 : {
2019 1 : OGRErr ret = OGRERR_NONE;
2020 1 : OGRFeatureDefn *poDefnInput = GetLayerDefn();
2021 1 : OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2022 1 : OGRFeatureDefn *poDefnResult = NULL;
2023 1 : OGRGeometry *pGeometryMethodFilter = NULL;
2024 1 : OGRGeometry *pGeometryInputFilter = NULL;
2025 1 : int *mapInput = NULL;
2026 1 : int *mapMethod = NULL;
2027 1 : double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
2028 1 : double progress_counter = 0;
2029 1 : double progress_ticker = 0;
2030 :
2031 : // check for GEOS
2032 1 : if (!OGRGeometryFactory::haveGEOS()) {
2033 0 : return OGRERR_UNSUPPORTED_OPERATION;
2034 : }
2035 :
2036 : // get resources
2037 1 : ret = clone_spatial_filter(this, &pGeometryInputFilter);
2038 1 : if (ret != OGRERR_NONE) goto done;
2039 1 : ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2040 1 : if (ret != OGRERR_NONE) goto done;
2041 1 : ret = create_field_map(poDefnInput, &mapInput);
2042 1 : if (ret != OGRERR_NONE) goto done;
2043 1 : ret = create_field_map(poDefnMethod, &mapMethod);
2044 1 : if (ret != OGRERR_NONE) goto done;
2045 1 : ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1);
2046 1 : if (ret != OGRERR_NONE) goto done;
2047 1 : poDefnResult = pLayerResult->GetLayerDefn();
2048 :
2049 : // add features based on input layer
2050 1 : ResetReading();
2051 5 : while (OGRFeature *x = GetNextFeature()) {
2052 :
2053 2 : if (pfnProgress) {
2054 0 : double p = progress_counter/progress_max;
2055 0 : if (p > progress_ticker) {
2056 0 : if (!pfnProgress(p, "", pProgressArg)) {
2057 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2058 0 : ret = OGRERR_FAILURE;
2059 0 : delete x;
2060 0 : goto done;
2061 : }
2062 0 : progress_ticker += 0.01;
2063 : }
2064 0 : progress_counter += 1.0;
2065 : }
2066 :
2067 : // set up the filter on method layer
2068 2 : OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2069 2 : if (!x_geom) {
2070 0 : delete x;
2071 0 : continue;
2072 : }
2073 :
2074 2 : OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
2075 2 : pLayerMethod->ResetReading();
2076 6 : while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2077 2 : OGRGeometry *y_geom = y->GetGeometryRef();
2078 2 : if (!y_geom) {delete y; continue;}
2079 2 : OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
2080 2 : if (geom) delete geom;
2081 2 : geom = geom_new;
2082 2 : delete y;
2083 2 : if (geom && geom->IsEmpty()) break;
2084 : }
2085 :
2086 2 : OGRFeature *z = NULL;
2087 2 : if (geom && !geom->IsEmpty()) {
2088 2 : z = new OGRFeature(poDefnResult);
2089 2 : z->SetFieldsFrom(x, mapInput);
2090 2 : z->SetGeometryDirectly(geom);
2091 : } else {
2092 0 : if (geom) delete geom;
2093 : }
2094 2 : delete x;
2095 2 : if (z) {
2096 2 : ret = pLayerResult->CreateFeature(z);
2097 2 : delete z;
2098 2 : if (ret != OGRERR_NONE) goto done;
2099 : }
2100 : }
2101 :
2102 : // restore filter on method layer and add features based on it
2103 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2104 1 : pLayerMethod->ResetReading();
2105 3 : while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
2106 :
2107 1 : if (pfnProgress) {
2108 0 : double p = progress_counter/progress_max;
2109 0 : if (p > progress_ticker) {
2110 0 : if (!pfnProgress(p, "", pProgressArg)) {
2111 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2112 0 : ret = OGRERR_FAILURE;
2113 0 : delete x;
2114 0 : goto done;
2115 : }
2116 0 : progress_ticker += 0.01;
2117 : }
2118 0 : progress_counter += 1.0;
2119 : }
2120 :
2121 : // set up the filter on input layer
2122 1 : OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
2123 1 : if (!x_geom) {
2124 0 : delete x;
2125 0 : continue;
2126 : }
2127 :
2128 1 : OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
2129 1 : ResetReading();
2130 5 : while (OGRFeature *y = GetNextFeature()) {
2131 2 : OGRGeometry *y_geom = y->GetGeometryRef();
2132 2 : if (!y_geom) {delete y; continue;}
2133 2 : OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
2134 2 : if (geom) delete geom;
2135 2 : geom = geom_new;
2136 2 : delete y;
2137 2 : if (geom->IsEmpty()) break;
2138 : }
2139 :
2140 1 : OGRFeature *z = NULL;
2141 1 : if (geom && !geom->IsEmpty()) {
2142 1 : z = new OGRFeature(poDefnResult);
2143 1 : z->SetFieldsFrom(x, mapMethod);
2144 1 : z->SetGeometryDirectly(geom);
2145 : } else {
2146 0 : if (geom) delete geom;
2147 : }
2148 1 : delete x;
2149 1 : if (z) {
2150 1 : ret = pLayerResult->CreateFeature(z);
2151 1 : delete z;
2152 1 : if (ret != OGRERR_NONE) goto done;
2153 : }
2154 : }
2155 1 : if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2156 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2157 0 : ret = OGRERR_FAILURE;
2158 : goto done;
2159 : }
2160 : done:
2161 : // release resources
2162 1 : SetSpatialFilter(pGeometryInputFilter);
2163 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2164 1 : if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2165 1 : if (pGeometryInputFilter) delete pGeometryInputFilter;
2166 1 : if (mapInput) VSIFree(mapInput);
2167 1 : if (mapMethod) VSIFree(mapMethod);
2168 1 : return ret;
2169 : }
2170 :
2171 : /************************************************************************/
2172 : /* OGR_L_SymDifference() */
2173 : /************************************************************************/
2174 :
2175 : /**
2176 : * \brief Symmetrical difference of two layers.
2177 : *
2178 : * The result layer contains features whose geometries represent areas
2179 : * that are in either in the input layer or in the method layer but
2180 : * not in both. The features in the result layer have attributes from
2181 : * both input and method layers. For features which represent areas
2182 : * that are only in the input or in the method layer the respective
2183 : * attributes have undefined values. The schema of the result layer
2184 : * can be set by the user or, if it is empty, is initialized to
2185 : * contain all fields in the input and method layers.
2186 : *
2187 : * \note If the schema of the result is set by user and contains
2188 : * fields that have the same name as a field in input and in method
2189 : * layer, then the attribute in the result feature will get the value
2190 : * from the feature of the method layer (even if it is undefined).
2191 : *
2192 : * \note For best performance use the minimum amount of features in
2193 : * the method layer and copy it into a memory layer.
2194 : *
2195 : * \note This method relies on GEOS support. Do not use unless the
2196 : * GEOS support is compiled in.
2197 : *
2198 : * This function is the same as the C++ method OGRLayer::SymDifference().
2199 : *
2200 : * @param pLayerInput the input layer. Should not be NULL.
2201 : *
2202 : * @param pLayerMethod the method layer. Should not be NULL.
2203 : *
2204 : * @param pLayerResult the layer where the features resulting from the
2205 : * operation are inserted. Should not be NULL. See above the note
2206 : * about the schema.
2207 : *
2208 : * @param papszOptions NULL terminated list of options (may be NULL).
2209 : *
2210 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
2211 : * reporting progress or NULL.
2212 : *
2213 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2214 : *
2215 : * @return an error code if there was an error or the execution was
2216 : * interrupted, OGRERR_NONE otherwise.
2217 : *
2218 : * @since OGR 1.10
2219 : */
2220 :
2221 1 : OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput,
2222 : OGRLayerH pLayerMethod,
2223 : OGRLayerH pLayerResult,
2224 : char** papszOptions,
2225 : GDALProgressFunc pfnProgress,
2226 : void * pProgressArg )
2227 :
2228 : {
2229 1 : VALIDATE_POINTER1( pLayerInput, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2230 1 : VALIDATE_POINTER1( pLayerMethod, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2231 1 : VALIDATE_POINTER1( pLayerResult, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2232 :
2233 1 : return ((OGRLayer *)pLayerInput)->SymDifference( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2234 : }
2235 :
2236 : /************************************************************************/
2237 : /* Identity() */
2238 : /************************************************************************/
2239 :
2240 : /**
2241 : * \brief Identify the features of this layer with the ones from the
2242 : * identity layer.
2243 : *
2244 : * The result layer contains features whose geometries represent areas
2245 : * that are in the input layer. The features in the result layer have
2246 : * attributes from both input and method layers. The schema of the
2247 : * result layer can be set by the user or, if it is empty, is
2248 : * initialized to contain all fields in input and method layers.
2249 : *
2250 : * \note If the schema of the result is set by user and contains
2251 : * fields that have the same name as a field in input and in method
2252 : * layer, then the attribute in the result feature will get the value
2253 : * from the feature of the method layer (even if it is undefined).
2254 : *
2255 : * \note For best performance use the minimum amount of features in
2256 : * the method layer and copy it into a memory layer.
2257 : *
2258 : * \note This method relies on GEOS support. Do not use unless the
2259 : * GEOS support is compiled in.
2260 : *
2261 : * This method is the same as the C function OGR_L_Identity().
2262 : *
2263 : * @param pLayerMethod the method layer. Should not be NULL.
2264 : *
2265 : * @param pLayerResult the layer where the features resulting from the
2266 : * operation are inserted. Should not be NULL. See above the note
2267 : * about the schema.
2268 : *
2269 : * @param papszOptions NULL terminated list of options (may be NULL).
2270 : *
2271 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
2272 : * reporting progress or NULL.
2273 : *
2274 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2275 : *
2276 : * @return an error code if there was an error or the execution was
2277 : * interrupted, OGRERR_NONE otherwise.
2278 : *
2279 : * @since OGR 1.10
2280 : */
2281 :
2282 1 : OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
2283 : OGRLayer *pLayerResult,
2284 : char** papszOptions,
2285 : GDALProgressFunc pfnProgress,
2286 : void * pProgressArg )
2287 : {
2288 1 : OGRErr ret = OGRERR_NONE;
2289 1 : OGRFeatureDefn *poDefnInput = GetLayerDefn();
2290 1 : OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2291 1 : OGRFeatureDefn *poDefnResult = NULL;
2292 1 : OGRGeometry *pGeometryMethodFilter = NULL;
2293 1 : int *mapInput = NULL;
2294 1 : int *mapMethod = NULL;
2295 1 : double progress_max = GetFeatureCount(0);
2296 1 : double progress_counter = 0;
2297 1 : double progress_ticker = 0;
2298 :
2299 : // check for GEOS
2300 1 : if (!OGRGeometryFactory::haveGEOS()) {
2301 0 : return OGRERR_UNSUPPORTED_OPERATION;
2302 : }
2303 :
2304 : // get resources
2305 1 : ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2306 1 : if (ret != OGRERR_NONE) goto done;
2307 1 : ret = create_field_map(poDefnInput, &mapInput);
2308 1 : if (ret != OGRERR_NONE) goto done;
2309 1 : ret = create_field_map(poDefnMethod, &mapMethod);
2310 1 : if (ret != OGRERR_NONE) goto done;
2311 1 : ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1);
2312 1 : if (ret != OGRERR_NONE) goto done;
2313 1 : poDefnResult = pLayerResult->GetLayerDefn();
2314 :
2315 : // split the features in input layer to the result layer
2316 1 : ResetReading();
2317 5 : while (OGRFeature *x = GetNextFeature()) {
2318 :
2319 2 : if (pfnProgress) {
2320 0 : double p = progress_counter/progress_max;
2321 0 : if (p > progress_ticker) {
2322 0 : if (!pfnProgress(p, "", pProgressArg)) {
2323 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2324 0 : ret = OGRERR_FAILURE;
2325 0 : delete x;
2326 0 : goto done;
2327 : }
2328 0 : progress_ticker += 0.01;
2329 : }
2330 0 : progress_counter += 1.0;
2331 : }
2332 :
2333 : // set up the filter on method layer
2334 2 : OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2335 2 : if (!x_geom) {
2336 0 : delete x;
2337 0 : continue;
2338 : }
2339 :
2340 2 : OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
2341 2 : pLayerMethod->ResetReading();
2342 6 : while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2343 2 : OGRGeometry *y_geom = y->GetGeometryRef();
2344 2 : if (!y_geom) {delete y; continue;}
2345 2 : OGRFeature *z = new OGRFeature(poDefnResult);
2346 2 : z->SetFieldsFrom(x, mapInput);
2347 2 : z->SetFieldsFrom(y, mapMethod);
2348 2 : z->SetGeometryDirectly(x_geom->Intersection(y_geom));
2349 4 : OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
2350 2 : if (x_geom_diff) delete x_geom_diff;
2351 2 : x_geom_diff = x_geom_diff_new;
2352 2 : delete y;
2353 2 : ret = pLayerResult->CreateFeature(z);
2354 2 : delete z;
2355 2 : if (ret != OGRERR_NONE) {delete x; delete x_geom_diff; goto done;}
2356 : }
2357 :
2358 4 : OGRFeature *z = new OGRFeature(poDefnResult);
2359 2 : z->SetFieldsFrom(x, mapInput);
2360 2 : z->SetGeometryDirectly(x_geom_diff);
2361 4 : delete x;
2362 2 : ret = pLayerResult->CreateFeature(z);
2363 2 : delete z;
2364 2 : if (ret != OGRERR_NONE) goto done;
2365 : }
2366 1 : if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2367 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2368 0 : ret = OGRERR_FAILURE;
2369 : goto done;
2370 : }
2371 : done:
2372 : // release resources
2373 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2374 1 : if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2375 1 : if (mapInput) VSIFree(mapInput);
2376 1 : if (mapMethod) VSIFree(mapMethod);
2377 1 : return ret;
2378 : }
2379 :
2380 : /************************************************************************/
2381 : /* OGR_L_Identity() */
2382 : /************************************************************************/
2383 :
2384 : /**
2385 : * \brief Identify the features of this layer with the ones from the
2386 : * identity layer.
2387 : *
2388 : * The result layer contains features whose geometries represent areas
2389 : * that are in the input layer. The features in the result layer have
2390 : * attributes from both input and method layers. The schema of the
2391 : * result layer can be set by the user or, if it is empty, is
2392 : * initialized to contain all fields in input and method layers.
2393 : *
2394 : * \note If the schema of the result is set by user and contains
2395 : * fields that have the same name as a field in input and in method
2396 : * layer, then the attribute in the result feature will get the value
2397 : * from the feature of the method layer (even if it is undefined).
2398 : *
2399 : * \note For best performance use the minimum amount of features in
2400 : * the method layer and copy it into a memory layer.
2401 : *
2402 : * \note This method relies on GEOS support. Do not use unless the
2403 : * GEOS support is compiled in.
2404 : *
2405 : * This function is the same as the C++ method OGRLayer::Identity().
2406 : *
2407 : * @param pLayerInput the input layer. Should not be NULL.
2408 : *
2409 : * @param pLayerMethod the method layer. Should not be NULL.
2410 : *
2411 : * @param pLayerResult the layer where the features resulting from the
2412 : * operation are inserted. Should not be NULL. See above the note
2413 : * about the schema.
2414 : *
2415 : * @param papszOptions NULL terminated list of options (may be NULL).
2416 : *
2417 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
2418 : * reporting progress or NULL.
2419 : *
2420 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2421 : *
2422 : * @return an error code if there was an error or the execution was
2423 : * interrupted, OGRERR_NONE otherwise.
2424 : *
2425 : * @since OGR 1.10
2426 : */
2427 :
2428 1 : OGRErr OGR_L_Identity( OGRLayerH pLayerInput,
2429 : OGRLayerH pLayerMethod,
2430 : OGRLayerH pLayerResult,
2431 : char** papszOptions,
2432 : GDALProgressFunc pfnProgress,
2433 : void * pProgressArg )
2434 :
2435 : {
2436 1 : VALIDATE_POINTER1( pLayerInput, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
2437 1 : VALIDATE_POINTER1( pLayerMethod, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
2438 1 : VALIDATE_POINTER1( pLayerResult, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
2439 :
2440 1 : return ((OGRLayer *)pLayerInput)->Identity( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2441 : }
2442 :
2443 : /************************************************************************/
2444 : /* Update() */
2445 : /************************************************************************/
2446 :
2447 : /**
2448 : * \brief Update this layer with features from the update layer.
2449 : *
2450 : * The result layer contains features whose geometries represent areas
2451 : * that are either in the input layer or in the method layer. The
2452 : * features in the result layer have areas of the features of the
2453 : * method layer or those ares of the features of the input layer that
2454 : * are not covered by the method layer. The features of the result
2455 : * layer get their attributes from the input layer. The schema of the
2456 : * result layer can be set by the user or, if it is empty, is
2457 : * initialized to contain all fields in the input layer.
2458 : *
2459 : * \note If the schema of the result is set by user and contains
2460 : * fields that have the same name as a field in the method layer, then
2461 : * the attribute in the result feature the originates from the method
2462 : * layer will get the value from the feature of the method layer.
2463 : *
2464 : * \note For best performance use the minimum amount of features in
2465 : * the method layer and copy it into a memory layer.
2466 : *
2467 : * \note This method relies on GEOS support. Do not use unless the
2468 : * GEOS support is compiled in.
2469 : *
2470 : * This method is the same as the C function OGR_L_Update().
2471 : *
2472 : * @param pLayerMethod the method layer. Should not be NULL.
2473 : *
2474 : * @param pLayerResult the layer where the features resulting from the
2475 : * operation are inserted. Should not be NULL. See above the note
2476 : * about the schema.
2477 : *
2478 : * @param papszOptions NULL terminated list of options (may be NULL).
2479 : *
2480 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
2481 : * reporting progress or NULL.
2482 : *
2483 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2484 : *
2485 : * @return an error code if there was an error or the execution was
2486 : * interrupted, OGRERR_NONE otherwise.
2487 : *
2488 : * @since OGR 1.10
2489 : */
2490 :
2491 1 : OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
2492 : OGRLayer *pLayerResult,
2493 : char** papszOptions,
2494 : GDALProgressFunc pfnProgress,
2495 : void * pProgressArg )
2496 : {
2497 1 : OGRErr ret = OGRERR_NONE;
2498 1 : OGRFeatureDefn *poDefnInput = GetLayerDefn();
2499 1 : OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2500 1 : OGRFeatureDefn *poDefnResult = NULL;
2501 1 : OGRGeometry *pGeometryMethodFilter = NULL;
2502 1 : int *mapInput = NULL;
2503 1 : int *mapMethod = NULL;
2504 1 : double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
2505 1 : double progress_counter = 0;
2506 1 : double progress_ticker = 0;
2507 :
2508 : // check for GEOS
2509 1 : if (!OGRGeometryFactory::haveGEOS()) {
2510 0 : return OGRERR_UNSUPPORTED_OPERATION;
2511 : }
2512 :
2513 : // get resources
2514 1 : ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2515 1 : if (ret != OGRERR_NONE) goto done;
2516 1 : ret = create_field_map(poDefnInput, &mapInput);
2517 1 : if (ret != OGRERR_NONE) goto done;
2518 1 : ret = create_field_map(poDefnMethod, &mapMethod);
2519 1 : if (ret != OGRERR_NONE) goto done;
2520 1 : ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 0);
2521 1 : if (ret != OGRERR_NONE) goto done;
2522 1 : poDefnResult = pLayerResult->GetLayerDefn();
2523 :
2524 : // add clipped features from the input layer
2525 1 : ResetReading();
2526 5 : while (OGRFeature *x = GetNextFeature()) {
2527 :
2528 2 : if (pfnProgress) {
2529 0 : double p = progress_counter/progress_max;
2530 0 : if (p > progress_ticker) {
2531 0 : if (!pfnProgress(p, "", pProgressArg)) {
2532 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2533 0 : ret = OGRERR_FAILURE;
2534 0 : delete x;
2535 0 : goto done;
2536 : }
2537 0 : progress_ticker += 0.01;
2538 : }
2539 0 : progress_counter += 1.0;
2540 : }
2541 :
2542 : // set up the filter on method layer
2543 2 : OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2544 2 : if (!x_geom) {
2545 0 : delete x;
2546 0 : continue;
2547 : }
2548 :
2549 2 : OGRGeometry *x_geom_diff = x_geom->clone(); //this will be the geometry of a result feature
2550 2 : pLayerMethod->ResetReading();
2551 6 : while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2552 2 : OGRGeometry *y_geom = y->GetGeometryRef();
2553 2 : if (!y_geom) {delete y; continue;}
2554 2 : OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
2555 2 : if (x_geom_diff) delete x_geom_diff;
2556 2 : x_geom_diff = x_geom_diff_new;
2557 2 : delete y;
2558 : }
2559 :
2560 4 : OGRFeature *z = new OGRFeature(poDefnResult);
2561 2 : z->SetFieldsFrom(x, mapInput);
2562 2 : z->SetGeometryDirectly(x_geom_diff);
2563 4 : delete x;
2564 2 : ret = pLayerResult->CreateFeature(z);
2565 2 : delete z;
2566 2 : if (ret != OGRERR_NONE) goto done;
2567 : }
2568 :
2569 : // restore the original filter and add features from the update layer
2570 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2571 1 : pLayerMethod->ResetReading();
2572 3 : while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2573 :
2574 1 : if (pfnProgress) {
2575 0 : double p = progress_counter/progress_max;
2576 0 : if (p > progress_ticker) {
2577 0 : if (!pfnProgress(p, "", pProgressArg)) {
2578 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2579 0 : ret = OGRERR_FAILURE;
2580 0 : delete y;
2581 0 : goto done;
2582 : }
2583 0 : progress_ticker += 0.01;
2584 : }
2585 0 : progress_counter += 1.0;
2586 : }
2587 :
2588 1 : OGRGeometry *y_geom = y->GetGeometryRef();
2589 1 : if (!y_geom) {delete y; continue;}
2590 1 : OGRFeature *z = new OGRFeature(poDefnResult);
2591 1 : if (mapMethod) z->SetFieldsFrom(y, mapMethod);
2592 1 : z->SetGeometry(y_geom);
2593 1 : delete y;
2594 1 : ret = pLayerResult->CreateFeature(z);
2595 1 : delete z;
2596 1 : if (ret != OGRERR_NONE) goto done;
2597 : }
2598 1 : if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2599 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2600 0 : ret = OGRERR_FAILURE;
2601 : goto done;
2602 : }
2603 : done:
2604 : // release resources
2605 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2606 1 : if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2607 1 : if (mapInput) VSIFree(mapInput);
2608 1 : if (mapMethod) VSIFree(mapMethod);
2609 1 : return ret;
2610 : }
2611 :
2612 : /************************************************************************/
2613 : /* OGR_L_Update() */
2614 : /************************************************************************/
2615 :
2616 : /**
2617 : * \brief Update this layer with features from the update layer.
2618 : *
2619 : * The result layer contains features whose geometries represent areas
2620 : * that are either in the input layer or in the method layer. The
2621 : * features in the result layer have areas of the features of the
2622 : * method layer or those ares of the features of the input layer that
2623 : * are not covered by the method layer. The features of the result
2624 : * layer get their attributes from the input layer. The schema of the
2625 : * result layer can be set by the user or, if it is empty, is
2626 : * initialized to contain all fields in the input layer.
2627 : *
2628 : * \note If the schema of the result is set by user and contains
2629 : * fields that have the same name as a field in the method layer, then
2630 : * the attribute in the result feature the originates from the method
2631 : * layer will get the value from the feature of the method layer.
2632 : *
2633 : * \note For best performance use the minimum amount of features in
2634 : * the method layer and copy it into a memory layer.
2635 : *
2636 : * \note This method relies on GEOS support. Do not use unless the
2637 : * GEOS support is compiled in.
2638 : *
2639 : * This function is the same as the C++ method OGRLayer::Update().
2640 : *
2641 : * @param pLayerInput the input layer. Should not be NULL.
2642 : *
2643 : * @param pLayerMethod the method layer. Should not be NULL.
2644 : *
2645 : * @param pLayerResult the layer where the features resulting from the
2646 : * operation are inserted. Should not be NULL. See above the note
2647 : * about the schema.
2648 : *
2649 : * @param papszOptions NULL terminated list of options (may be NULL).
2650 : *
2651 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
2652 : * reporting progress or NULL.
2653 : *
2654 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2655 : *
2656 : * @return an error code if there was an error or the execution was
2657 : * interrupted, OGRERR_NONE otherwise.
2658 : *
2659 : * @since OGR 1.10
2660 : */
2661 :
2662 1 : OGRErr OGR_L_Update( OGRLayerH pLayerInput,
2663 : OGRLayerH pLayerMethod,
2664 : OGRLayerH pLayerResult,
2665 : char** papszOptions,
2666 : GDALProgressFunc pfnProgress,
2667 : void * pProgressArg )
2668 :
2669 : {
2670 1 : VALIDATE_POINTER1( pLayerInput, "OGR_L_Update", OGRERR_INVALID_HANDLE );
2671 1 : VALIDATE_POINTER1( pLayerMethod, "OGR_L_Update", OGRERR_INVALID_HANDLE );
2672 1 : VALIDATE_POINTER1( pLayerResult, "OGR_L_Update", OGRERR_INVALID_HANDLE );
2673 :
2674 1 : return ((OGRLayer *)pLayerInput)->Update( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2675 : }
2676 :
2677 : /************************************************************************/
2678 : /* Clip() */
2679 : /************************************************************************/
2680 :
2681 : /**
2682 : * \brief Clip off areas that are not covered by the method layer.
2683 : *
2684 : * The result layer contains features whose geometries represent areas
2685 : * that are in the input layer and in the method layer. The features
2686 : * in the result layer have the (possibly clipped) areas of features
2687 : * in the input layer and the attributes from the same features. The
2688 : * schema of the result layer can be set by the user or, if it is
2689 : * empty, is initialized to contain all fields in the input layer.
2690 : *
2691 : * \note For best performance use the minimum amount of features in
2692 : * the method layer and copy it into a memory layer.
2693 : *
2694 : * \note This method relies on GEOS support. Do not use unless the
2695 : * GEOS support is compiled in.
2696 : *
2697 : * This method is the same as the C function OGR_L_Clip().
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 1 : OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
2719 : OGRLayer *pLayerResult,
2720 : char** papszOptions,
2721 : GDALProgressFunc pfnProgress,
2722 : void * pProgressArg )
2723 : {
2724 1 : OGRErr ret = OGRERR_NONE;
2725 1 : OGRFeatureDefn *poDefnInput = GetLayerDefn();
2726 1 : OGRFeatureDefn *poDefnResult = NULL;
2727 1 : OGRGeometry *pGeometryMethodFilter = NULL;
2728 1 : int *mapInput = NULL;
2729 1 : double progress_max = GetFeatureCount(0);
2730 1 : double progress_counter = 0;
2731 1 : double progress_ticker = 0;
2732 :
2733 : // check for GEOS
2734 1 : if (!OGRGeometryFactory::haveGEOS()) {
2735 0 : return OGRERR_UNSUPPORTED_OPERATION;
2736 : }
2737 :
2738 1 : ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2739 1 : if (ret != OGRERR_NONE) goto done;
2740 1 : ret = create_field_map(poDefnInput, &mapInput);
2741 1 : if (ret != OGRERR_NONE) goto done;
2742 1 : ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0);
2743 1 : if (ret != OGRERR_NONE) goto done;
2744 :
2745 1 : poDefnResult = pLayerResult->GetLayerDefn();
2746 1 : ResetReading();
2747 5 : while (OGRFeature *x = GetNextFeature()) {
2748 :
2749 2 : if (pfnProgress) {
2750 0 : double p = progress_counter/progress_max;
2751 0 : if (p > progress_ticker) {
2752 0 : if (pfnProgress(p, "", pProgressArg)) {
2753 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2754 0 : ret = OGRERR_FAILURE;
2755 0 : delete x;
2756 0 : goto done;
2757 : }
2758 0 : progress_ticker += 0.01;
2759 : }
2760 0 : progress_counter += 1.0;
2761 : }
2762 :
2763 : // set up the filter on method layer
2764 2 : OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2765 2 : if (!x_geom) {
2766 0 : delete x;
2767 0 : continue;
2768 : }
2769 :
2770 2 : OGRGeometry *geom = NULL; // this will be the geometry of the result feature
2771 2 : pLayerMethod->ResetReading();
2772 : // incrementally add area from y to geom
2773 6 : while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2774 2 : OGRGeometry *y_geom = y->GetGeometryRef();
2775 2 : if (!y_geom) {delete y; continue;}
2776 2 : if (!geom) {
2777 2 : geom = y_geom->clone();
2778 : } else {
2779 0 : OGRGeometry *geom_new = geom->Union(y_geom);
2780 0 : delete geom;
2781 0 : geom = geom_new;
2782 : }
2783 2 : delete y;
2784 : }
2785 :
2786 : // possibly add a new feature with area x intersection sum of y
2787 2 : OGRFeature *z = NULL;
2788 2 : if (geom) {
2789 2 : z = new OGRFeature(poDefnResult);
2790 2 : z->SetFieldsFrom(x, mapInput);
2791 2 : z->SetGeometryDirectly(x_geom->Intersection(geom));
2792 4 : delete geom;
2793 : }
2794 2 : delete x;
2795 2 : if (z) {
2796 2 : if (!z->GetGeometryRef()->IsEmpty())
2797 2 : ret = pLayerResult->CreateFeature(z);
2798 2 : delete z;
2799 2 : if (ret != OGRERR_NONE) goto done;
2800 : }
2801 : }
2802 1 : if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2803 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2804 0 : ret = OGRERR_FAILURE;
2805 : goto done;
2806 : }
2807 : done:
2808 : // release resources
2809 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2810 1 : if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2811 1 : if (mapInput) VSIFree(mapInput);
2812 1 : return ret;
2813 : }
2814 :
2815 : /************************************************************************/
2816 : /* OGR_L_Clip() */
2817 : /************************************************************************/
2818 :
2819 : /**
2820 : * \brief Clip off areas that are not covered by the method layer.
2821 : *
2822 : * The result layer contains features whose geometries represent areas
2823 : * that are in the input layer and in the method layer. The features
2824 : * in the result layer have the (possibly clipped) areas of features
2825 : * in the input layer and the attributes from the same features. The
2826 : * schema of the result layer can be set by the user or, if it is
2827 : * empty, is initialized to contain all fields in the input layer.
2828 : *
2829 : * \note For best performance use the minimum amount of features in
2830 : * the method layer and copy it into a memory layer.
2831 : *
2832 : * \note This method relies on GEOS support. Do not use unless the
2833 : * GEOS support is compiled in.
2834 : *
2835 : * This function is the same as the C++ method OGRLayer::Clip().
2836 : *
2837 : * @param pLayerInput the input layer. Should not be NULL.
2838 : *
2839 : * @param pLayerMethod the method layer. Should not be NULL.
2840 : *
2841 : * @param pLayerResult the layer where the features resulting from the
2842 : * operation are inserted. Should not be NULL. See above the note
2843 : * about the schema.
2844 : *
2845 : * @param papszOptions NULL terminated list of options (may be NULL).
2846 : *
2847 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
2848 : * reporting progress or NULL.
2849 : *
2850 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2851 : *
2852 : * @return an error code if there was an error or the execution was
2853 : * interrupted, OGRERR_NONE otherwise.
2854 : *
2855 : * @since OGR 1.10
2856 : */
2857 :
2858 1 : OGRErr OGR_L_Clip( OGRLayerH pLayerInput,
2859 : OGRLayerH pLayerMethod,
2860 : OGRLayerH pLayerResult,
2861 : char** papszOptions,
2862 : GDALProgressFunc pfnProgress,
2863 : void * pProgressArg )
2864 :
2865 : {
2866 1 : VALIDATE_POINTER1( pLayerInput, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
2867 1 : VALIDATE_POINTER1( pLayerMethod, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
2868 1 : VALIDATE_POINTER1( pLayerResult, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
2869 :
2870 1 : return ((OGRLayer *)pLayerInput)->Clip( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2871 : }
2872 :
2873 : /************************************************************************/
2874 : /* Erase() */
2875 : /************************************************************************/
2876 :
2877 : /**
2878 : * \brief Remove areas that are covered by the method layer.
2879 : *
2880 : * The result layer contains features whose geometries represent areas
2881 : * that are in the input layer but not in the method layer. The
2882 : * features in the result layer have attributes from the input
2883 : * layer. The schema of the result layer can be set by the user or, if
2884 : * it is empty, is initialized to contain all fields in the input
2885 : * layer.
2886 : *
2887 : * \note For best performance use the minimum amount of features in
2888 : * the method layer and copy it into a memory layer.
2889 : *
2890 : * \note This method relies on GEOS support. Do not use unless the
2891 : * GEOS support is compiled in.
2892 : *
2893 : * This method is the same as the C function OGR_L_Erase().
2894 : *
2895 : * @param pLayerMethod the method layer. Should not be NULL.
2896 : *
2897 : * @param pLayerResult the layer where the features resulting from the
2898 : * operation are inserted. Should not be NULL. See above the note
2899 : * about the schema.
2900 : *
2901 : * @param papszOptions NULL terminated list of options (may be NULL).
2902 : *
2903 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
2904 : * reporting progress or NULL.
2905 : *
2906 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2907 : *
2908 : * @return an error code if there was an error or the execution was
2909 : * interrupted, OGRERR_NONE otherwise.
2910 : *
2911 : * @since OGR 1.10
2912 : */
2913 :
2914 1 : OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
2915 : OGRLayer *pLayerResult,
2916 : char** papszOptions,
2917 : GDALProgressFunc pfnProgress,
2918 : void * pProgressArg )
2919 : {
2920 1 : OGRErr ret = OGRERR_NONE;
2921 1 : OGRFeatureDefn *poDefnInput = GetLayerDefn();
2922 1 : OGRFeatureDefn *poDefnResult = NULL;
2923 1 : OGRGeometry *pGeometryMethodFilter = NULL;
2924 1 : int *mapInput = NULL;
2925 1 : double progress_max = GetFeatureCount(0);
2926 1 : double progress_counter = 0;
2927 1 : double progress_ticker = 0;
2928 :
2929 : // check for GEOS
2930 1 : if (!OGRGeometryFactory::haveGEOS()) {
2931 0 : return OGRERR_UNSUPPORTED_OPERATION;
2932 : }
2933 :
2934 : // get resources
2935 1 : ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2936 1 : if (ret != OGRERR_NONE) goto done;
2937 1 : ret = create_field_map(poDefnInput, &mapInput);
2938 1 : if (ret != OGRERR_NONE) goto done;
2939 1 : ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0);
2940 1 : if (ret != OGRERR_NONE) goto done;
2941 1 : poDefnResult = pLayerResult->GetLayerDefn();
2942 :
2943 1 : ResetReading();
2944 5 : while (OGRFeature *x = GetNextFeature()) {
2945 :
2946 2 : if (pfnProgress) {
2947 0 : double p = progress_counter/progress_max;
2948 0 : if (p > progress_ticker) {
2949 0 : if (!pfnProgress(p, "", pProgressArg)) {
2950 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2951 0 : ret = OGRERR_FAILURE;
2952 0 : delete x;
2953 0 : goto done;
2954 : }
2955 0 : progress_ticker += 0.01;
2956 : }
2957 0 : progress_counter += 1.0;
2958 : }
2959 :
2960 : // set up the filter on the method layer
2961 2 : OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2962 2 : if (!x_geom) {
2963 0 : delete x;
2964 0 : continue;
2965 : }
2966 :
2967 2 : OGRGeometry *geom = NULL; // this will be the geometry of the result feature
2968 2 : pLayerMethod->ResetReading();
2969 : // incrementally add area from y to geom
2970 6 : while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2971 2 : OGRGeometry *y_geom = y->GetGeometryRef();
2972 2 : if (!y_geom) {delete y; continue;}
2973 2 : if (!geom) {
2974 2 : geom = y_geom->clone();
2975 : } else {
2976 0 : OGRGeometry *geom_new = geom->Union(y_geom);
2977 0 : delete geom;
2978 0 : geom = geom_new;
2979 : }
2980 2 : delete y;
2981 : }
2982 :
2983 : // possibly add a new feature with area x minus sum of y
2984 2 : OGRFeature *z = NULL;
2985 2 : if (geom) {
2986 2 : z = new OGRFeature(poDefnResult);
2987 2 : z->SetFieldsFrom(x, mapInput);
2988 2 : z->SetGeometryDirectly(x_geom->Difference(geom));
2989 4 : delete geom;
2990 : }
2991 2 : delete x;
2992 2 : if (z) {
2993 2 : if (!z->GetGeometryRef()->IsEmpty())
2994 2 : ret = pLayerResult->CreateFeature(z);
2995 2 : delete z;
2996 2 : if (ret != OGRERR_NONE) goto done;
2997 : }
2998 : }
2999 1 : if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3000 0 : CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3001 0 : ret = OGRERR_FAILURE;
3002 : goto done;
3003 : }
3004 : done:
3005 : // release resources
3006 1 : pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3007 1 : if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3008 1 : if (mapInput) VSIFree(mapInput);
3009 1 : return ret;
3010 : }
3011 :
3012 : /************************************************************************/
3013 : /* OGR_L_Erase() */
3014 : /************************************************************************/
3015 :
3016 : /**
3017 : * \brief Remove areas that are covered by the method layer.
3018 : *
3019 : * The result layer contains features whose geometries represent areas
3020 : * that are in the input layer but not in the method layer. The
3021 : * features in the result layer have attributes from the input
3022 : * layer. The schema of the result layer can be set by the user or, if
3023 : * it is empty, is initialized to contain all fields in the input
3024 : * layer.
3025 : *
3026 : * \note For best performance use the minimum amount of features in
3027 : * the method layer and copy it into a memory layer.
3028 : *
3029 : * \note This method relies on GEOS support. Do not use unless the
3030 : * GEOS support is compiled in.
3031 : *
3032 : * This function is the same as the C++ method OGRLayer::Erase().
3033 : *
3034 : * @param pLayerInput the input layer. Should not be NULL.
3035 : *
3036 : * @param pLayerMethod the method layer. Should not be NULL.
3037 : *
3038 : * @param pLayerResult the layer where the features resulting from the
3039 : * operation are inserted. Should not be NULL. See above the note
3040 : * about the schema.
3041 : *
3042 : * @param papszOptions NULL terminated list of options (may be NULL).
3043 : *
3044 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
3045 : * reporting progress or NULL.
3046 : *
3047 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3048 : *
3049 : * @return an error code if there was an error or the execution was
3050 : * interrupted, OGRERR_NONE otherwise.
3051 : *
3052 : * @since OGR 1.10
3053 : */
3054 :
3055 1 : OGRErr OGR_L_Erase( OGRLayerH pLayerInput,
3056 : OGRLayerH pLayerMethod,
3057 : OGRLayerH pLayerResult,
3058 : char** papszOptions,
3059 : GDALProgressFunc pfnProgress,
3060 : void * pProgressArg )
3061 :
3062 : {
3063 1 : VALIDATE_POINTER1( pLayerInput, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3064 1 : VALIDATE_POINTER1( pLayerMethod, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3065 1 : VALIDATE_POINTER1( pLayerResult, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3066 :
3067 1 : return ((OGRLayer *)pLayerInput)->Erase( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3068 : }
|