Coverage Report

Created: 2026-08-11 08:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/envisat/unwrapgcps.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  APP ENVISAT Support
4
 * Purpose:  GCPs Unwrapping for products crossing the WGS84 date-line
5
 * Author:   Martin Paces martin.paces@eox.at
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2013, EOX IT Services, GmbH
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "gdal.h"
14
#include <cmath>
15
#include <cstdio>
16
17
// number of histogram bins (36 a 10dg)
18
constexpr int NBIN = 36;
19
// number of empty bins to guess the flip-point
20
constexpr int NEMPY = 7;
21
22
// WGS84 bounds
23
constexpr double XMIN = -180.0;
24
// constexpr double XMAX = 180.0;
25
constexpr double XDIF = 360.0;
26
constexpr double XCNT = 0.0;
27
28
// max. allowed longitude extent of the GCP set
29
constexpr double XLIM = XDIF * (1.0 - NEMPY * (1.0 / NBIN));
30
31
/* used by envisatdataset.cpp */
32
extern void EnvisatUnwrapGCPs(int cnt, GDAL_GCP *gcp);
33
34
// The algorithm is based on assumption that the unwrapped
35
// GCPs ('flipped' values) have smaller extent along the longitude.
36
// We further assume that the length of the striplines is limited
37
// to one orbit and does not exceeded given limit along the longitude,
38
// e.i., the wrapped-around coordinates have significantly larger
39
// extent the unwrapped. If the smaller extend exceeds the limit
40
// the original tiepoints are returned.
41
42
static double _suggest_flip_point(const int cnt, GDAL_GCP *gcp)
43
0
{
44
    // the histogram array - it is expected to fit the stack
45
0
    int hist[NBIN];
46
47
    // reset the histogram counters
48
0
    for (int i = 0; i < NBIN; i++)
49
0
        hist[i] = 0;
50
51
    // accumulate the histogram
52
0
    for (int i = 0; i < cnt; i++)
53
0
    {
54
0
        double x = (gcp[i].dfGCPX - XMIN) / XDIF;
55
0
        int idx = (int)(NBIN * (x - floor(x)));
56
57
        // The latitudes should lay in the +/-180 bounds
58
        // although it should never happen we check the outliers
59
0
        if (idx < 0)
60
0
            idx = 0;
61
0
        if (idx >= NBIN)
62
0
            idx = NBIN - 1;
63
64
0
        hist[idx] += 1;
65
0
    }
66
67
    // Find middle of at least NEMPTY consecutive empty bins and get its middle.
68
0
    int i0 = -1;
69
0
    int i1 = -1;
70
0
    int last_is_empty = 0;
71
0
    for (int i = 0; i < (2 * NBIN - 1); i++)
72
0
    {
73
0
        if (0 == hist[i % NBIN])  // empty
74
0
        {
75
0
            if (!last_is_empty)  // re-start counter
76
0
            {
77
0
                i0 = i;
78
0
                last_is_empty = 1;
79
0
            }
80
0
        }
81
0
        else  // non-empty
82
0
        {
83
0
            if (last_is_empty)
84
0
            {
85
0
                i1 = i;
86
0
                last_is_empty = 0;
87
88
                // if the segment is long enough -> terminate
89
0
                if ((i1 - i0) >= NEMPY)
90
0
                    break;
91
0
            }
92
0
        }
93
0
    }
94
95
    // if all full or all empty the returning default value
96
0
    if (i1 < 0)
97
0
        return XCNT;
98
99
    // return the flip-centre
100
101
0
    double tmp = ((i1 - i0) * 0.5 + i0) / ((float)NBIN);
102
103
0
    return (tmp - floor(tmp)) * XDIF + XMIN;
104
0
}
105
106
void EnvisatUnwrapGCPs(int cnt, GDAL_GCP *gcp)
107
0
{
108
0
    if (cnt < 1)
109
0
        return;
110
111
    // suggest right flip-point
112
0
    double x_flip = _suggest_flip_point(cnt, gcp);
113
114
    // Find the limits along the longitude (x) for flipped and unflipped values.
115
116
0
    int cnt_flip = 0;  // flipped values' counter
117
0
    double x0_dif, x1_dif;
118
119
0
    {
120
0
        double x0_min;
121
0
        double x0_max;
122
0
        double x1_min;
123
0
        double x1_max;
124
125
0
        {
126
0
            double x0 = gcp[0].dfGCPX;
127
0
            int flip = (x0 > x_flip);
128
0
            x0_min = x0;
129
0
            x0_max = x0;
130
0
            x1_min = x0 - flip * XDIF;
131
0
            x1_max = x1_min;
132
0
            cnt_flip += flip;  // count the flipped values
133
0
        }
134
135
0
        for (int i = 1; i < cnt; ++i)
136
0
        {
137
0
            double x0 = gcp[i].dfGCPX;
138
0
            int flip = (x0 > x_flip);
139
0
            double x1 = x0 - flip * XDIF;  // flipped value
140
0
            cnt_flip += flip;              // count the flipped values
141
142
0
            if (x0 > x0_max)
143
0
                x0_max = x0;
144
0
            if (x0 < x0_min)
145
0
                x0_min = x0;
146
0
            if (x1 > x1_max)
147
0
                x1_max = x1;
148
0
            if (x1 < x1_min)
149
0
                x1_min = x1;
150
0
        }
151
152
0
        x0_dif = x0_max - x0_min;
153
0
        x1_dif = x1_max - x1_min;
154
0
    }
155
156
    // in case all values either flipped or non-flipped
157
    // nothing is to be done
158
0
    if ((cnt_flip == 0) || (cnt_flip == cnt))
159
0
        return;
160
161
    // check whether we need to split the segment
162
    // i.e., segment is too long decide the best option
163
164
0
    if ((x0_dif > XLIM) && (x1_dif > XLIM))
165
0
    {
166
        // this should not happen
167
        // we give-up and return the original tie-point set
168
169
0
        CPLError(
170
0
            CE_Warning, CPLE_AppDefined,
171
0
            "GCPs' set is too large"
172
0
            " to perform the unwrapping! The unwrapping is not performed!");
173
174
0
        return;
175
0
    }
176
0
    else if (x1_dif < x0_dif)
177
0
    {
178
        // flipped GCPs' set has smaller extent -> unwrapping is performed
179
0
        for (int i = 1; i < cnt; ++i)
180
0
        {
181
0
            double x0 = gcp[i].dfGCPX;
182
183
0
            gcp[i].dfGCPX = x0 - (x0 > XCNT) * XDIF;
184
0
        }
185
0
    }
186
0
}