Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: Algorithm to apply a transformer to geolocation style bands.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012, Frank Warmerdam
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "cpl_port.h"
14 : #include "gdal_alg.h"
15 :
16 : #include <cstring>
17 :
18 : #include "cpl_conv.h"
19 : #include "cpl_error.h"
20 : #include "cpl_progress.h"
21 : #include "gdal.h"
22 : #include "gdal_alg_priv.h"
23 : #include "gdal_priv.h"
24 :
25 : /************************************************************************/
26 : /* GDALTransformGeolocations() */
27 : /************************************************************************/
28 :
29 : /**
30 : * Transform locations held in bands.
31 : *
32 : * The X/Y and possibly Z values in the identified bands are transformed
33 : * using a spatial transformer. The changed values are written back to the
34 : * source bands so they need to be updateable.
35 : *
36 : * @param hXBand the band containing the X locations (usually long/easting).
37 : * @param hYBand the band containing the Y locations (usually lat/northing).
38 : * @param hZBand the band containing the Z locations (may be NULL).
39 : * @param pfnTransformer the transformer function.
40 : * @param pTransformArg the callback data for the transformer function.
41 : * @param pfnProgress callback for reporting algorithm progress matching the
42 : * GDALProgressFunc() semantics. May be NULL.
43 : * @param pProgressArg callback argument passed to pfnProgress.
44 : * @param papszOptions list of name/value options - none currently supported.
45 : *
46 : * @return CE_None on success or CE_Failure if an error occurs.
47 : */
48 :
49 1 : CPLErr GDALTransformGeolocations(GDALRasterBandH hXBand, GDALRasterBandH hYBand,
50 : GDALRasterBandH hZBand,
51 : GDALTransformerFunc pfnTransformer,
52 : void *pTransformArg,
53 : GDALProgressFunc pfnProgress,
54 : void *pProgressArg,
55 : CPL_UNUSED char **papszOptions)
56 :
57 : {
58 1 : VALIDATE_POINTER1(hXBand, "GDALTransformGeolocations", CE_Failure);
59 1 : VALIDATE_POINTER1(hYBand, "GDALTransformGeolocations", CE_Failure);
60 :
61 1 : if (pfnProgress == nullptr)
62 1 : pfnProgress = GDALDummyProgress;
63 :
64 : /* -------------------------------------------------------------------- */
65 : /* Ensure the bands are matching in size. */
66 : /* -------------------------------------------------------------------- */
67 1 : GDALRasterBand *poXBand = reinterpret_cast<GDALRasterBand *>(hXBand);
68 1 : GDALRasterBand *poYBand = reinterpret_cast<GDALRasterBand *>(hYBand);
69 1 : GDALRasterBand *poZBand = reinterpret_cast<GDALRasterBand *>(hZBand);
70 1 : const int nXSize = poXBand->GetXSize();
71 1 : const int nYSize = poXBand->GetYSize();
72 :
73 2 : if (nXSize != poYBand->GetXSize() || nYSize != poYBand->GetYSize() ||
74 3 : (poZBand != nullptr && nXSize != poZBand->GetXSize()) ||
75 1 : (poZBand != nullptr && nYSize != poZBand->GetYSize()))
76 : {
77 0 : CPLError(CE_Failure, CPLE_AppDefined,
78 : "Size of X, Y and/or Z bands do not match.");
79 0 : return CE_Failure;
80 : }
81 :
82 : /* -------------------------------------------------------------------- */
83 : /* Allocate a buffer large enough to hold one whole row. */
84 : /* -------------------------------------------------------------------- */
85 : std::unique_ptr<double, VSIFreeReleaser> padfX(
86 2 : static_cast<double *>(VSI_MALLOC2_VERBOSE(sizeof(double), nXSize)));
87 : std::unique_ptr<double, VSIFreeReleaser> padfY(
88 2 : static_cast<double *>(VSI_MALLOC2_VERBOSE(sizeof(double), nXSize)));
89 : std::unique_ptr<double, VSIFreeReleaser> padfZ(
90 2 : static_cast<double *>(VSI_MALLOC2_VERBOSE(sizeof(double), nXSize)));
91 : std::unique_ptr<int, VSIFreeReleaser> panSuccess(
92 1 : static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nXSize)));
93 1 : CPLErr eErr = padfX && padfY && padfZ && panSuccess ? CE_None : CE_Failure;
94 :
95 1 : pfnProgress(0.0, "", pProgressArg);
96 3 : for (int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++)
97 : {
98 2 : eErr = poXBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfX.get(),
99 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
100 2 : if (eErr == CE_None)
101 2 : eErr = poYBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfY.get(),
102 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
103 2 : if (eErr == CE_None && poZBand != nullptr)
104 2 : eErr = poZBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfZ.get(),
105 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
106 : else
107 0 : memset(padfZ.get(), 0, sizeof(double) * nXSize);
108 :
109 2 : if (eErr == CE_None)
110 : {
111 2 : pfnTransformer(pTransformArg, FALSE, nXSize, padfX.get(),
112 : padfY.get(), padfZ.get(), panSuccess.get());
113 : }
114 :
115 2 : if (eErr == CE_None)
116 2 : eErr = poXBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfX.get(),
117 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
118 2 : if (eErr == CE_None)
119 2 : eErr = poYBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfY.get(),
120 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
121 2 : if (eErr == CE_None && poZBand != nullptr)
122 2 : eErr = poZBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfZ.get(),
123 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
124 :
125 2 : if (eErr == CE_None)
126 2 : pfnProgress((iLine + 1) / static_cast<double>(nYSize), "",
127 : pProgressArg);
128 : }
129 :
130 1 : return eErr;
131 : }
|