LCOV - code coverage report
Current view: top level - frmts/dted - dted_create.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 108 121 89.3 %
Date: 2025-01-18 12:42:00 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  DTED Translator
       4             :  * Purpose:  Implementation of DTEDCreate() portion of DTED API.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2001, Frank Warmerdam
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "dted_api.h"
      14             : #include <assert.h>
      15             : 
      16             : #define DTED_ABS_VERT_ACC "NA  "
      17             : #define DTED_SECURITY "U"
      18             : #define DTED_EDITION 1
      19             : 
      20             : /************************************************************************/
      21             : /*                           DTEDFormatDMS()                            */
      22             : /************************************************************************/
      23             : 
      24         180 : static void DTEDFormatDMS(unsigned char *achField, size_t nTargetLenSize,
      25             :                           size_t nOffset, double dfAngle,
      26             :                           const char *pszLatLong, const char *pszFormat)
      27             : 
      28             : {
      29             :     char chHemisphere;
      30             :     int nDegrees, nMinutes, nSeconds;
      31             :     double dfRemainder;
      32             : 
      33         180 :     if (pszFormat == NULL)
      34          90 :         pszFormat = "%03d%02d%02d%c";
      35             : 
      36         180 :     assert(EQUAL(pszLatLong, "LAT") || EQUAL(pszLatLong, "LONG"));
      37             : 
      38         180 :     if (EQUAL(pszLatLong, "LAT"))
      39             :     {
      40          90 :         if (dfAngle < 0.0)
      41           0 :             chHemisphere = 'S';
      42             :         else
      43          90 :             chHemisphere = 'N';
      44             :     }
      45             :     else
      46             :     {
      47          90 :         if (dfAngle < 0.0)
      48          24 :             chHemisphere = 'W';
      49             :         else
      50          66 :             chHemisphere = 'E';
      51             :     }
      52             : 
      53         180 :     dfAngle = ABS(dfAngle);
      54             : 
      55         180 :     nDegrees = (int)floor(dfAngle + 0.5 / 3600.0);
      56         180 :     dfRemainder = dfAngle - nDegrees;
      57         180 :     nMinutes = (int)floor(dfRemainder * 60.0 + 0.5 / 60.0);
      58         180 :     dfRemainder = dfRemainder - nMinutes / 60.0;
      59         180 :     nSeconds = (int)floor(dfRemainder * 3600.0 + 0.5);
      60             : 
      61         180 :     snprintf((char *)achField + nOffset, nTargetLenSize - nOffset, pszFormat,
      62             :              nDegrees, nMinutes, nSeconds, chHemisphere);
      63         180 : }
      64             : 
      65             : /************************************************************************/
      66             : /*                             DTEDFormat()                             */
      67             : /************************************************************************/
      68             : 
      69             : static void DTEDFormat(unsigned char *pszTarget, size_t nTargetLenSize,
      70             :                        size_t nOffset, const char *pszFormat, ...)
      71             :     CPL_PRINT_FUNC_FORMAT(4, 5);
      72             : 
      73         525 : static void DTEDFormat(unsigned char *pszTarget, size_t nTargetLenSize,
      74             :                        size_t nOffset, const char *pszFormat, ...)
      75             : 
      76             : {
      77             :     va_list args;
      78             : 
      79         525 :     va_start(args, pszFormat);
      80         525 :     CPLvsnprintf((char *)pszTarget + nOffset, nTargetLenSize - nOffset,
      81             :                  pszFormat, args);
      82         525 :     va_end(args);
      83         525 : }
      84             : 
      85             : /************************************************************************/
      86             : /*                             DTEDCreate()                             */
      87             : /************************************************************************/
      88             : 
      89          17 : const char *DTEDCreate(const char *pszFilename, int nLevel, int nLLOriginLat,
      90             :                        int nLLOriginLong)
      91             : 
      92             : {
      93             :     VSILFILE *fp;
      94             :     unsigned char achRecord[3601 * 2 + 12];
      95             :     int nXSize, nYSize, nReferenceLat, iProfile;
      96             : 
      97             :     /* -------------------------------------------------------------------- */
      98             :     /*      Establish resolution.                                           */
      99             :     /* -------------------------------------------------------------------- */
     100          17 :     if (nLevel == 0)
     101             :     {
     102           3 :         nXSize = 121;
     103           3 :         nYSize = 121;
     104             :     }
     105          14 :     else if (nLevel == 1)
     106             :     {
     107          14 :         nXSize = 1201;
     108          14 :         nYSize = 1201;
     109             :     }
     110           0 :     else if (nLevel == 2)
     111             :     {
     112           0 :         nXSize = 3601;
     113           0 :         nYSize = 3601;
     114             :     }
     115             :     else
     116             :     {
     117           0 :         return CPLSPrintf("Illegal DTED Level value %d, only 0-2 allowed.",
     118             :                           nLevel);
     119             :     }
     120             : 
     121          17 :     nReferenceLat = nLLOriginLat < 0 ? -(nLLOriginLat + 1) : nLLOriginLat;
     122             : 
     123          17 :     if (nReferenceLat >= 80)
     124           0 :         nXSize = (nXSize - 1) / 6 + 1;
     125          17 :     else if (nReferenceLat >= 75)
     126           0 :         nXSize = (nXSize - 1) / 4 + 1;
     127          17 :     else if (nReferenceLat >= 70)
     128           0 :         nXSize = (nXSize - 1) / 3 + 1;
     129          17 :     else if (nReferenceLat >= 50)
     130           1 :         nXSize = (nXSize - 1) / 2 + 1;
     131             : 
     132             :     /* -------------------------------------------------------------------- */
     133             :     /*      Open the file.                                                  */
     134             :     /* -------------------------------------------------------------------- */
     135          17 :     fp = VSIFOpenL(pszFilename, "wb");
     136             : 
     137          17 :     if (fp == NULL)
     138             :     {
     139           2 :         return CPLSPrintf("Unable to create file `%s'.", pszFilename);
     140             :     }
     141             : 
     142             :     /* -------------------------------------------------------------------- */
     143             :     /*      Format and write the UHL record.                                */
     144             :     /* -------------------------------------------------------------------- */
     145          15 :     memset(achRecord, ' ', DTED_UHL_SIZE);
     146             : 
     147          15 :     DTEDFormat(achRecord, sizeof(achRecord), 0, "UHL1");
     148             : 
     149          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 4, nLLOriginLong, "LONG", NULL);
     150          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 12, nLLOriginLat, "LAT", NULL);
     151             : 
     152          15 :     DTEDFormat(achRecord, sizeof(achRecord), 20, "%04d",
     153          15 :                (3600 / (nXSize - 1)) * 10);
     154          15 :     DTEDFormat(achRecord, sizeof(achRecord), 24, "%04d",
     155          15 :                (3600 / (nYSize - 1)) * 10);
     156             : 
     157          15 :     DTEDFormat(achRecord, sizeof(achRecord), 28, "%4s", DTED_ABS_VERT_ACC);
     158          15 :     DTEDFormat(achRecord, sizeof(achRecord), 32, "%-3s", DTED_SECURITY);
     159          15 :     DTEDFormat(achRecord, sizeof(achRecord), 47, "%04d", nXSize);
     160          15 :     DTEDFormat(achRecord, sizeof(achRecord), 51, "%04d", nYSize);
     161          15 :     DTEDFormat(achRecord, sizeof(achRecord), 55, "%c", '0');
     162             : 
     163          15 :     if (VSIFWriteL(achRecord, DTED_UHL_SIZE, 1, fp) != 1)
     164           0 :         return "UHL record write failed.";
     165             : 
     166             :     /* -------------------------------------------------------------------- */
     167             :     /*      Format and write the DSI record.                                */
     168             :     /* -------------------------------------------------------------------- */
     169          15 :     memset(achRecord, ' ', DTED_DSI_SIZE);
     170             : 
     171          15 :     DTEDFormat(achRecord, sizeof(achRecord), 0, "DSI");
     172          15 :     DTEDFormat(achRecord, sizeof(achRecord), 3, "%1s", DTED_SECURITY);
     173             : 
     174          15 :     DTEDFormat(achRecord, sizeof(achRecord), 59, "DTED%d", nLevel);
     175          15 :     DTEDFormat(achRecord, sizeof(achRecord), 64, "%015d", 0);
     176          15 :     DTEDFormat(achRecord, sizeof(achRecord), 87, "%02d", DTED_EDITION);
     177          15 :     DTEDFormat(achRecord, sizeof(achRecord), 89, "%c", 'A');
     178          15 :     DTEDFormat(achRecord, sizeof(achRecord), 90, "%04d", 0);
     179          15 :     DTEDFormat(achRecord, sizeof(achRecord), 94, "%04d", 0);
     180          15 :     DTEDFormat(achRecord, sizeof(achRecord), 98, "%04d", 0);
     181          15 :     DTEDFormat(achRecord, sizeof(achRecord), 126, "PRF89020B");
     182          15 :     DTEDFormat(achRecord, sizeof(achRecord), 135, "00");
     183          15 :     DTEDFormat(achRecord, sizeof(achRecord), 137, "0005");
     184          15 :     DTEDFormat(achRecord, sizeof(achRecord), 141, "MSL");
     185          15 :     DTEDFormat(achRecord, sizeof(achRecord), 144, "WGS84");
     186             : 
     187             :     /* origin */
     188          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 185, nLLOriginLat, "LAT",
     189             :                   "%02d%02d%02d.0%c");
     190          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 194, nLLOriginLong, "LONG",
     191             :                   "%03d%02d%02d.0%c");
     192             : 
     193             :     /* SW */
     194          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 204, nLLOriginLat, "LAT",
     195             :                   "%02d%02d%02d%c");
     196          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 211, nLLOriginLong, "LONG",
     197             :                   NULL);
     198             : 
     199             :     /* NW */
     200          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 219, nLLOriginLat + 1, "LAT",
     201             :                   "%02d%02d%02d%c");
     202          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 226, nLLOriginLong, "LONG",
     203             :                   NULL);
     204             : 
     205             :     /* NE */
     206          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 234, nLLOriginLat + 1, "LAT",
     207             :                   "%02d%02d%02d%c");
     208          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 241, nLLOriginLong + 1, "LONG",
     209             :                   NULL);
     210             : 
     211             :     /* SE */
     212          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 249, nLLOriginLat, "LAT",
     213             :                   "%02d%02d%02d%c");
     214          15 :     DTEDFormatDMS(achRecord, sizeof(achRecord), 256, nLLOriginLong + 1, "LONG",
     215             :                   NULL);
     216             : 
     217          15 :     DTEDFormat(achRecord, sizeof(achRecord), 264, "0000000.0");
     218          15 :     DTEDFormat(achRecord, sizeof(achRecord), 264, "0000000.0");
     219             : 
     220          15 :     DTEDFormat(achRecord, sizeof(achRecord), 273, "%04d",
     221          15 :                (3600 / (nYSize - 1)) * 10);
     222          15 :     DTEDFormat(achRecord, sizeof(achRecord), 277, "%04d",
     223          15 :                (3600 / (nXSize - 1)) * 10);
     224             : 
     225          15 :     DTEDFormat(achRecord, sizeof(achRecord), 281, "%04d", nYSize);
     226          15 :     DTEDFormat(achRecord, sizeof(achRecord), 285, "%04d", nXSize);
     227          15 :     DTEDFormat(achRecord, sizeof(achRecord), 289, "%02d", 0);
     228             : 
     229          15 :     if (VSIFWriteL(achRecord, DTED_DSI_SIZE, 1, fp) != 1)
     230           0 :         return "DSI record write failed.";
     231             : 
     232             :     /* -------------------------------------------------------------------- */
     233             :     /*      Create and write ACC record.                                    */
     234             :     /* -------------------------------------------------------------------- */
     235          15 :     memset(achRecord, ' ', DTED_ACC_SIZE);
     236             : 
     237          15 :     DTEDFormat(achRecord, sizeof(achRecord), 0, "ACC");
     238             : 
     239          15 :     DTEDFormat(achRecord, sizeof(achRecord), 3, "NA");
     240          15 :     DTEDFormat(achRecord, sizeof(achRecord), 7, "NA");
     241          15 :     DTEDFormat(achRecord, sizeof(achRecord), 11, "NA");
     242          15 :     DTEDFormat(achRecord, sizeof(achRecord), 15, "NA");
     243             : 
     244          15 :     DTEDFormat(achRecord, sizeof(achRecord), 55, "00");
     245             : 
     246          15 :     if (VSIFWriteL(achRecord, DTED_ACC_SIZE, 1, fp) != 1)
     247           0 :         return "ACC record write failed.";
     248             : 
     249             :     /* -------------------------------------------------------------------- */
     250             :     /*      Write blank template profile data records.                      */
     251             :     /* -------------------------------------------------------------------- */
     252          15 :     memset(achRecord, 0, nYSize * 2 + 12);
     253          15 :     memset(achRecord + 8, 0xff, nYSize * 2);
     254             : 
     255          15 :     achRecord[0] = 0252;
     256             : 
     257       14190 :     for (iProfile = 0; iProfile < nXSize; iProfile++)
     258             :     {
     259       14175 :         achRecord[1] = 0;
     260       14175 :         achRecord[2] = (GByte)(iProfile / 256);
     261       14175 :         achRecord[3] = (GByte)(iProfile % 256);
     262             : 
     263       14175 :         achRecord[4] = (GByte)(iProfile / 256);
     264       14175 :         achRecord[5] = (GByte)(iProfile % 256);
     265             : 
     266       14175 :         if (VSIFWriteL(achRecord, nYSize * 2 + 12, 1, fp) != 1)
     267           0 :             return "Data record write failed.";
     268             :     }
     269             : 
     270          15 :     if (VSIFCloseL(fp) != 0)
     271           0 :         return "I/O error";
     272             : 
     273          15 :     return NULL;
     274             : }

Generated by: LCOV version 1.14