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