Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRWarpedLayer class
5 : * Author: Even Rouault, even dot rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012-2014, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef DOXYGEN_SKIP
14 :
15 : #include <cmath>
16 :
17 : #include "ogrwarpedlayer.h"
18 :
19 : /************************************************************************/
20 : /* OGRWarpedLayer() */
21 : /************************************************************************/
22 :
23 28 : OGRWarpedLayer::OGRWarpedLayer(OGRLayer *poDecoratedLayer, int iGeomField,
24 : int bTakeOwnership,
25 : OGRCoordinateTransformation *poCT,
26 28 : OGRCoordinateTransformation *poReversedCT)
27 : : OGRLayerDecorator(poDecoratedLayer, bTakeOwnership),
28 : m_poFeatureDefn(nullptr), m_iGeomField(iGeomField), m_poCT(poCT),
29 : m_poReversedCT(poReversedCT),
30 28 : m_poSRS(const_cast<OGRSpatialReference *>(m_poCT->GetTargetCS()))
31 : {
32 28 : CPLAssert(poCT != nullptr);
33 28 : SetDescription(poDecoratedLayer->GetDescription());
34 :
35 28 : if (m_poSRS != nullptr)
36 : {
37 28 : m_poSRS->Reference();
38 : }
39 28 : }
40 :
41 : /************************************************************************/
42 : /* ~OGRWarpedLayer() */
43 : /************************************************************************/
44 :
45 56 : OGRWarpedLayer::~OGRWarpedLayer()
46 : {
47 28 : if (m_poFeatureDefn != nullptr)
48 26 : m_poFeatureDefn->Release();
49 28 : if (m_poSRS != nullptr)
50 28 : m_poSRS->Release();
51 28 : delete m_poCT;
52 28 : delete m_poReversedCT;
53 56 : }
54 :
55 : /************************************************************************/
56 : /* ISetSpatialFilter() */
57 : /************************************************************************/
58 :
59 216 : OGRErr OGRWarpedLayer::ISetSpatialFilter(int iGeomField,
60 : const OGRGeometry *poGeom)
61 : {
62 :
63 216 : m_iGeomFieldFilter = iGeomField;
64 216 : if (InstallFilter(poGeom))
65 99 : ResetReading();
66 :
67 216 : if (m_iGeomFieldFilter == m_iGeomField)
68 : {
69 63 : if (poGeom == nullptr || m_poReversedCT == nullptr)
70 : {
71 19 : return m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter,
72 19 : nullptr);
73 : }
74 : else
75 : {
76 44 : OGREnvelope sEnvelope;
77 44 : poGeom->getEnvelope(&sEnvelope);
78 54 : if (std::isinf(sEnvelope.MinX) && std::isinf(sEnvelope.MinY) &&
79 54 : std::isinf(sEnvelope.MaxX) && std::isinf(sEnvelope.MaxY))
80 : {
81 5 : return m_poDecoratedLayer->SetSpatialFilterRect(
82 : m_iGeomFieldFilter, sEnvelope.MinX, sEnvelope.MinY,
83 5 : sEnvelope.MaxX, sEnvelope.MaxY);
84 : }
85 39 : else if (ReprojectEnvelope(&sEnvelope, m_poReversedCT))
86 : {
87 34 : return m_poDecoratedLayer->SetSpatialFilterRect(
88 : m_iGeomFieldFilter, sEnvelope.MinX, sEnvelope.MinY,
89 34 : sEnvelope.MaxX, sEnvelope.MaxY);
90 : }
91 : else
92 : {
93 5 : return m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter,
94 5 : nullptr);
95 : }
96 : }
97 : }
98 : else
99 : {
100 153 : return m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter, poGeom);
101 : }
102 : }
103 :
104 : /************************************************************************/
105 : /* TranslateFeature() */
106 : /************************************************************************/
107 :
108 8 : void OGRWarpedLayer::TranslateFeature(
109 : std::unique_ptr<OGRFeature> poSrcFeature,
110 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures)
111 : {
112 8 : apoOutFeatures.push_back(
113 16 : SrcFeatureToWarpedFeature(std::move(poSrcFeature)));
114 8 : }
115 :
116 : /************************************************************************/
117 : /* SrcFeatureToWarpedFeature() */
118 : /************************************************************************/
119 :
120 : std::unique_ptr<OGRFeature>
121 457 : OGRWarpedLayer::SrcFeatureToWarpedFeature(std::unique_ptr<OGRFeature> poFeature)
122 : {
123 : // This is safe to do here as they have matching attribute and geometry
124 : // fields
125 457 : poFeature->SetFDefnUnsafe(GetLayerDefn());
126 :
127 457 : OGRGeometry *poGeom = poFeature->GetGeomFieldRef(m_iGeomField);
128 457 : if (poGeom && poGeom->transform(m_poCT) != OGRERR_NONE)
129 : {
130 2 : delete poFeature->StealGeometry(m_iGeomField);
131 : }
132 :
133 457 : return poFeature;
134 : }
135 :
136 : /************************************************************************/
137 : /* WarpedFeatureToSrcFeature() */
138 : /************************************************************************/
139 :
140 : std::unique_ptr<OGRFeature>
141 9 : OGRWarpedLayer::WarpedFeatureToSrcFeature(std::unique_ptr<OGRFeature> poFeature)
142 : {
143 : // This is safe to do here as they have matching attribute and geometry
144 : // fields
145 9 : poFeature->SetFDefnUnsafe(m_poDecoratedLayer->GetLayerDefn());
146 :
147 9 : OGRGeometry *poGeom = poFeature->GetGeomFieldRef(m_iGeomField);
148 16 : if (poGeom &&
149 7 : (!m_poReversedCT || poGeom->transform(m_poReversedCT) != OGRERR_NONE))
150 : {
151 2 : return nullptr;
152 : }
153 :
154 7 : return poFeature;
155 : }
156 :
157 : /************************************************************************/
158 : /* GetNextFeature() */
159 : /************************************************************************/
160 :
161 538 : OGRFeature *OGRWarpedLayer::GetNextFeature()
162 : {
163 : while (true)
164 : {
165 : auto poFeature =
166 538 : std::unique_ptr<OGRFeature>(m_poDecoratedLayer->GetNextFeature());
167 538 : if (!poFeature)
168 95 : return nullptr;
169 :
170 443 : auto poFeatureNew = SrcFeatureToWarpedFeature(std::move(poFeature));
171 443 : const OGRGeometry *poGeom = poFeatureNew->GetGeomFieldRef(m_iGeomField);
172 443 : if (m_poFilterGeom != nullptr && !FilterGeometry(poGeom))
173 : {
174 1 : continue;
175 : }
176 :
177 442 : return poFeatureNew.release();
178 1 : }
179 : }
180 :
181 : /************************************************************************/
182 : /* GetFeature() */
183 : /************************************************************************/
184 :
185 9 : OGRFeature *OGRWarpedLayer::GetFeature(GIntBig nFID)
186 : {
187 : auto poFeature =
188 18 : std::unique_ptr<OGRFeature>(m_poDecoratedLayer->GetFeature(nFID));
189 9 : if (poFeature)
190 : {
191 6 : poFeature = SrcFeatureToWarpedFeature(std::move(poFeature));
192 : }
193 18 : return poFeature.release();
194 : }
195 :
196 : /************************************************************************/
197 : /* ISetFeature() */
198 : /************************************************************************/
199 :
200 5 : OGRErr OGRWarpedLayer::ISetFeature(OGRFeature *poFeature)
201 : {
202 : auto poFeatureNew = WarpedFeatureToSrcFeature(
203 10 : std::unique_ptr<OGRFeature>(poFeature->Clone()));
204 5 : if (!poFeatureNew)
205 1 : return OGRERR_FAILURE;
206 :
207 4 : return m_poDecoratedLayer->SetFeature(poFeatureNew.get());
208 : }
209 :
210 : /************************************************************************/
211 : /* ICreateFeature() */
212 : /************************************************************************/
213 :
214 4 : OGRErr OGRWarpedLayer::ICreateFeature(OGRFeature *poFeature)
215 : {
216 : auto poFeatureNew = WarpedFeatureToSrcFeature(
217 8 : std::unique_ptr<OGRFeature>(poFeature->Clone()));
218 4 : if (!poFeatureNew)
219 1 : return OGRERR_FAILURE;
220 :
221 3 : return m_poDecoratedLayer->CreateFeature(poFeatureNew.get());
222 : }
223 :
224 : /************************************************************************/
225 : /* IUpsertFeature() */
226 : /************************************************************************/
227 :
228 0 : OGRErr OGRWarpedLayer::IUpsertFeature(OGRFeature *poFeature)
229 : {
230 : auto poFeatureNew = WarpedFeatureToSrcFeature(
231 0 : std::unique_ptr<OGRFeature>(poFeature->Clone()));
232 0 : if (poFeatureNew == nullptr)
233 0 : return OGRERR_FAILURE;
234 :
235 0 : return m_poDecoratedLayer->UpsertFeature(poFeatureNew.get());
236 : }
237 :
238 : /************************************************************************/
239 : /* IUpdateFeature() */
240 : /************************************************************************/
241 :
242 0 : OGRErr OGRWarpedLayer::IUpdateFeature(OGRFeature *poFeature,
243 : int nUpdatedFieldsCount,
244 : const int *panUpdatedFieldsIdx,
245 : int nUpdatedGeomFieldsCount,
246 : const int *panUpdatedGeomFieldsIdx,
247 : bool bUpdateStyleString)
248 : {
249 : auto poFeatureNew = WarpedFeatureToSrcFeature(
250 0 : std::unique_ptr<OGRFeature>(poFeature->Clone()));
251 0 : if (!poFeatureNew)
252 0 : return OGRERR_FAILURE;
253 :
254 0 : return m_poDecoratedLayer->UpdateFeature(
255 : poFeatureNew.get(), nUpdatedFieldsCount, panUpdatedFieldsIdx,
256 0 : nUpdatedGeomFieldsCount, panUpdatedGeomFieldsIdx, bUpdateStyleString);
257 : }
258 :
259 : /************************************************************************/
260 : /* GetLayerDefn() */
261 : /************************************************************************/
262 :
263 1150 : OGRFeatureDefn *OGRWarpedLayer::GetLayerDefn()
264 : {
265 1150 : if (m_poFeatureDefn != nullptr)
266 1124 : return m_poFeatureDefn;
267 :
268 26 : m_poFeatureDefn = m_poDecoratedLayer->GetLayerDefn()->Clone();
269 26 : m_poFeatureDefn->Reference();
270 26 : if (m_poFeatureDefn->GetGeomFieldCount() > 0)
271 26 : m_poFeatureDefn->GetGeomFieldDefn(m_iGeomField)->SetSpatialRef(m_poSRS);
272 :
273 26 : return m_poFeatureDefn;
274 : }
275 :
276 : /************************************************************************/
277 : /* GetSpatialRef() */
278 : /************************************************************************/
279 :
280 11 : OGRSpatialReference *OGRWarpedLayer::GetSpatialRef()
281 : {
282 11 : if (m_iGeomField == 0)
283 11 : return m_poSRS;
284 : else
285 0 : return OGRLayer::GetSpatialRef();
286 : }
287 :
288 : /************************************************************************/
289 : /* GetFeatureCount() */
290 : /************************************************************************/
291 :
292 45 : GIntBig OGRWarpedLayer::GetFeatureCount(int bForce)
293 : {
294 45 : if (m_poFilterGeom == nullptr)
295 25 : return m_poDecoratedLayer->GetFeatureCount(bForce);
296 :
297 20 : return OGRLayer::GetFeatureCount(bForce);
298 : }
299 :
300 : /************************************************************************/
301 : /* IGetExtent() */
302 : /************************************************************************/
303 :
304 15 : OGRErr OGRWarpedLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
305 : bool bForce)
306 : {
307 15 : if (iGeomField == m_iGeomField)
308 : {
309 11 : if (sStaticEnvelope.IsInit())
310 : {
311 1 : *psExtent = sStaticEnvelope;
312 1 : return OGRERR_NONE;
313 : }
314 :
315 10 : OGREnvelope sExtent;
316 : OGRErr eErr =
317 10 : m_poDecoratedLayer->GetExtent(m_iGeomField, &sExtent, bForce);
318 10 : if (eErr != OGRERR_NONE)
319 0 : return eErr;
320 :
321 10 : if (ReprojectEnvelope(&sExtent, m_poCT))
322 : {
323 10 : *psExtent = sExtent;
324 10 : return OGRERR_NONE;
325 : }
326 : else
327 0 : return OGRERR_FAILURE;
328 : }
329 : else
330 4 : return m_poDecoratedLayer->GetExtent(iGeomField, psExtent, bForce);
331 : }
332 :
333 : /************************************************************************/
334 : /* TransformAndUpdateBBAndReturnX() */
335 : /************************************************************************/
336 :
337 0 : static double TransformAndUpdateBBAndReturnX(OGRCoordinateTransformation *poCT,
338 : double dfX, double dfY,
339 : double &dfMinX, double &dfMinY,
340 : double &dfMaxX, double &dfMaxY)
341 : {
342 0 : int bSuccess = FALSE;
343 0 : poCT->Transform(1, &dfX, &dfY, nullptr, nullptr, &bSuccess);
344 0 : if (bSuccess)
345 : {
346 0 : if (dfX < dfMinX)
347 0 : dfMinX = dfX;
348 0 : if (dfY < dfMinY)
349 0 : dfMinY = dfY;
350 0 : if (dfX > dfMaxX)
351 0 : dfMaxX = dfX;
352 0 : if (dfY > dfMaxY)
353 0 : dfMaxY = dfY;
354 0 : return dfX;
355 : }
356 :
357 0 : return 0.0;
358 : }
359 :
360 : /************************************************************************/
361 : /* FindXDiscontinuity() */
362 : /************************************************************************/
363 :
364 0 : static void FindXDiscontinuity(OGRCoordinateTransformation *poCT, double dfX1,
365 : double dfX2, double dfY, double &dfMinX,
366 : double &dfMinY, double &dfMaxX, double &dfMaxY,
367 : int nRecLevel = 0)
368 : {
369 0 : double dfXMid = (dfX1 + dfX2) / 2;
370 :
371 0 : double dfWrkX1 = TransformAndUpdateBBAndReturnX(poCT, dfX1, dfY, dfMinX,
372 : dfMinY, dfMaxX, dfMaxY);
373 0 : double dfWrkXMid = TransformAndUpdateBBAndReturnX(poCT, dfXMid, dfY, dfMinX,
374 : dfMinY, dfMaxX, dfMaxY);
375 0 : double dfWrkX2 = TransformAndUpdateBBAndReturnX(poCT, dfX2, dfY, dfMinX,
376 : dfMinY, dfMaxX, dfMaxY);
377 :
378 0 : double dfDX1 = dfWrkXMid - dfWrkX1;
379 0 : double dfDX2 = dfWrkX2 - dfWrkXMid;
380 :
381 0 : if (dfDX1 * dfDX2 < 0 && nRecLevel < 30)
382 : {
383 0 : FindXDiscontinuity(poCT, dfX1, dfXMid, dfY, dfMinX, dfMinY, dfMaxX,
384 : dfMaxY, nRecLevel + 1);
385 0 : FindXDiscontinuity(poCT, dfXMid, dfX2, dfY, dfMinX, dfMinY, dfMaxX,
386 : dfMaxY, nRecLevel + 1);
387 : }
388 0 : }
389 :
390 : /************************************************************************/
391 : /* ReprojectEnvelope() */
392 : /************************************************************************/
393 :
394 49 : int OGRWarpedLayer::ReprojectEnvelope(OGREnvelope *psEnvelope,
395 : OGRCoordinateTransformation *poCT)
396 : {
397 49 : const int NSTEP = 20;
398 49 : double dfXStep = (psEnvelope->MaxX - psEnvelope->MinX) / NSTEP;
399 49 : double dfYStep = (psEnvelope->MaxY - psEnvelope->MinY) / NSTEP;
400 :
401 : double *padfX = static_cast<double *>(
402 49 : VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double)));
403 : double *padfY = static_cast<double *>(
404 49 : VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double)));
405 : int *pabSuccess = static_cast<int *>(
406 49 : VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(int)));
407 49 : if (padfX == nullptr || padfY == nullptr || pabSuccess == nullptr)
408 : {
409 0 : VSIFree(padfX);
410 0 : VSIFree(padfY);
411 0 : VSIFree(pabSuccess);
412 0 : return FALSE;
413 : }
414 :
415 1078 : for (int j = 0; j <= NSTEP; j++)
416 : {
417 22638 : for (int i = 0; i <= NSTEP; i++)
418 : {
419 21609 : padfX[j * (NSTEP + 1) + i] = psEnvelope->MinX + i * dfXStep;
420 21609 : padfY[j * (NSTEP + 1) + i] = psEnvelope->MinY + j * dfYStep;
421 : }
422 : }
423 :
424 49 : int bRet = FALSE;
425 :
426 98 : if (poCT->Transform((NSTEP + 1) * (NSTEP + 1), padfX, padfY, nullptr,
427 49 : nullptr, pabSuccess))
428 : {
429 44 : double dfMinX = 0.0;
430 44 : double dfMinY = 0.0;
431 44 : double dfMaxX = 0.0;
432 44 : double dfMaxY = 0.0;
433 44 : int bSet = FALSE;
434 968 : for (int j = 0; j <= NSTEP; j++)
435 : {
436 924 : double dfXOld = 0.0;
437 924 : double dfDXOld = 0.0;
438 924 : int iOld = -1;
439 924 : int iOldOld = -1;
440 20328 : for (int i = 0; i <= NSTEP; i++)
441 : {
442 19404 : if (pabSuccess[j * (NSTEP + 1) + i])
443 : {
444 19404 : double dfX = padfX[j * (NSTEP + 1) + i];
445 19404 : double dfY = padfY[j * (NSTEP + 1) + i];
446 :
447 19404 : if (!bSet)
448 : {
449 44 : dfMinX = dfX;
450 44 : dfMaxX = dfX;
451 44 : dfMinY = dfY;
452 44 : dfMaxY = dfY;
453 44 : bSet = TRUE;
454 : }
455 : else
456 : {
457 19360 : if (dfX < dfMinX)
458 124 : dfMinX = dfX;
459 19360 : if (dfY < dfMinY)
460 150 : dfMinY = dfY;
461 19360 : if (dfX > dfMaxX)
462 965 : dfMaxX = dfX;
463 19360 : if (dfY > dfMaxY)
464 3471 : dfMaxY = dfY;
465 : }
466 :
467 19404 : if (iOld >= 0)
468 : {
469 18480 : double dfDXNew = dfX - dfXOld;
470 18480 : if (iOldOld >= 0 && dfDXNew * dfDXOld < 0)
471 : {
472 0 : FindXDiscontinuity(
473 0 : poCT, psEnvelope->MinX + iOldOld * dfXStep,
474 0 : psEnvelope->MinX + i * dfXStep,
475 0 : psEnvelope->MinY + j * dfYStep, dfMinX, dfMinY,
476 : dfMaxX, dfMaxY);
477 : }
478 18480 : dfDXOld = dfDXNew;
479 : }
480 :
481 19404 : dfXOld = dfX;
482 19404 : iOldOld = iOld;
483 19404 : iOld = i;
484 : }
485 : }
486 : }
487 44 : if (bSet)
488 : {
489 44 : psEnvelope->MinX = dfMinX;
490 44 : psEnvelope->MinY = dfMinY;
491 44 : psEnvelope->MaxX = dfMaxX;
492 44 : psEnvelope->MaxY = dfMaxY;
493 44 : bRet = TRUE;
494 : }
495 : }
496 :
497 49 : VSIFree(padfX);
498 49 : VSIFree(padfY);
499 49 : VSIFree(pabSuccess);
500 :
501 49 : return bRet;
502 : }
503 :
504 : /************************************************************************/
505 : /* TestCapability() */
506 : /************************************************************************/
507 :
508 173 : int OGRWarpedLayer::TestCapability(const char *pszCapability)
509 : {
510 173 : if (EQUAL(pszCapability, OLCFastGetExtent) && sStaticEnvelope.IsInit())
511 0 : return TRUE;
512 :
513 173 : int bVal = m_poDecoratedLayer->TestCapability(pszCapability);
514 :
515 173 : if (EQUAL(pszCapability, OLCFastGetArrowStream))
516 3 : return false;
517 :
518 170 : if (EQUAL(pszCapability, OLCFastSpatialFilter) ||
519 170 : EQUAL(pszCapability, OLCRandomWrite) ||
520 169 : EQUAL(pszCapability, OLCSequentialWrite))
521 : {
522 2 : if (bVal)
523 0 : bVal = m_poReversedCT != nullptr;
524 : }
525 168 : else if (EQUAL(pszCapability, OLCFastFeatureCount))
526 : {
527 0 : if (bVal)
528 0 : bVal = m_poFilterGeom == nullptr;
529 : }
530 :
531 170 : return bVal;
532 : }
533 :
534 : /************************************************************************/
535 : /* SetExtent() */
536 : /************************************************************************/
537 :
538 1 : void OGRWarpedLayer::SetExtent(double dfXMin, double dfYMin, double dfXMax,
539 : double dfYMax)
540 : {
541 1 : sStaticEnvelope.MinX = dfXMin;
542 1 : sStaticEnvelope.MinY = dfYMin;
543 1 : sStaticEnvelope.MaxX = dfXMax;
544 1 : sStaticEnvelope.MaxY = dfYMax;
545 1 : }
546 :
547 : /************************************************************************/
548 : /* GetArrowStream() */
549 : /************************************************************************/
550 :
551 7 : bool OGRWarpedLayer::GetArrowStream(struct ArrowArrayStream *out_stream,
552 : CSLConstList papszOptions)
553 : {
554 7 : return OGRLayer::GetArrowStream(out_stream, papszOptions);
555 : }
556 :
557 : #endif /* #ifndef DOXYGEN_SKIP */
|