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 1 : double *padfX = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
86 1 : double *padfY = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
87 1 : double *padfZ = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
88 1 : int *panSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nXSize));
89 1 : CPLErr eErr = CE_None;
90 :
91 1 : pfnProgress(0.0, "", pProgressArg);
92 3 : for (int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++)
93 : {
94 2 : eErr = poXBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfX, nXSize, 1,
95 : GDT_Float64, 0, 0, nullptr);
96 2 : if (eErr == CE_None)
97 2 : eErr = poYBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfY,
98 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
99 2 : if (eErr == CE_None && poZBand != nullptr)
100 2 : eErr = poZBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfZ,
101 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
102 : else
103 0 : memset(padfZ, 0, sizeof(double) * nXSize);
104 :
105 2 : if (eErr == CE_None)
106 : {
107 2 : pfnTransformer(pTransformArg, FALSE, nXSize, padfX, padfY, padfZ,
108 : panSuccess);
109 : }
110 :
111 2 : if (eErr == CE_None)
112 2 : eErr = poXBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfX,
113 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
114 2 : if (eErr == CE_None)
115 2 : eErr = poYBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfY,
116 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
117 2 : if (eErr == CE_None && poZBand != nullptr)
118 2 : eErr = poZBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfZ,
119 : nXSize, 1, GDT_Float64, 0, 0, nullptr);
120 :
121 2 : if (eErr == CE_None)
122 2 : pfnProgress((iLine + 1) / static_cast<double>(nYSize), "",
123 : pProgressArg);
124 : }
125 :
126 : /* -------------------------------------------------------------------- */
127 : /* Cleanup */
128 : /* -------------------------------------------------------------------- */
129 1 : CPLFree(padfX);
130 1 : CPLFree(padfY);
131 1 : CPLFree(padfZ);
132 1 : CPLFree(panSuccess);
133 :
134 1 : return eErr;
135 : }
|