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

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  MSG Native Reader
       4             :  * Purpose:  Basic types implementation.
       5             :  * Author:   Frans van den Bergh, fvdbergh@csir.co.za
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2005, Frans van den Bergh <fvdbergh@csir.co.za>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_port.h"
      14             : #include "cpl_error.h"
      15             : #include "msg_basic_types.h"
      16             : 
      17             : #include <stdio.h>
      18             : 
      19             : namespace msg_native_format
      20             : {
      21             : 
      22             : #ifndef SQR
      23             : #define SQR(x) ((x) * (x))
      24             : #endif
      25             : 
      26             : // endian conversion routines
      27           0 : void to_native(GP_PK_HEADER &h)
      28             : {
      29           0 :     h.sourceSUId = CPL_MSBWORD32(h.sourceSUId);
      30           0 :     h.sequenceCount = CPL_MSBWORD16(h.sequenceCount);
      31           0 :     h.packetLength = CPL_MSBWORD32(h.packetLength);
      32           0 : }
      33             : 
      34           0 : void to_native(GP_PK_SH1 &h)
      35             : {
      36           0 :     h.spacecraftId = CPL_MSBWORD16(h.spacecraftId);
      37           0 :     h.packetTime.day = CPL_MSBWORD16(h.packetTime.day);
      38           0 :     h.packetTime.ms = CPL_MSBWORD32(h.packetTime.ms);
      39           0 : }
      40             : 
      41           0 : void to_native(SUB_VISIRLINE &v)
      42             : {
      43           0 :     v.satelliteId = CPL_MSBWORD16(v.satelliteId);
      44           0 :     v.lineNumberInVisirGrid = CPL_MSBWORD32(v.lineNumberInVisirGrid);
      45           0 : }
      46             : 
      47           0 : static void swap_64_bits(unsigned char *b)
      48             : {
      49           0 :     CPL_SWAP64PTR(b);
      50           0 : }
      51             : 
      52           0 : void to_native(RADIOMETRIC_PROCESSING_RECORD &r)
      53             : {
      54           0 :     for (int i = 0; i < 12; i++)
      55             :     {
      56           0 :         swap_64_bits((unsigned char *)&r.level1_5ImageCalibration[i].cal_slope);
      57           0 :         swap_64_bits(
      58           0 :             (unsigned char *)&r.level1_5ImageCalibration[i].cal_offset);
      59             :     }
      60           0 : }
      61             : 
      62           0 : static void to_native(REFERENCEGRID_VISIR &r)
      63             : {
      64           0 :     r.numberOfLines = CPL_MSBWORD32(r.numberOfLines);
      65           0 :     r.numberOfColumns = CPL_MSBWORD32(r.numberOfColumns);
      66             :     // should floats be swapped too?
      67             :     float f;
      68             : 
      69             :     // convert float using CPL_MSBPTR32
      70           0 :     memcpy(&f, &r.lineDirGridStep, sizeof(f));
      71           0 :     CPL_MSBPTR32(&f);
      72           0 :     r.lineDirGridStep = f;
      73             : 
      74             :     // convert float using CPL_MSBPTR32
      75           0 :     memcpy(&f, &r.columnDirGridStep, sizeof(f));
      76           0 :     CPL_MSBPTR32(&f);
      77           0 :     r.columnDirGridStep = f;
      78           0 : }
      79             : 
      80           0 : static void to_native(PLANNED_COVERAGE_VISIR &r)
      81             : {
      82           0 :     r.southernLinePlanned = CPL_MSBWORD32(r.southernLinePlanned);
      83           0 :     r.northernLinePlanned = CPL_MSBWORD32(r.northernLinePlanned);
      84           0 :     r.easternColumnPlanned = CPL_MSBWORD32(r.easternColumnPlanned);
      85           0 :     r.westernColumnPlanned = CPL_MSBWORD32(r.westernColumnPlanned);
      86           0 : }
      87             : 
      88           0 : static void to_native(PLANNED_COVERAGE_HRV &r)
      89             : {
      90           0 :     r.lowerSouthLinePlanned = CPL_MSBWORD32(r.lowerSouthLinePlanned);
      91           0 :     r.lowerNorthLinePlanned = CPL_MSBWORD32(r.lowerNorthLinePlanned);
      92           0 :     r.lowerEastColumnPlanned = CPL_MSBWORD32(r.lowerEastColumnPlanned);
      93           0 :     r.lowerWestColumnPlanned = CPL_MSBWORD32(r.lowerWestColumnPlanned);
      94           0 :     r.upperSouthLinePlanned = CPL_MSBWORD32(r.upperSouthLinePlanned);
      95           0 :     r.upperNorthLinePlanned = CPL_MSBWORD32(r.upperNorthLinePlanned);
      96           0 :     r.upperEastColumnPlanned = CPL_MSBWORD32(r.upperEastColumnPlanned);
      97           0 :     r.upperWestColumnPlanned = CPL_MSBWORD32(r.upperWestColumnPlanned);
      98           0 : }
      99             : 
     100           0 : void to_native(IMAGE_DESCRIPTION_RECORD &r)
     101             : {
     102             :     float f;
     103             : 
     104             :     // convert float using CPL_MSBPTR32
     105           0 :     memcpy(&f, &r.longitudeOfSSP, sizeof(f));
     106           0 :     CPL_MSBPTR32(&f);
     107           0 :     r.longitudeOfSSP = f;
     108             : 
     109           0 :     to_native(r.referencegrid_visir);
     110           0 :     to_native(r.referencegrid_hrv);
     111           0 :     to_native(r.plannedCoverage_visir);
     112           0 :     to_native(r.plannedCoverage_hrv);
     113           0 : }
     114             : 
     115           0 : void to_native(ACTUAL_L15_COVERAGE_VISIR_RECORD &r)
     116             : {
     117           0 :     r.southernLineActual = CPL_MSBWORD32(r.southernLineActual);
     118           0 :     r.northernLineActual = CPL_MSBWORD32(r.northernLineActual);
     119           0 :     r.easternColumnActual = CPL_MSBWORD32(r.easternColumnActual);
     120           0 :     r.westernColumnActual = CPL_MSBWORD32(r.westernColumnActual);
     121           0 : }
     122             : 
     123           0 : void to_native(ACTUAL_L15_COVERAGE_HRV_RECORD &r)
     124             : {
     125           0 :     r.lowerSouthLineActual = CPL_MSBWORD32(r.lowerSouthLineActual);
     126           0 :     r.lowerNorthLineActual = CPL_MSBWORD32(r.lowerNorthLineActual);
     127           0 :     r.lowerEastColumnActual = CPL_MSBWORD32(r.lowerEastColumnActual);
     128           0 :     r.lowerWestColumnActual = CPL_MSBWORD32(r.lowerWestColumnActual);
     129           0 :     r.upperSouthLineActual = CPL_MSBWORD32(r.upperSouthLineActual);
     130           0 :     r.upperNorthLineActual = CPL_MSBWORD32(r.upperNorthLineActual);
     131           0 :     r.upperEastColumnActual = CPL_MSBWORD32(r.upperEastColumnActual);
     132           0 :     r.upperWestColumnActual = CPL_MSBWORD32(r.upperWestColumnActual);
     133           0 : }
     134             : 
     135           0 : void to_string(PH_DATA &d)
     136             : {
     137           0 :     d.name[29] = 0;
     138           0 :     d.value[49] = 0;
     139           0 : }
     140             : 
     141             : #ifdef notdef
     142             : // unit tests on structures
     143             : bool perform_type_size_check(void)
     144             : {
     145             :     bool success = true;
     146             :     if (sizeof(MAIN_PROD_HEADER) != 3674)
     147             :     {
     148             :         fprintf(stderr, "MAIN_PROD_HEADER size not 3674 (%lu)\n", /*ok*/
     149             :                 (unsigned long)sizeof(MAIN_PROD_HEADER));
     150             :         success = false;
     151             :     }
     152             :     if (sizeof(SECONDARY_PROD_HEADER) != 1120)
     153             :     {
     154             :         fprintf(stderr, "SECONDARY_PROD_HEADER size not 1120 (%lu)\n", /*ok*/
     155             :                 (unsigned long)sizeof(SECONDARY_PROD_HEADER));
     156             :         success = false;
     157             :     }
     158             :     if (sizeof(SUB_VISIRLINE) != 27)
     159             :     {
     160             :         fprintf(stderr, "SUB_VISIRLINE size not 17 (%lu)\n", /*ok*/
     161             :                 (unsigned long)sizeof(SUB_VISIRLINE));
     162             :         success = false;
     163             :     }
     164             :     if (sizeof(GP_PK_HEADER) != 22)
     165             :     {
     166             :         fprintf(stderr, "GP_PK_HEADER size not 22 (%lu)\n", /*ok*/
     167             :                 (unsigned long)sizeof(GP_PK_HEADER));
     168             :         success = false;
     169             :     }
     170             :     if (sizeof(GP_PK_SH1) != 16)
     171             :     {
     172             :         fprintf(stderr, "GP_PK_SH1 size not 16 (%lu)\n", /*ok*/
     173             :                 (unsigned long)sizeof(GP_PK_SH1));
     174             :         success = false;
     175             :     }
     176             :     return success;
     177             : }
     178             : #endif
     179             : 
     180             : const double Conversions::altitude = 42164;  // km from origin
     181             : // the spheroid in CGMS 03 4.4.3.2 is unique - flattening is 1/295.488
     182             : // note the req and rpol were revised in issue 2.8 of CGMS/DOC/12/0017 - these
     183             : // are the revised values
     184             : const double Conversions::req = 6378.1370;   // earth equatorial radius
     185             : const double Conversions::rpol = 6356.7523;  // earth polar radius
     186             : 
     187             : // replace the magic constants in the paper with the calculated values in case
     188             : // of further change
     189             : const double Conversions::dtp2 =
     190             :     (SQR(altitude) -
     191             :      SQR(req));  // square of the distance to the equatorial tangent point
     192             :                  // first/last point sensed on the equator
     193             : 
     194             : // given req and rpol, oblate is already defined. Unused afaik in the gdal code
     195             : const double Conversions::oblate = ((req - rpol) / req);  // oblateness of earth
     196             : const double Conversions::eccentricity2 =
     197             :     (1.0 - (SQR(rpol) / SQR(req)));  // 0.00669438...
     198             : const double Conversions::ratio2 =
     199             :     SQR(rpol / req);  // 0.9933056   1/x = 1.006739501
     200             : const double Conversions::deg_to_rad = (M_PI / 180.0);
     201             : const double Conversions::rad_to_deg = (180.0 / M_PI);
     202             : const double Conversions::nlines = 3712;  // number of lines in an image
     203             : const double Conversions::step =
     204             :     17.83 / nlines;  // pixel / line step in degrees
     205             : 
     206             : const int Conversions::CFAC = -781648343;
     207             : const int Conversions::LFAC = -781648343;
     208             : const int Conversions::COFF = 1856;
     209             : const int Conversions::LOFF = 1856;
     210             : const double Conversions::CFAC_scaled = ((double)CFAC / (1 << 16));
     211             : const double Conversions::LFAC_scaled = ((double)LFAC / (1 << 16));
     212             : 
     213             : #define SQR(x) ((x) * (x))
     214             : 
     215           0 : void Conversions::convert_pixel_to_geo(double line, double column,
     216             :                                        double &longitude, double &latitude)
     217             : {
     218             :     // x and y are angles in radians
     219           0 :     double x = (column - COFF - 0.0) / CFAC_scaled;
     220           0 :     double y = (line - LOFF - 0.0) / LFAC_scaled;
     221             : 
     222           0 :     double sd = sqrt(SQR(altitude * cos(x) * cos(y)) -
     223           0 :                      (SQR(cos(y)) + SQR(sin(y)) / ratio2) * dtp2);
     224           0 :     double sn = (altitude * cos(x) * cos(y) - sd) /
     225           0 :                 (SQR(cos(y)) + SQR(sin(y)) / ratio2);
     226           0 :     double s1 = altitude - sn * SQR(cos(y));
     227           0 :     double s2 = sn * sin(x) * cos(y);
     228           0 :     double s3 = -sn * sin(y);
     229           0 :     double sxy = sqrt(s1 * s1 + s2 * s2);
     230             : 
     231           0 :     longitude = atan(s2 / s1);
     232           0 :     latitude = atan((s3 / sxy) / ratio2);
     233             : 
     234           0 :     longitude = longitude * rad_to_deg;
     235           0 :     latitude = latitude * rad_to_deg;
     236           0 : }
     237             : 
     238           0 : void Conversions::compute_pixel_xyz(double line, double column, double &x,
     239             :                                     double &y, double &z)
     240             : {
     241           0 :     double asamp = -(column - (nlines / 2.0 + 0.5)) * step;
     242           0 :     double aline = (line - (nlines / 2.0 + 0.5)) * step;
     243             : 
     244           0 :     asamp *= deg_to_rad;
     245           0 :     aline *= deg_to_rad;
     246             : 
     247           0 :     double tanal = tan(aline);
     248           0 :     double tanas = tan(asamp);
     249             : 
     250           0 :     double p = -1;
     251           0 :     double q = tanas;
     252           0 :     double r = tanal * sqrt(1 + q * q);
     253             : 
     254           0 :     double a = q * q + SQR((r * req / rpol)) + p * p;
     255           0 :     double b = 2 * altitude * p;
     256           0 :     double c = altitude * altitude - req * req;
     257             : 
     258           0 :     double det = b * b - 4 * a * c;
     259             : 
     260           0 :     if (det > 0)
     261             :     {
     262           0 :         double k = (-b - sqrt(det)) / (2 * a);
     263           0 :         x = altitude + k * p;
     264           0 :         y = k * q;
     265           0 :         z = k * r;
     266             :     }
     267             :     else
     268             :     {
     269           0 :         x = y = z = 0;
     270           0 :         CPLError(CE_Warning, CPLE_AppDefined, "Warning: pixel not visible");
     271             :     }
     272           0 : }
     273             : 
     274           0 : double Conversions::compute_pixel_area_sqkm(double line, double column)
     275             : {
     276             :     double x1, x2;
     277             :     double y1, y2;
     278             :     double z1, z2;
     279             : 
     280           0 :     compute_pixel_xyz(line - 0.5, column - 0.5, x1, y1, z1);
     281           0 :     compute_pixel_xyz(line + 0.5, column - 0.5, x2, y2, z2);
     282             : 
     283           0 :     double xlen = sqrt(SQR(x1 - x2) + SQR(y1 - y2) + SQR(z1 - z2));
     284             : 
     285           0 :     compute_pixel_xyz(line - 0.5, column + 0.5, x2, y2, z2);
     286             : 
     287           0 :     double ylen = sqrt(SQR(x1 - x2) + SQR(y1 - y2) + SQR(z1 - z2));
     288             : 
     289           0 :     return xlen * ylen;
     290             : }
     291             : 
     292           0 : void Conversions::convert_geo_to_pixel(double longitude, double latitude,
     293             :                                        unsigned int &line, unsigned int &column)
     294             : {
     295             : 
     296           0 :     latitude = latitude * deg_to_rad;
     297           0 :     longitude = longitude * deg_to_rad;
     298             : 
     299           0 :     double c_lat = atan(ratio2 * tan(latitude));
     300           0 :     double r_l = rpol / sqrt(1 - eccentricity2 * cos(c_lat) * cos(c_lat));
     301           0 :     double r1 = altitude - r_l * cos(c_lat) * cos(longitude);
     302           0 :     double r2 = -r_l * cos(c_lat) * sin(longitude);
     303           0 :     double r3 = r_l * sin(c_lat);
     304           0 :     double rn = sqrt(r1 * r1 + r2 * r2 + r3 * r3);
     305             : 
     306           0 :     double x = atan(-r2 / r1) * CFAC_scaled + COFF;
     307           0 :     double y = asin(-r3 / rn) * LFAC_scaled + LOFF;
     308             : 
     309           0 :     line = (unsigned int)floor(x + 0.5);
     310           0 :     column = (unsigned int)floor(y + 0.5);
     311           0 : }
     312             : 
     313             : }  // namespace msg_native_format

Generated by: LCOV version 1.14