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

Generated by: LCOV version 1.14