/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 | } |