LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/ntf - ntf_raster.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 162 0.0 %
Date: 2024-11-25 13:07:18 Functions: 0 12 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  NTF Translator
       4             :  * Purpose:  Handle UK Ordnance Survey Raster DTM products.  Includes some
       5             :  *           raster related methods from NTFFileReader and the implementation
       6             :  *           of OGRNTFRasterLayer.
       7             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8             :  *
       9             :  ******************************************************************************
      10             :  * Copyright (c) 1999, Frank Warmerdam
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "ntf.h"
      16             : 
      17             : #include <algorithm>
      18             : 
      19             : /************************************************************************/
      20             : /* ==================================================================== */
      21             : /*                     NTFFileReader Raster Methods                     */
      22             : /* ==================================================================== */
      23             : /************************************************************************/
      24             : 
      25             : /************************************************************************/
      26             : /*                          IsRasterProduct()                           */
      27             : /************************************************************************/
      28             : 
      29           0 : int NTFFileReader::IsRasterProduct()
      30             : 
      31             : {
      32           0 :     return GetProductId() == NPC_LANDRANGER_DTM ||
      33           0 :            GetProductId() == NPC_LANDFORM_PROFILE_DTM;
      34             : }
      35             : 
      36             : /************************************************************************/
      37             : /*                       EstablishRasterAccess()                        */
      38             : /************************************************************************/
      39             : 
      40           0 : void NTFFileReader::EstablishRasterAccess()
      41             : 
      42             : {
      43             :     /* -------------------------------------------------------------------- */
      44             :     /*      Read the type 50 record.                                        */
      45             :     /* -------------------------------------------------------------------- */
      46           0 :     NTFRecord *poRecord = nullptr;
      47             : 
      48           0 :     while ((poRecord = ReadRecord()) != nullptr &&
      49           0 :            poRecord->GetType() != NRT_GRIDHREC &&
      50           0 :            poRecord->GetType() != NRT_VTR)
      51             :     {
      52           0 :         delete poRecord;
      53             :     }
      54             : 
      55           0 :     if (poRecord == nullptr || poRecord->GetType() != NRT_GRIDHREC)
      56             :     {
      57           0 :         delete poRecord;
      58           0 :         CPLError(CE_Failure, CPLE_AppDefined,
      59             :                  "Unable to find GRIDHREC (type 50) record in what appears\n"
      60             :                  "to be an NTF Raster DTM product.");
      61           0 :         return;
      62             :     }
      63             : 
      64             :     /* -------------------------------------------------------------------- */
      65             :     /*      Parse if LANDRANGER_DTM                                         */
      66             :     /* -------------------------------------------------------------------- */
      67           0 :     if (GetProductId() == NPC_LANDRANGER_DTM)
      68             :     {
      69           0 :         nRasterXSize = atoi(poRecord->GetField(13, 16));
      70           0 :         nRasterYSize = atoi(poRecord->GetField(17, 20));
      71             : 
      72             :         // NOTE: unusual use of GeoTransform - the pixel origin is the
      73             :         // bottom left corner!
      74           0 :         adfGeoTransform[0] = atoi(poRecord->GetField(25, 34));
      75           0 :         adfGeoTransform[1] = 50;
      76           0 :         adfGeoTransform[2] = 0;
      77           0 :         adfGeoTransform[3] = atoi(poRecord->GetField(35, 44));
      78           0 :         adfGeoTransform[4] = 0;
      79           0 :         adfGeoTransform[5] = 50;
      80             : 
      81           0 :         nRasterDataType = 3; /* GDT_Int16 */
      82             :     }
      83             : 
      84             :     /* -------------------------------------------------------------------- */
      85             :     /*      Parse if LANDFORM_PROFILE_DTM                                   */
      86             :     /* -------------------------------------------------------------------- */
      87           0 :     else if (GetProductId() == NPC_LANDFORM_PROFILE_DTM)
      88             :     {
      89           0 :         nRasterXSize = atoi(poRecord->GetField(23, 30));
      90           0 :         nRasterYSize = atoi(poRecord->GetField(31, 38));
      91             : 
      92             :         // NOTE: unusual use of GeoTransform - the pixel origin is the
      93             :         // bottom left corner!
      94           0 :         adfGeoTransform[0] = atoi(poRecord->GetField(13, 17)) + GetXOrigin();
      95           0 :         adfGeoTransform[1] = atoi(poRecord->GetField(39, 42));
      96           0 :         adfGeoTransform[2] = 0;
      97           0 :         adfGeoTransform[3] = atoi(poRecord->GetField(18, 22)) + GetYOrigin();
      98           0 :         adfGeoTransform[4] = 0;
      99           0 :         adfGeoTransform[5] = atoi(poRecord->GetField(43, 46));
     100             : 
     101           0 :         nRasterDataType = 3; /* GDT_Int16 */
     102             :     }
     103             : 
     104             :     /* -------------------------------------------------------------------- */
     105             :     /*      Initialize column offsets table.                                */
     106             :     /* -------------------------------------------------------------------- */
     107           0 :     delete poRecord;
     108             : 
     109           0 :     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
     110           0 :         return;
     111             : 
     112           0 :     panColumnOffset = static_cast<vsi_l_offset *>(
     113           0 :         CPLCalloc(sizeof(vsi_l_offset), nRasterXSize));
     114             : 
     115           0 :     GetFPPos(panColumnOffset + 0, nullptr);
     116             : 
     117             :     /* -------------------------------------------------------------------- */
     118             :     /*      Create an OGRSFLayer for this file readers raster points.       */
     119             :     /* -------------------------------------------------------------------- */
     120           0 :     if (poDS != nullptr)
     121             :     {
     122           0 :         poRasterLayer = new OGRNTFRasterLayer(poDS, this);
     123           0 :         poDS->AddLayer(poRasterLayer);
     124             :     }
     125             : }
     126             : 
     127             : /************************************************************************/
     128             : /*                          ReadRasterColumn()                          */
     129             : /************************************************************************/
     130             : 
     131           0 : CPLErr NTFFileReader::ReadRasterColumn(int iColumn, float *pafElev)
     132             : 
     133             : {
     134             :     /* -------------------------------------------------------------------- */
     135             :     /*      If we don't already have the scanline offset of the previous    */
     136             :     /*      line, force reading of previous records to establish it.        */
     137             :     /* -------------------------------------------------------------------- */
     138           0 :     if (panColumnOffset[iColumn] == 0)
     139             :     {
     140           0 :         for (int iPrev = 0; iPrev < iColumn - 1; iPrev++)
     141             :         {
     142           0 :             if (panColumnOffset[iPrev + 1] == 0)
     143             :             {
     144             :                 CPLErr eErr;
     145             : 
     146           0 :                 eErr = ReadRasterColumn(iPrev, nullptr);
     147           0 :                 if (eErr != CE_None)
     148           0 :                     return eErr;
     149             :             }
     150             :         }
     151             :     }
     152             : 
     153             :     /* -------------------------------------------------------------------- */
     154             :     /*      If the dataset isn't open, open it now.                         */
     155             :     /* -------------------------------------------------------------------- */
     156           0 :     if (GetFP() == nullptr)
     157           0 :         Open();
     158             : 
     159             :     /* -------------------------------------------------------------------- */
     160             :     /*      Read requested record.                                          */
     161             :     /* -------------------------------------------------------------------- */
     162           0 :     SetFPPos(panColumnOffset[iColumn], iColumn);
     163           0 :     NTFRecord *poRecord = ReadRecord();
     164           0 :     if (poRecord == nullptr)
     165           0 :         return CE_Failure;
     166             : 
     167           0 :     CPLErr eErr = CE_None;
     168           0 :     if (iColumn < nRasterXSize - 1)
     169             :     {
     170           0 :         GetFPPos(panColumnOffset + iColumn + 1, nullptr);
     171             :     }
     172             : 
     173             :     /* -------------------------------------------------------------------- */
     174             :     /*      Handle LANDRANGER DTM columns.                                  */
     175             :     /* -------------------------------------------------------------------- */
     176           0 :     if (pafElev != nullptr && GetProductId() == NPC_LANDRANGER_DTM)
     177             :     {
     178           0 :         const double dfVOffset = atoi(poRecord->GetField(56, 65));
     179           0 :         const double dfVScale = atoi(poRecord->GetField(66, 75)) * 0.001;
     180             : 
     181           0 :         for (int iPixel = 0; iPixel < nRasterYSize; iPixel++)
     182             :         {
     183             :             const char *pszValue =
     184           0 :                 poRecord->GetField(84 + iPixel * 4, 87 + iPixel * 4);
     185           0 :             if (pszValue[0] == '\0' || pszValue[0] == ' ')
     186             :             {
     187           0 :                 eErr = CE_Failure;
     188           0 :                 break;
     189             :             }
     190           0 :             pafElev[iPixel] = (float)(dfVOffset + dfVScale * atoi(pszValue));
     191             :         }
     192             :     }
     193             : 
     194             :     /* -------------------------------------------------------------------- */
     195             :     /*      Handle PROFILE                                                  */
     196             :     /* -------------------------------------------------------------------- */
     197           0 :     else if (pafElev != nullptr && GetProductId() == NPC_LANDFORM_PROFILE_DTM)
     198             :     {
     199           0 :         for (int iPixel = 0; iPixel < nRasterYSize; iPixel++)
     200             :         {
     201             :             const char *pszValue =
     202           0 :                 poRecord->GetField(19 + iPixel * 5, 23 + iPixel * 5);
     203           0 :             if (pszValue[0] == '\0' || pszValue[0] == ' ')
     204             :             {
     205           0 :                 eErr = CE_Failure;
     206           0 :                 break;
     207             :             }
     208           0 :             pafElev[iPixel] = (float)(atoi(pszValue) * GetZMult());
     209             :         }
     210             :     }
     211             : 
     212           0 :     delete poRecord;
     213             : 
     214           0 :     return eErr;
     215             : }
     216             : 
     217             : /************************************************************************/
     218             : /* ==================================================================== */
     219             : /*                        OGRNTFRasterLayer                             */
     220             : /* ==================================================================== */
     221             : /************************************************************************/
     222             : 
     223             : /************************************************************************/
     224             : /*                          OGRNTFRasterLayer                           */
     225             : /************************************************************************/
     226             : 
     227           0 : OGRNTFRasterLayer::OGRNTFRasterLayer(OGRNTFDataSource *poDSIn,
     228           0 :                                      NTFFileReader *poReaderIn)
     229             :     : poFeatureDefn(nullptr), poFilterGeom(nullptr), poReader(poReaderIn),
     230             :       pafColumn(static_cast<float *>(
     231           0 :           CPLCalloc(sizeof(float), poReaderIn->GetRasterYSize()))),
     232             :       iColumnOffset(-1), iCurrentFC(1),
     233             :       // Check for DEM subsampling.
     234           0 :       nDEMSample(poDSIn->GetOption("DEM_SAMPLE") == nullptr
     235           0 :                      ? 1
     236           0 :                      : std::max(1, atoi(poDSIn->GetOption("DEM_SAMPLE")))),
     237           0 :       nFeatureCount(0)
     238             : {
     239             :     char szLayerName[128];
     240           0 :     snprintf(szLayerName, sizeof(szLayerName), "DTM_%s",
     241             :              poReaderIn->GetTileName());
     242           0 :     poFeatureDefn = new OGRFeatureDefn(szLayerName);
     243             : 
     244           0 :     poFeatureDefn->Reference();
     245           0 :     poFeatureDefn->SetGeomType(wkbPoint25D);
     246           0 :     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(
     247           0 :         poDSIn->DSGetSpatialRef());
     248             : 
     249           0 :     OGRFieldDefn oHeight("HEIGHT", OFTReal);
     250           0 :     poFeatureDefn->AddFieldDefn(&oHeight);
     251             : 
     252           0 :     nFeatureCount =
     253           0 :         static_cast<GIntBig>(poReader->GetRasterXSize() / nDEMSample) *
     254           0 :         (poReader->GetRasterYSize() / nDEMSample);
     255           0 : }
     256             : 
     257             : /************************************************************************/
     258             : /*                         ~OGRNTFRasterLayer()                         */
     259             : /************************************************************************/
     260             : 
     261           0 : OGRNTFRasterLayer::~OGRNTFRasterLayer()
     262             : 
     263             : {
     264           0 :     CPLFree(pafColumn);
     265           0 :     if (poFeatureDefn)
     266           0 :         poFeatureDefn->Release();
     267             : 
     268           0 :     if (poFilterGeom != nullptr)
     269           0 :         delete poFilterGeom;
     270           0 : }
     271             : 
     272             : /************************************************************************/
     273             : /*                          SetSpatialFilter()                          */
     274             : /************************************************************************/
     275             : 
     276           0 : void OGRNTFRasterLayer::SetSpatialFilter(OGRGeometry *poGeomIn)
     277             : 
     278             : {
     279           0 :     if (poFilterGeom != nullptr)
     280             :     {
     281           0 :         delete poFilterGeom;
     282           0 :         poFilterGeom = nullptr;
     283             :     }
     284             : 
     285           0 :     if (poGeomIn != nullptr)
     286           0 :         poFilterGeom = poGeomIn->clone();
     287           0 : }
     288             : 
     289             : /************************************************************************/
     290             : /*                            ResetReading()                            */
     291             : /************************************************************************/
     292             : 
     293           0 : void OGRNTFRasterLayer::ResetReading()
     294             : 
     295             : {
     296           0 :     iCurrentFC = 1;
     297           0 : }
     298             : 
     299             : /************************************************************************/
     300             : /*                           GetNextFeature()                           */
     301             : /************************************************************************/
     302             : 
     303           0 : OGRFeature *OGRNTFRasterLayer::GetNextFeature()
     304             : 
     305             : {
     306           0 :     if (iCurrentFC > static_cast<GIntBig>(poReader->GetRasterXSize()) *
     307           0 :                          poReader->GetRasterYSize())
     308             :     {
     309           0 :         return nullptr;
     310             :     }
     311             : 
     312           0 :     OGRFeature *poFeature = GetFeature(iCurrentFC);
     313             : 
     314             :     int iReqColumn, iReqRow;
     315             : 
     316           0 :     iReqColumn =
     317           0 :         static_cast<int>((iCurrentFC - 1) / poReader->GetRasterYSize());
     318           0 :     iReqRow = static_cast<int>(
     319           0 :         iCurrentFC -
     320           0 :         static_cast<GIntBig>(iReqColumn) * poReader->GetRasterYSize() - 1);
     321             : 
     322           0 :     if (iReqRow + nDEMSample > poReader->GetRasterYSize())
     323             :     {
     324           0 :         iReqRow = 0;
     325           0 :         iReqColumn += nDEMSample;
     326             :     }
     327             :     else
     328             :     {
     329           0 :         iReqRow += nDEMSample;
     330             :     }
     331             : 
     332           0 :     iCurrentFC = static_cast<GIntBig>(iReqColumn) * poReader->GetRasterYSize() +
     333           0 :                  iReqRow + 1;
     334             : 
     335           0 :     return poFeature;
     336             : }
     337             : 
     338             : /************************************************************************/
     339             : /*                             GetFeature()                             */
     340             : /************************************************************************/
     341             : 
     342           0 : OGRFeature *OGRNTFRasterLayer::GetFeature(GIntBig nFeatureId)
     343             : 
     344             : {
     345             :     int iReqColumn, iReqRow;
     346             : 
     347             :     /* -------------------------------------------------------------------- */
     348             :     /*      Is this in the range of legal feature ids (pixels)?             */
     349             :     /* -------------------------------------------------------------------- */
     350           0 :     if (nFeatureId < 1 ||
     351           0 :         nFeatureId > static_cast<GIntBig>(poReader->GetRasterXSize()) *
     352           0 :                          poReader->GetRasterYSize())
     353             :     {
     354           0 :         return nullptr;
     355             :     }
     356             : 
     357             :     /* -------------------------------------------------------------------- */
     358             :     /*      Do we need to load a different column.                          */
     359             :     /* -------------------------------------------------------------------- */
     360           0 :     iReqColumn =
     361           0 :         static_cast<int>((nFeatureId - 1) / poReader->GetRasterYSize());
     362           0 :     iReqRow = static_cast<int>(
     363           0 :         nFeatureId -
     364           0 :         static_cast<GIntBig>(iReqColumn) * poReader->GetRasterYSize() - 1);
     365             : 
     366           0 :     if (iReqColumn != iColumnOffset)
     367             :     {
     368           0 :         iColumnOffset = iReqColumn;
     369           0 :         if (poReader->ReadRasterColumn(iReqColumn, pafColumn) != CE_None)
     370           0 :             return nullptr;
     371             :     }
     372           0 :     if (iReqRow < 0 || iReqRow >= poReader->GetRasterYSize())
     373           0 :         return nullptr;
     374             : 
     375             :     /* -------------------------------------------------------------------- */
     376             :     /*      Create a corresponding feature.                                 */
     377             :     /* -------------------------------------------------------------------- */
     378           0 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     379           0 :     double *padfGeoTransform = poReader->GetGeoTransform();
     380             : 
     381           0 :     poFeature->SetFID(nFeatureId);
     382             : 
     383             :     // NOTE: unusual use of GeoTransform - the pixel origin is the
     384             :     // bottom left corner!
     385           0 :     poFeature->SetGeometryDirectly(
     386           0 :         new OGRPoint(padfGeoTransform[0] + padfGeoTransform[1] * iReqColumn,
     387           0 :                      padfGeoTransform[3] + padfGeoTransform[5] * iReqRow,
     388           0 :                      pafColumn[iReqRow]));
     389           0 :     poFeature->SetField(0, pafColumn[iReqRow]);
     390             : 
     391           0 :     return poFeature;
     392             : }
     393             : 
     394             : /************************************************************************/
     395             : /*                          GetFeatureCount()                           */
     396             : /*                                                                      */
     397             : /*      If a spatial filter is in effect, we turn control over to       */
     398             : /*      the generic counter.  Otherwise we return the total count.      */
     399             : /*      Eventually we should consider implementing a more efficient     */
     400             : /*      way of counting features matching a spatial query.              */
     401             : /************************************************************************/
     402             : 
     403           0 : GIntBig OGRNTFRasterLayer::GetFeatureCount(CPL_UNUSED int bForce)
     404             : {
     405           0 :     return nFeatureCount;
     406             : }
     407             : 
     408             : /************************************************************************/
     409             : /*                           TestCapability()                           */
     410             : /************************************************************************/
     411             : 
     412           0 : int OGRNTFRasterLayer::TestCapability(const char *pszCap)
     413             : 
     414             : {
     415           0 :     if (EQUAL(pszCap, OLCRandomRead))
     416           0 :         return TRUE;
     417             : 
     418           0 :     else if (EQUAL(pszCap, OLCFastFeatureCount))
     419           0 :         return TRUE;
     420             : 
     421           0 :     return FALSE;
     422             : }

Generated by: LCOV version 1.14