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: 2024-11-21 22:18:42 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.14