LCOV - code coverage report
Current view: top level - frmts/envisat - unwrapgcps.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 64 0.0 %
Date: 2024-11-21 22:18:42 Functions: 0 2 0.0 %

          Line data    Source code
       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           0 : static double _suggest_flip_point(const int cnt, GDAL_GCP *gcp)
      43             : {
      44             :     // the histogram array - it is expected to fit the stack
      45             :     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             :     {
      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             :     }
      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             :     {
      73           0 :         if (0 == hist[i % NBIN])  // empty
      74             :         {
      75           0 :             if (!last_is_empty)  // re-start counter
      76             :             {
      77           0 :                 i0 = i;
      78           0 :                 last_is_empty = 1;
      79             :             }
      80             :         }
      81             :         else  // non-empty
      82             :         {
      83           0 :             if (last_is_empty)
      84             :             {
      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             :             }
      92             :         }
      93             :     }
      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             : }
     105             : 
     106           0 : void EnvisatUnwrapGCPs(int cnt, GDAL_GCP *gcp)
     107             : {
     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             :     double x0_dif, x1_dif;
     118             : 
     119             :     {
     120             :         double x0_min;
     121             :         double x0_max;
     122             :         double x1_min;
     123             :         double x1_max;
     124             : 
     125             :         {
     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             :         }
     134             : 
     135           0 :         for (int i = 1; i < cnt; ++i)
     136             :         {
     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             :         }
     151             : 
     152           0 :         x0_dif = x0_max - x0_min;
     153           0 :         x1_dif = x1_max - x1_min;
     154             :     }
     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             :     {
     166             :         // this should not happen
     167             :         // we give-up and return the original tie-point set
     168             : 
     169           0 :         CPLError(
     170             :             CE_Warning, CPLE_AppDefined,
     171             :             "GCPs' set is too large"
     172             :             " to perform the unwrapping! The unwrapping is not performed!");
     173             : 
     174           0 :         return;
     175             :     }
     176           0 :     else if (x1_dif < x0_dif)
     177             :     {
     178             :         // flipped GCPs' set has smaller extent -> unwrapping is performed
     179           0 :         for (int i = 1; i < cnt; ++i)
     180             :         {
     181           0 :             double x0 = gcp[i].dfGCPX;
     182             : 
     183           0 :             gcp[i].dfGCPX = x0 - (x0 > XCNT) * XDIF;
     184             :         }
     185             :     }
     186             : }

Generated by: LCOV version 1.14