LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_rasterize.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 189 193 97.9 %
Date: 2026-02-14 05:03:47 Functions: 4 4 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             : #include "gdalalg_raster_write.h"
      17             : 
      18             : #include "cpl_conv.h"
      19             : #include "gdal_priv.h"
      20             : #include "gdal_utils.h"
      21             : 
      22             : //! @cond Doxygen_Suppress
      23             : 
      24             : #ifndef _
      25             : #define _(x) (x)
      26             : #endif
      27             : 
      28             : /************************************************************************/
      29             : /*     GDALVectorRasterizeAlgorithm::GDALVectorRasterizeAlgorithm()     */
      30             : /************************************************************************/
      31             : 
      32          75 : GDALVectorRasterizeAlgorithm::GDALVectorRasterizeAlgorithm(bool bStandaloneStep)
      33             :     : GDALPipelineStepAlgorithm(
      34             :           NAME, DESCRIPTION, HELP_URL,
      35           0 :           ConstructorOptions()
      36          75 :               .SetStandaloneStep(bStandaloneStep)
      37         150 :               .SetOutputFormatCreateCapability(GDAL_DCAP_CREATE))
      38             : {
      39          75 :     AddProgressArg();
      40          75 :     if (bStandaloneStep)
      41             :     {
      42          60 :         AddOutputFormatArg(&m_format)
      43             :             .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
      44         240 :                              {GDAL_DCAP_RASTER, GDAL_DCAP_CREATE})
      45         120 :             .AddMetadataItem(GAAMDI_VRT_COMPATIBLE, {"false"});
      46          60 :         AddOpenOptionsArg(&m_openOptions);
      47          60 :         AddInputFormatsArg(&m_inputFormats)
      48         120 :             .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_VECTOR});
      49          60 :         AddInputDatasetArg(&m_inputDataset, GDAL_OF_VECTOR)
      50          60 :             .SetMinCount(1)
      51          60 :             .SetMaxCount(1);
      52          60 :         AddOutputDatasetArg(&m_outputDataset, GDAL_OF_RASTER)
      53          60 :             .SetDatasetInputFlags(GADV_NAME | GADV_OBJECT);
      54          60 :         AddCreationOptionsArg(&m_creationOptions);
      55          60 :         AddOverwriteArg(&m_overwrite);
      56             :     }
      57             :     else
      58             :     {
      59          15 :         AddVectorHiddenInputDatasetArg();
      60             :     }
      61             : 
      62          75 :     AddBandArg(&m_bands, _("The band(s) to burn values into (1-based index)"));
      63         150 :     AddArg("invert", 0, _("Invert the rasterization"), &m_invert)
      64          75 :         .SetDefault(false);
      65             :     AddArg("all-touched", 0, _("Enables the ALL_TOUCHED rasterization option"),
      66          75 :            &m_allTouched);
      67          75 :     AddArg("burn", 0, _("Burn value"), &m_burnValues);
      68          75 :     AddArg("attribute-name", 'a', _("Attribute name"), &m_attributeName);
      69             :     AddArg("3d", 0,
      70             :            _("Indicates that a burn value should be extracted from the Z"
      71             :              " values of the feature"),
      72          75 :            &m_3d);
      73          75 :     AddLayerNameArg(&m_layerName).SetMutualExclusionGroup("layer-name-or-sql");
      74          75 :     AddArg("where", 0, _("SQL where clause"), &m_where);
      75         150 :     AddArg("sql", 0, _("SQL select statement"), &m_sql)
      76          75 :         .SetMutualExclusionGroup("layer-name-or-sql");
      77          75 :     AddArg("dialect", 0, _("SQL dialect"), &m_dialect);
      78             :     AddArg("nodata", 0, _("Assign a specified nodata value to output bands"),
      79          75 :            &m_nodata);
      80             :     AddArg("init", 0, _("Pre-initialize output bands with specified value"),
      81          75 :            &m_initValues);
      82         150 :     AddArg("crs", 0, _("Override the projection for the output file"), &m_srs)
      83         150 :         .AddHiddenAlias("srs")
      84          75 :         .SetIsCRSArg(/*noneAllowed=*/false);
      85             :     AddArg("transformer-option", 0,
      86             :            _("Set a transformer option suitable to pass to "
      87             :              "GDALCreateGenImgProjTransformer2"),
      88         150 :            &m_transformerOption)
      89          75 :         .SetMetaVar("<NAME>=<VALUE>");
      90             :     AddArg("extent", 0, _("Set the target georeferenced extent"),
      91         150 :            &m_targetExtent)
      92          75 :         .SetMinCount(4)
      93          75 :         .SetMaxCount(4)
      94          75 :         .SetRepeatedArgAllowed(false)
      95          75 :         .SetMetaVar("<xmin>,<ymin>,<xmax>,<ymax>");
      96         150 :     AddArg("resolution", 0, _("Set the target resolution"), &m_targetResolution)
      97          75 :         .SetMinCount(2)
      98          75 :         .SetMaxCount(2)
      99          75 :         .SetRepeatedArgAllowed(false)
     100         150 :         .SetMetaVar("<xres>,<yres>")
     101          75 :         .SetMutualExclusionGroup("size-or-resolution");
     102             :     AddArg("target-aligned-pixels", 0,
     103             :            _("(target aligned pixels) Align the coordinates of the extent of "
     104             :              "the output file to the values of the resolution"),
     105         150 :            &m_tap)
     106          75 :         .AddAlias("tap");
     107             :     AddArg("size", 0, _("Set the target size in pixels and lines"),
     108         150 :            &m_targetSize)
     109          75 :         .SetMinCount(2)
     110          75 :         .SetMaxCount(2)
     111          75 :         .SetRepeatedArgAllowed(false)
     112         150 :         .SetMetaVar("<xsize>,<ysize>")
     113          75 :         .SetMutualExclusionGroup("size-or-resolution");
     114          75 :     AddOutputDataTypeArg(&m_outputType);
     115             :     AddArg("optimization", 0,
     116             :            _("Force the algorithm used (results are identical)"),
     117         150 :            &m_optimization)
     118          75 :         .SetChoices("AUTO", "RASTER", "VECTOR")
     119          75 :         .SetDefault("AUTO");
     120             : 
     121          75 :     if (bStandaloneStep)
     122             :     {
     123         120 :         auto &addArg = AddArg("add", 0, _("Add to existing raster"), &m_add)
     124          60 :                            .SetDefault(false);
     125          60 :         auto &updateArg = AddUpdateArg(&m_update);
     126             :         addArg.AddValidationAction(
     127           3 :             [&updateArg]()
     128             :             {
     129           3 :                 updateArg.Set(true);
     130           3 :                 return true;
     131          60 :             });
     132             :     }
     133          75 : }
     134             : 
     135             : /************************************************************************/
     136             : /*               GDALVectorRasterizeAlgorithm::RunStep()                */
     137             : /************************************************************************/
     138             : 
     139          48 : bool GDALVectorRasterizeAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
     140             : {
     141          48 :     auto poSrcDS = m_inputDataset[0].GetDatasetRef();
     142          48 :     CPLAssert(poSrcDS);
     143             : 
     144          96 :     CPLStringList aosOptions;
     145             : 
     146          48 :     if (m_bands.size())
     147             :     {
     148          72 :         for (int band : m_bands)
     149             :         {
     150          54 :             aosOptions.AddString("-b");
     151          54 :             aosOptions.AddString(CPLSPrintf("%d", band));
     152             :         }
     153             :     }
     154             : 
     155          48 :     if (m_invert)
     156             :     {
     157           1 :         aosOptions.AddString("-i");
     158             :     }
     159             : 
     160          48 :     if (m_allTouched)
     161             :     {
     162          31 :         aosOptions.AddString("-at");
     163             :     }
     164             : 
     165          48 :     if (m_burnValues.size())
     166             :     {
     167         138 :         for (double burnValue : m_burnValues)
     168             :         {
     169          98 :             aosOptions.AddString("-burn");
     170          98 :             aosOptions.AddString(CPLSPrintf("%.17g", burnValue));
     171             :         }
     172             :     }
     173             : 
     174          48 :     if (!m_attributeName.empty())
     175             :     {
     176           5 :         aosOptions.AddString("-a");
     177           5 :         aosOptions.AddString(m_attributeName.c_str());
     178             :     }
     179             : 
     180          48 :     if (m_3d)
     181             :     {
     182           2 :         aosOptions.AddString("-3d");
     183             :     }
     184             : 
     185          48 :     if (m_add)
     186             :     {
     187           1 :         aosOptions.AddString("-add");
     188             :         // Implies update
     189           1 :         m_update = true;
     190             :     }
     191             : 
     192          48 :     if (!m_layerName.empty())
     193             :     {
     194          22 :         aosOptions.AddString("-l");
     195          22 :         aosOptions.AddString(m_layerName.c_str());
     196             :     }
     197             : 
     198          48 :     if (!m_where.empty())
     199             :     {
     200           1 :         aosOptions.AddString("-where");
     201           1 :         aosOptions.AddString(m_where.c_str());
     202             :     }
     203             : 
     204          48 :     if (!m_sql.empty())
     205             :     {
     206           7 :         aosOptions.AddString("-sql");
     207           7 :         aosOptions.AddString(m_sql.c_str());
     208             :     }
     209             : 
     210          48 :     if (!m_dialect.empty())
     211             :     {
     212           3 :         aosOptions.AddString("-dialect");
     213           3 :         aosOptions.AddString(m_dialect.c_str());
     214             :     }
     215             : 
     216          96 :     std::string outputFilename;
     217          48 :     if (m_standaloneStep)
     218             :     {
     219          47 :         outputFilename = m_outputDataset.GetName();
     220          47 :         if (!m_format.empty())
     221             :         {
     222           5 :             aosOptions.AddString("-of");
     223           5 :             aosOptions.AddString(m_format.c_str());
     224             :         }
     225             : 
     226          48 :         for (const std::string &co : m_creationOptions)
     227             :         {
     228           1 :             aosOptions.AddString("-co");
     229           1 :             aosOptions.AddString(co.c_str());
     230             :         }
     231             :     }
     232             :     else
     233             :     {
     234           1 :         outputFilename = CPLGenerateTempFilenameSafe("_rasterize.tif");
     235             : 
     236           1 :         aosOptions.AddString("-of");
     237           1 :         aosOptions.AddString("GTiff");
     238             : 
     239           1 :         aosOptions.AddString("-co");
     240           1 :         aosOptions.AddString("TILED=YES");
     241             :     }
     242             : 
     243          48 :     if (!std::isnan(m_nodata))
     244             :     {
     245           2 :         if (m_update)
     246             :         {
     247           1 :             ReportError(
     248             :                 CE_Failure, CPLE_AppDefined,
     249             :                 "Cannot specify --nodata when updating an existing raster.");
     250           1 :             return false;
     251             :         }
     252           1 :         aosOptions.AddString("-a_nodata");
     253           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_nodata));
     254             :     }
     255             : 
     256          47 :     if (m_initValues.size())
     257             :     {
     258          36 :         for (double initValue : m_initValues)
     259             :         {
     260          27 :             aosOptions.AddString("-init");
     261          27 :             aosOptions.AddString(CPLSPrintf("%.17g", initValue));
     262             :         }
     263             :     }
     264             : 
     265          47 :     if (!m_srs.empty())
     266             :     {
     267           2 :         if (m_update)
     268             :         {
     269           1 :             ReportError(
     270             :                 CE_Failure, CPLE_AppDefined,
     271             :                 "Cannot specify --crs when updating an existing raster.");
     272           1 :             return false;
     273             :         }
     274           1 :         aosOptions.AddString("-a_srs");
     275           1 :         aosOptions.AddString(m_srs.c_str());
     276             :     }
     277             : 
     278          46 :     if (m_transformerOption.size())
     279             :     {
     280           0 :         for (const auto &to : m_transformerOption)
     281             :         {
     282           0 :             aosOptions.AddString("-to");
     283           0 :             aosOptions.AddString(to.c_str());
     284             :         }
     285             :     }
     286             : 
     287          46 :     if (m_targetExtent.size())
     288             :     {
     289           1 :         aosOptions.AddString("-te");
     290           5 :         for (double targetExtent : m_targetExtent)
     291             :         {
     292           4 :             aosOptions.AddString(CPLSPrintf("%.17g", targetExtent));
     293             :         }
     294             :     }
     295             : 
     296          46 :     if (m_tap)
     297             :     {
     298           1 :         aosOptions.AddString("-tap");
     299             :     }
     300             : 
     301          46 :     if (m_targetResolution.size())
     302             :     {
     303           7 :         if (m_update)
     304             :         {
     305           1 :             ReportError(CE_Failure, CPLE_AppDefined,
     306             :                         "Cannot specify --resolution when updating an existing "
     307             :                         "raster.");
     308           1 :             return false;
     309             :         }
     310           6 :         aosOptions.AddString("-tr");
     311          18 :         for (double targetResolution : m_targetResolution)
     312             :         {
     313          12 :             aosOptions.AddString(CPLSPrintf("%.17g", targetResolution));
     314             :         }
     315             :     }
     316          39 :     else if (m_targetSize.size())
     317             :     {
     318          20 :         if (m_update)
     319             :         {
     320           1 :             ReportError(
     321             :                 CE_Failure, CPLE_AppDefined,
     322             :                 "Cannot specify --size when updating an existing raster.");
     323           1 :             return false;
     324             :         }
     325          19 :         aosOptions.AddString("-ts");
     326          57 :         for (int targetSize : m_targetSize)
     327             :         {
     328          38 :             aosOptions.AddString(CPLSPrintf("%d", targetSize));
     329             :         }
     330             :     }
     331          19 :     else if (m_outputDataset.GetDatasetRef() == nullptr)
     332             :     {
     333           3 :         ReportError(
     334             :             CE_Failure, CPLE_AppDefined,
     335             :             "Must specify output resolution (--resolution) or size (--size) "
     336             :             "when writing rasterized features to a new dataset.");
     337           3 :         return false;
     338             :     }
     339             : 
     340          41 :     if (!m_outputType.empty())
     341             :     {
     342           2 :         if (m_update)
     343             :         {
     344           1 :             ReportError(CE_Failure, CPLE_AppDefined,
     345             :                         "Cannot specify --output-data-type when updating an "
     346             :                         "existing raster.");
     347           1 :             return false;
     348             :         }
     349           1 :         aosOptions.AddString("-ot");
     350           1 :         aosOptions.AddString(m_outputType.c_str());
     351             :     }
     352             : 
     353          40 :     if (!m_optimization.empty())
     354             :     {
     355          40 :         aosOptions.AddString("-optim");
     356          40 :         aosOptions.AddString(m_optimization.c_str());
     357             :     }
     358             : 
     359          40 :     bool bOK = false;
     360             :     std::unique_ptr<GDALRasterizeOptions, decltype(&GDALRasterizeOptionsFree)>
     361             :         psOptions{GDALRasterizeOptionsNew(aosOptions.List(), nullptr),
     362          40 :                   GDALRasterizeOptionsFree};
     363          40 :     if (psOptions)
     364             :     {
     365          37 :         GDALRasterizeOptionsSetProgress(psOptions.get(), ctxt.m_pfnProgress,
     366             :                                         ctxt.m_pProgressData);
     367             : 
     368             :         GDALDatasetH hDstDS =
     369          37 :             GDALDataset::ToHandle(m_outputDataset.GetDatasetRef());
     370             : 
     371          37 :         GDALDatasetH hSrcDS = GDALDataset::ToHandle(poSrcDS);
     372             : 
     373          37 :         auto poRetDS = GDALDataset::FromHandle(GDALRasterize(
     374          37 :             outputFilename.c_str(), hDstDS, hSrcDS, psOptions.get(), nullptr));
     375          37 :         bOK = poRetDS != nullptr;
     376             : 
     377          37 :         if (!hDstDS)
     378             :         {
     379          24 :             if (!m_standaloneStep && poRetDS)
     380             :             {
     381           1 :                 VSIUnlink(outputFilename.c_str());
     382           1 :                 poRetDS->MarkSuppressOnClose();
     383             :             }
     384             : 
     385          24 :             m_outputDataset.Set(std::unique_ptr<GDALDataset>(poRetDS));
     386             :         }
     387             :     }
     388             : 
     389          40 :     return bOK;
     390             : }
     391             : 
     392             : /************************************************************************/
     393             : /*               GDALVectorRasterizeAlgorithm::RunImpl()                */
     394             : /************************************************************************/
     395             : 
     396          47 : bool GDALVectorRasterizeAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
     397             :                                            void *pProgressData)
     398             : {
     399          47 :     GDALPipelineStepRunContext stepCtxt;
     400          47 :     stepCtxt.m_pfnProgress = pfnProgress;
     401          47 :     stepCtxt.m_pProgressData = pProgressData;
     402          47 :     return RunPreStepPipelineValidations() && RunStep(stepCtxt);
     403             : }
     404             : 
     405             : GDALVectorRasterizeAlgorithmStandalone::
     406             :     ~GDALVectorRasterizeAlgorithmStandalone() = default;
     407             : 
     408             : //! @endcond

Generated by: LCOV version 1.14