File: gdaltransformgeolocs.cpp

package info (click to toggle)
gdal 3.12.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 92,396 kB
  • sloc: cpp: 1,224,305; ansic: 206,456; python: 26,284; java: 6,001; xml: 4,769; sh: 3,869; cs: 2,513; yacc: 1,306; makefile: 214
file content (131 lines) | stat: -rw-r--r-- 5,886 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/******************************************************************************
 *
 * Project:  GDAL
 * Purpose:  Algorithm to apply a transformer to geolocation style bands.
 * Author:   Frank Warmerdam, warmerdam@pobox.com
 *
 ******************************************************************************
 * Copyright (c) 2012, Frank Warmerdam
 *
 * SPDX-License-Identifier: MIT
 ****************************************************************************/

#include "cpl_port.h"
#include "gdal_alg.h"

#include <cstring>

#include "cpl_conv.h"
#include "cpl_error.h"
#include "cpl_progress.h"
#include "gdal.h"
#include "gdal_alg_priv.h"
#include "gdal_priv.h"

/************************************************************************/
/*                     GDALTransformGeolocations()                      */
/************************************************************************/

/**
 * Transform locations held in bands.
 *
 * The X/Y and possibly Z values in the identified bands are transformed
 * using a spatial transformer.  The changed values are written back to the
 * source bands so they need to be updateable.
 *
 * @param hXBand the band containing the X locations (usually long/easting).
 * @param hYBand the band containing the Y locations (usually lat/northing).
 * @param hZBand the band containing the Z locations (may be NULL).
 * @param pfnTransformer the transformer function.
 * @param pTransformArg the callback data for the transformer function.
 * @param pfnProgress callback for reporting algorithm progress matching the
 * GDALProgressFunc() semantics.  May be NULL.
 * @param pProgressArg callback argument passed to pfnProgress.
 * @param papszOptions list of name/value options - none currently supported.
 *
 * @return CE_None on success or CE_Failure if an error occurs.
 */

CPLErr GDALTransformGeolocations(GDALRasterBandH hXBand, GDALRasterBandH hYBand,
                                 GDALRasterBandH hZBand,
                                 GDALTransformerFunc pfnTransformer,
                                 void *pTransformArg,
                                 GDALProgressFunc pfnProgress,
                                 void *pProgressArg,
                                 CPL_UNUSED char **papszOptions)

{
    VALIDATE_POINTER1(hXBand, "GDALTransformGeolocations", CE_Failure);
    VALIDATE_POINTER1(hYBand, "GDALTransformGeolocations", CE_Failure);

    if (pfnProgress == nullptr)
        pfnProgress = GDALDummyProgress;

    /* -------------------------------------------------------------------- */
    /*      Ensure the bands are matching in size.                          */
    /* -------------------------------------------------------------------- */
    GDALRasterBand *poXBand = reinterpret_cast<GDALRasterBand *>(hXBand);
    GDALRasterBand *poYBand = reinterpret_cast<GDALRasterBand *>(hYBand);
    GDALRasterBand *poZBand = reinterpret_cast<GDALRasterBand *>(hZBand);
    const int nXSize = poXBand->GetXSize();
    const int nYSize = poXBand->GetYSize();

    if (nXSize != poYBand->GetXSize() || nYSize != poYBand->GetYSize() ||
        (poZBand != nullptr && nXSize != poZBand->GetXSize()) ||
        (poZBand != nullptr && nYSize != poZBand->GetYSize()))
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Size of X, Y and/or Z bands do not match.");
        return CE_Failure;
    }

    /* -------------------------------------------------------------------- */
    /*      Allocate a buffer large enough to hold one whole row.           */
    /* -------------------------------------------------------------------- */
    std::unique_ptr<double, VSIFreeReleaser> padfX(
        static_cast<double *>(VSI_MALLOC2_VERBOSE(sizeof(double), nXSize)));
    std::unique_ptr<double, VSIFreeReleaser> padfY(
        static_cast<double *>(VSI_MALLOC2_VERBOSE(sizeof(double), nXSize)));
    std::unique_ptr<double, VSIFreeReleaser> padfZ(
        static_cast<double *>(VSI_MALLOC2_VERBOSE(sizeof(double), nXSize)));
    std::unique_ptr<int, VSIFreeReleaser> panSuccess(
        static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nXSize)));
    CPLErr eErr = padfX && padfY && padfZ && panSuccess ? CE_None : CE_Failure;

    pfnProgress(0.0, "", pProgressArg);
    for (int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++)
    {
        eErr = poXBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfX.get(),
                                 nXSize, 1, GDT_Float64, 0, 0, nullptr);
        if (eErr == CE_None)
            eErr = poYBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfY.get(),
                                     nXSize, 1, GDT_Float64, 0, 0, nullptr);
        if (eErr == CE_None && poZBand != nullptr)
            eErr = poZBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfZ.get(),
                                     nXSize, 1, GDT_Float64, 0, 0, nullptr);
        else
            memset(padfZ.get(), 0, sizeof(double) * nXSize);

        if (eErr == CE_None)
        {
            pfnTransformer(pTransformArg, FALSE, nXSize, padfX.get(),
                           padfY.get(), padfZ.get(), panSuccess.get());
        }

        if (eErr == CE_None)
            eErr = poXBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfX.get(),
                                     nXSize, 1, GDT_Float64, 0, 0, nullptr);
        if (eErr == CE_None)
            eErr = poYBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfY.get(),
                                     nXSize, 1, GDT_Float64, 0, 0, nullptr);
        if (eErr == CE_None && poZBand != nullptr)
            eErr = poZBand->RasterIO(GF_Write, 0, iLine, nXSize, 1, padfZ.get(),
                                     nXSize, 1, GDT_Float64, 0, 0, nullptr);

        if (eErr == CE_None)
            pfnProgress((iLine + 1) / static_cast<double>(nYSize), "",
                        pProgressArg);
    }

    return eErr;
}