LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_rasterize.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 158 179 88.3 %
Date: 2025-03-28 11:40:40 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "vector rasterize" subcommand
       5             :  * Author:   Alessandro Pasotti <elpaso at itopen dot it>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2025, Alessandro Pasotti <elpaso at itopen dot it>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include <cmath>
      14             : 
      15             : #include "gdalalg_vector_rasterize.h"
      16             : 
      17             : #include "cpl_conv.h"
      18             : #include "gdal_priv.h"
      19             : #include "gdal_utils.h"
      20             : 
      21             : //! @cond Doxygen_Suppress
      22             : 
      23             : #ifndef _
      24             : #define _(x) (x)
      25             : #endif
      26             : 
      27             : /************************************************************************/
      28             : /*          GDALVectorRasterizeAlgorithm::GDALVectorRasterizeAlgorithm()    */
      29             : /************************************************************************/
      30             : 
      31          31 : GDALVectorRasterizeAlgorithm::GDALVectorRasterizeAlgorithm()
      32          31 :     : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
      33             : {
      34          31 :     AddProgressArg();
      35          31 :     AddOutputFormatArg(&m_outputFormat)
      36             :         .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
      37          93 :                          {GDAL_DCAP_VECTOR, GDAL_DCAP_CREATE});
      38          31 :     AddOpenOptionsArg(&m_openOptions);
      39          31 :     AddInputFormatsArg(&m_inputFormats)
      40          62 :         .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_VECTOR});
      41          31 :     AddInputDatasetArg(&m_inputDataset, GDAL_OF_VECTOR);
      42          31 :     AddOutputDatasetArg(&m_outputDataset, GDAL_OF_RASTER);
      43          31 :     m_outputDataset.SetInputFlags(GADV_NAME | GADV_OBJECT);
      44          31 :     AddCreationOptionsArg(&m_datasetCreationOptions);
      45          31 :     AddArg("band", 'b', _("The band(s) to burn values into"), &m_bands);
      46          62 :     AddArg("invert", 0, _("Invert the rasterization"), &m_invert)
      47          31 :         .SetDefault(false);
      48             :     AddArg("all-touched", 0, _("Enables the ALL_TOUCHED rasterization option"),
      49          31 :            &m_allTouched);
      50          31 :     AddArg("burn", 0, _("Burn value"), &m_burnValues);
      51          31 :     AddArg("attribute-name", 'a', _("Attribute name"), &m_attributeName);
      52             :     AddArg("3d", 0,
      53             :            _("Indicates that a burn value should be extracted from the Z"
      54             :              " values of the feature"),
      55          31 :            &m_3d);
      56          31 :     AddArg("add", 0, _("Add to existing raster"), &m_add).SetDefault(false);
      57          62 :     AddArg("layer-name", 'l', _("Layer name"), &m_layerName)
      58          62 :         .AddAlias("layer")
      59          31 :         .SetMutualExclusionGroup("layer-name-or-sql");
      60          31 :     AddArg("where", 0, _("SQL where clause"), &m_where);
      61          62 :     AddArg("sql", 0, _("SQL select statement"), &m_sql)
      62          31 :         .SetMutualExclusionGroup("layer-name-or-sql");
      63          31 :     AddArg("dialect", 0, _("SQL dialect"), &m_dialect);
      64             :     AddArg("nodata", 0, _("Assign a specified nodata value to output bands"),
      65          31 :            &m_nodata);
      66             :     AddArg("init", 0, _("Pre-initialize output bands with specified value"),
      67          31 :            &m_initValues);
      68          62 :     AddArg("crs", 0, _("Override the projection for the output file"), &m_srs)
      69          62 :         .AddHiddenAlias("srs")
      70          31 :         .SetIsCRSArg(/*noneAllowed=*/false);
      71             :     AddArg("transformer-option", 0,
      72             :            _("Set a transformer option suitable to pass to "
      73             :              "GDALCreateGenImgProjTransformer2"),
      74          62 :            &m_transformerOption)
      75          31 :         .SetMetaVar("<NAME>=<VALUE>");
      76             :     AddArg("extent", 0, _("Set the target georeferenced extent"),
      77          62 :            &m_targetExtent)
      78          31 :         .SetMinCount(4)
      79          31 :         .SetMaxCount(4)
      80          31 :         .SetRepeatedArgAllowed(false)
      81          31 :         .SetMetaVar("<xmin>,<ymin>,<xmax>,<ymax>");
      82          62 :     AddArg("resolution", 0, _("Set the target resolution"), &m_targetResolution)
      83          31 :         .SetMinCount(2)
      84          31 :         .SetMaxCount(2)
      85          31 :         .SetRepeatedArgAllowed(false)
      86          62 :         .SetMetaVar("<xres>,<yres>")
      87          31 :         .SetMutualExclusionGroup("size-or-resolution");
      88             :     AddArg("target-aligned-pixels", 0,
      89             :            _("(target aligned pixels) Align the coordinates of the extent of "
      90             :              "the output file to the values of the resolution"),
      91          62 :            &m_tap)
      92          31 :         .AddAlias("tap");
      93             :     AddArg("size", 0, _("Set the target size in pixels and lines"),
      94          62 :            &m_targetSize)
      95          31 :         .SetMinCount(2)
      96          31 :         .SetMaxCount(2)
      97          31 :         .SetRepeatedArgAllowed(false)
      98          62 :         .SetMetaVar("<xsize>,<ysize>")
      99          31 :         .SetMutualExclusionGroup("size-or-resolution");
     100          31 :     AddOutputDataTypeArg(&m_outputType);
     101             :     AddArg("optimization", 0,
     102             :            _("Force the algorithm used (results are identical)"),
     103          62 :            &m_optimization)
     104          31 :         .SetChoices("AUTO", "RASTER", "VECTOR")
     105          31 :         .SetDefault("AUTO");
     106          31 :     AddUpdateArg(&m_update);
     107          31 :     AddOverwriteArg(&m_overwrite);
     108          31 : }
     109             : 
     110             : /************************************************************************/
     111             : /*                  GDALVectorRasterizeAlgorithm::RunImpl()               */
     112             : /************************************************************************/
     113             : 
     114          26 : bool GDALVectorRasterizeAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
     115             :                                            void *pProgressData)
     116             : {
     117          26 :     CPLAssert(m_inputDataset.GetDatasetRef());
     118             : 
     119          52 :     CPLStringList aosOptions;
     120             : 
     121          26 :     if (pfnProgress && pfnProgress != GDALDummyProgress)
     122             :     {
     123           0 :         aosOptions.AddString("-progress");
     124             :     }
     125             : 
     126          26 :     if (m_bands.size())
     127             :     {
     128          76 :         for (int band : m_bands)
     129             :         {
     130          57 :             aosOptions.AddString("-b");
     131          57 :             aosOptions.AddString(CPLSPrintf("%d", band));
     132             :         }
     133             :     }
     134             : 
     135          26 :     if (m_invert)
     136             :     {
     137           1 :         aosOptions.AddString("-i");
     138             :     }
     139             : 
     140          26 :     if (m_allTouched)
     141             :     {
     142          26 :         aosOptions.AddString("-at");
     143             :     }
     144             : 
     145          26 :     if (m_burnValues.size())
     146             :     {
     147          92 :         for (double burnValue : m_burnValues)
     148             :         {
     149          69 :             aosOptions.AddString("-burn");
     150          69 :             aosOptions.AddString(CPLSPrintf("%.17g", burnValue));
     151             :         }
     152             :     }
     153             : 
     154          26 :     if (!m_attributeName.empty())
     155             :     {
     156           3 :         aosOptions.AddString("-a");
     157           3 :         aosOptions.AddString(m_attributeName.c_str());
     158             :     }
     159             : 
     160          26 :     if (m_3d)
     161             :     {
     162           2 :         aosOptions.AddString("-3d");
     163             :     }
     164             : 
     165          26 :     if (m_add)
     166             :     {
     167           1 :         aosOptions.AddString("-add");
     168             :         // Implies update
     169           1 :         m_update = true;
     170             :     }
     171             : 
     172          26 :     if (!m_layerName.empty())
     173             :     {
     174          20 :         aosOptions.AddString("-l");
     175          20 :         aosOptions.AddString(m_layerName.c_str());
     176             :     }
     177             : 
     178          26 :     if (!m_where.empty())
     179             :     {
     180           1 :         aosOptions.AddString("-where");
     181           1 :         aosOptions.AddString(m_where.c_str());
     182             :     }
     183             : 
     184          26 :     if (!m_sql.empty())
     185             :     {
     186           4 :         aosOptions.AddString("-sql");
     187           4 :         aosOptions.AddString(m_sql.c_str());
     188             :     }
     189             : 
     190          26 :     if (!m_dialect.empty())
     191             :     {
     192           3 :         aosOptions.AddString("-dialect");
     193           3 :         aosOptions.AddString(m_dialect.c_str());
     194             :     }
     195             : 
     196          26 :     if (!m_outputFormat.empty())
     197             :     {
     198           0 :         aosOptions.AddString("-of");
     199           0 :         aosOptions.AddString(m_outputFormat.c_str());
     200             :     }
     201             : 
     202          26 :     if (!std::isnan(m_nodata))
     203             :     {
     204           1 :         aosOptions.AddString("-a_nodata");
     205           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_nodata));
     206             :     }
     207             : 
     208          26 :     if (m_initValues.size())
     209             :     {
     210          12 :         for (double initValue : m_initValues)
     211             :         {
     212           9 :             aosOptions.AddString("-init");
     213           9 :             aosOptions.AddString(CPLSPrintf("%.17g", initValue));
     214             :         }
     215             :     }
     216             : 
     217          26 :     if (!m_srs.empty())
     218             :     {
     219           1 :         aosOptions.AddString("-a_srs");
     220           1 :         aosOptions.AddString(m_srs.c_str());
     221             :     }
     222             : 
     223          26 :     if (m_transformerOption.size())
     224             :     {
     225           0 :         for (const auto &to : m_transformerOption)
     226             :         {
     227           0 :             aosOptions.AddString("-to");
     228           0 :             aosOptions.AddString(to.c_str());
     229             :         }
     230             :     }
     231             : 
     232          26 :     for (const auto &co : m_datasetCreationOptions)
     233             :     {
     234           0 :         aosOptions.AddString("-dsco");
     235           0 :         aosOptions.AddString(co.c_str());
     236             :     }
     237             : 
     238          26 :     if (m_targetExtent.size())
     239             :     {
     240           1 :         aosOptions.AddString("-te");
     241           5 :         for (double targetExtent : m_targetExtent)
     242             :         {
     243           4 :             aosOptions.AddString(CPLSPrintf("%.17g", targetExtent));
     244             :         }
     245             :     }
     246             : 
     247          26 :     if (m_targetResolution.size())
     248             :     {
     249           6 :         aosOptions.AddString("-tr");
     250          18 :         for (double targetResolution : m_targetResolution)
     251             :         {
     252          12 :             aosOptions.AddString(CPLSPrintf("%.17g", targetResolution));
     253             :         }
     254             :     }
     255             : 
     256          26 :     if (m_tap)
     257             :     {
     258           1 :         aosOptions.AddString("-tap");
     259             :     }
     260             : 
     261          26 :     if (m_targetSize.size())
     262             :     {
     263           2 :         aosOptions.AddString("-ts");
     264           6 :         for (int targetSize : m_targetSize)
     265             :         {
     266           4 :             aosOptions.AddString(CPLSPrintf("%d", targetSize));
     267             :         }
     268             :     }
     269             : 
     270          26 :     if (!m_outputType.empty())
     271             :     {
     272           0 :         aosOptions.AddString("-ot");
     273           0 :         aosOptions.AddString(m_outputType.c_str());
     274             :     }
     275             : 
     276          26 :     if (!m_optimization.empty())
     277             :     {
     278          26 :         aosOptions.AddString("-optim");
     279          26 :         aosOptions.AddString(m_optimization.c_str());
     280             :     }
     281             : 
     282          26 :     if (m_openOptions.size())
     283             :     {
     284           0 :         for (const auto &oo : m_openOptions)
     285             :         {
     286           0 :             aosOptions.AddString("-oo");
     287           0 :             aosOptions.AddString(oo.c_str());
     288             :         }
     289             :     }
     290             : 
     291             :     std::unique_ptr<GDALRasterizeOptions, decltype(&GDALRasterizeOptionsFree)>
     292             :         psOptions{GDALRasterizeOptionsNew(aosOptions.List(), nullptr),
     293          52 :                   GDALRasterizeOptionsFree};
     294             : 
     295          26 :     if (!psOptions)
     296             :     {
     297           4 :         return false;
     298             :     }
     299             : 
     300          22 :     GDALRasterizeOptionsSetProgress(psOptions.get(), pfnProgress,
     301             :                                     pProgressData);
     302             : 
     303             :     GDALDatasetH hDstDS =
     304          22 :         GDALDataset::ToHandle(m_outputDataset.GetDatasetRef());
     305             : 
     306          22 :     const bool dstDSWasNull{!hDstDS};
     307             : 
     308          22 :     if (!hDstDS && !m_outputDataset.GetName().empty())
     309             :     {
     310             :         VSIStatBufL sStat;
     311          10 :         bool fileExists{VSIStatL(m_outputDataset.GetName().c_str(), &sStat) ==
     312          10 :                         0};
     313             : 
     314             :         {
     315          20 :             CPLErrorStateBackuper oCPLErrorHandlerPusher(CPLQuietErrorHandler);
     316          10 :             hDstDS = GDALOpenEx(m_outputDataset.GetName().c_str(),
     317             :                                 GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR |
     318             :                                     GDAL_OF_UPDATE,
     319             :                                 nullptr, nullptr, nullptr);
     320          10 :             CPLErrorReset();
     321             :         }
     322             : 
     323          10 :         if (hDstDS)
     324             :         {
     325           2 :             if (!m_overwrite && !m_update)
     326             :             {
     327           1 :                 CPLError(CE_Failure, CPLE_AppDefined,
     328             :                          "Dataset '%s' already exists. Specify the --overwrite "
     329             :                          "option to overwrite it or the --update option to "
     330             :                          "update it.",
     331           1 :                          m_outputDataset.GetName().c_str());
     332           1 :                 GDALClose(hDstDS);
     333           1 :                 return false;
     334             :             }
     335           1 :             else if (fileExists && m_overwrite)
     336             :             {
     337             :                 // Delete the existing file
     338             :                 CPLErrorStateBackuper oCPLErrorHandlerPusher(
     339           0 :                     CPLQuietErrorHandler);
     340           0 :                 if (VSIUnlink(m_outputDataset.GetName().c_str()) != 0)
     341             :                 {
     342           0 :                     CPLError(CE_Failure, CPLE_AppDefined,
     343             :                              "Failed to delete existing dataset '%s'.",
     344           0 :                              m_outputDataset.GetName().c_str());
     345           0 :                     GDALClose(hDstDS);
     346           0 :                     return false;
     347             :                 }
     348             :             }
     349             :         }
     350             :     }
     351             : 
     352          21 :     GDALDatasetH hSrcDS = GDALDataset::ToHandle(m_inputDataset.GetDatasetRef());
     353          21 :     auto poRetDS = GDALDataset::FromHandle(
     354          21 :         GDALRasterize(m_outputDataset.GetName().c_str(), hDstDS, hSrcDS,
     355          21 :                       psOptions.get(), nullptr));
     356             : 
     357          21 :     if (!poRetDS)
     358           2 :         return false;
     359             : 
     360          19 :     if (!hDstDS)
     361             :     {
     362           7 :         m_outputDataset.Set(std::unique_ptr<GDALDataset>(poRetDS));
     363             :     }
     364          12 :     else if (dstDSWasNull)
     365             :     {
     366           1 :         if (GDALClose(hDstDS) != CE_None)
     367             :         {
     368           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     369             :                      "Failed to close output dataset");
     370           0 :             return false;
     371             :         }
     372             :     }
     373             : 
     374          19 :     return true;
     375             : }
     376             : 
     377             : //! @endcond

Generated by: LCOV version 1.14