LCOV - code coverage report
Current view: top level - alg - polygonize.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 135 156 86.5 %
Date: 2024-05-04 12:52:34 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * Project:  GDAL
       3             :  * Purpose:  Raster to Polygon Converter
       4             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       5             :  *
       6             :  ******************************************************************************
       7             :  * Copyright (c) 2008, Frank Warmerdam
       8             :  * Copyright (c) 2009-2020, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_port.h"
      30             : #include "gdal_alg.h"
      31             : 
      32             : #include <stddef.h>
      33             : #include <stdio.h>
      34             : #include <cstdlib>
      35             : #include <string.h>
      36             : 
      37             : #include <algorithm>
      38             : #include <limits>
      39             : #include <map>
      40             : #include <memory>
      41             : #include <utility>
      42             : #include <vector>
      43             : 
      44             : #include "gdal_alg_priv.h"
      45             : #include "gdal.h"
      46             : #include "ogr_api.h"
      47             : #include "ogr_core.h"
      48             : #include "cpl_conv.h"
      49             : #include "cpl_error.h"
      50             : #include "cpl_progress.h"
      51             : #include "cpl_string.h"
      52             : #include "cpl_vsi.h"
      53             : 
      54             : #include "polygonize_polygonizer.h"
      55             : 
      56             : using namespace gdal::polygonizer;
      57             : 
      58             : /************************************************************************/
      59             : /*                          GPMaskImageData()                           */
      60             : /*                                                                      */
      61             : /*      Mask out image pixels to a special nodata value if the mask     */
      62             : /*      band is zero.                                                   */
      63             : /************************************************************************/
      64             : 
      65             : template <class DataType>
      66        2720 : static CPLErr GPMaskImageData(GDALRasterBandH hMaskBand, GByte *pabyMaskLine,
      67             :                               int iY, int nXSize, DataType *panImageLine)
      68             : 
      69             : {
      70        2720 :     const CPLErr eErr = GDALRasterIO(hMaskBand, GF_Read, 0, iY, nXSize, 1,
      71             :                                      pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0);
      72        2720 :     if (eErr != CE_None)
      73           0 :         return eErr;
      74             : 
      75      840682 :     for (int i = 0; i < nXSize; i++)
      76             :     {
      77      837962 :         if (pabyMaskLine[i] == 0)
      78      105692 :             panImageLine[i] = GP_NODATA_MARKER;
      79             :     }
      80             : 
      81        2720 :     return CE_None;
      82             : }
      83             : 
      84             : /************************************************************************/
      85             : /*                           GDALPolygonizeT()                          */
      86             : /************************************************************************/
      87             : 
      88             : template <class DataType, class EqualityTest>
      89          52 : static CPLErr GDALPolygonizeT(GDALRasterBandH hSrcBand,
      90             :                               GDALRasterBandH hMaskBand, OGRLayerH hOutLayer,
      91             :                               int iPixValField, char **papszOptions,
      92             :                               GDALProgressFunc pfnProgress, void *pProgressArg,
      93             :                               GDALDataType eDT)
      94             : 
      95             : {
      96          52 :     VALIDATE_POINTER1(hSrcBand, "GDALPolygonize", CE_Failure);
      97          52 :     VALIDATE_POINTER1(hOutLayer, "GDALPolygonize", CE_Failure);
      98             : 
      99          52 :     if (pfnProgress == nullptr)
     100          15 :         pfnProgress = GDALDummyProgress;
     101             : 
     102          52 :     const int nConnectedness =
     103          52 :         CSLFetchNameValue(papszOptions, "8CONNECTED") ? 8 : 4;
     104             : 
     105             :     /* -------------------------------------------------------------------- */
     106             :     /*      Confirm our output layer will support feature creation.         */
     107             :     /* -------------------------------------------------------------------- */
     108          52 :     if (!OGR_L_TestCapability(hOutLayer, OLCSequentialWrite))
     109             :     {
     110           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     111             :                  "Output feature layer does not appear to support creation "
     112             :                  "of features in GDALPolygonize().");
     113           0 :         return CE_Failure;
     114             :     }
     115             : 
     116             :     /* -------------------------------------------------------------------- */
     117             :     /*      Allocate working buffers.                                       */
     118             :     /* -------------------------------------------------------------------- */
     119          52 :     const int nXSize = GDALGetRasterBandXSize(hSrcBand);
     120          52 :     const int nYSize = GDALGetRasterBandYSize(hSrcBand);
     121          52 :     if (nXSize > std::numeric_limits<int>::max() - 2)
     122             :     {
     123           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Too wide raster");
     124           0 :         return CE_Failure;
     125             :     }
     126             : 
     127          52 :     DataType *panLastLineVal =
     128          52 :         static_cast<DataType *>(VSI_MALLOC2_VERBOSE(sizeof(DataType), nXSize));
     129          52 :     DataType *panThisLineVal =
     130          52 :         static_cast<DataType *>(VSI_MALLOC2_VERBOSE(sizeof(DataType), nXSize));
     131          52 :     GInt32 *panLastLineId =
     132          52 :         static_cast<GInt32 *>(VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize));
     133          52 :     GInt32 *panThisLineId =
     134          52 :         static_cast<GInt32 *>(VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize));
     135             : 
     136          52 :     GByte *pabyMaskLine = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
     137             : 
     138          52 :     if (panLastLineVal == nullptr || panThisLineVal == nullptr ||
     139          52 :         panLastLineId == nullptr || panThisLineId == nullptr ||
     140             :         pabyMaskLine == nullptr)
     141             :     {
     142           0 :         CPLFree(panThisLineId);
     143           0 :         CPLFree(panLastLineId);
     144           0 :         CPLFree(panThisLineVal);
     145           0 :         CPLFree(panLastLineVal);
     146           0 :         CPLFree(pabyMaskLine);
     147           0 :         return CE_Failure;
     148             :     }
     149             : 
     150             :     /* -------------------------------------------------------------------- */
     151             :     /*      Get the geotransform, if there is one, so we can convert the    */
     152             :     /*      vectors into georeferenced coordinates.                         */
     153             :     /* -------------------------------------------------------------------- */
     154          52 :     double adfGeoTransform[6] = {0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
     155          52 :     bool bGotGeoTransform = false;
     156             :     const char *pszDatasetForGeoRef =
     157          52 :         CSLFetchNameValue(papszOptions, "DATASET_FOR_GEOREF");
     158          52 :     if (pszDatasetForGeoRef)
     159             :     {
     160           2 :         GDALDatasetH hSrcDS = GDALOpen(pszDatasetForGeoRef, GA_ReadOnly);
     161           2 :         if (hSrcDS)
     162             :         {
     163           2 :             bGotGeoTransform =
     164           2 :                 GDALGetGeoTransform(hSrcDS, adfGeoTransform) == CE_None;
     165           2 :             GDALClose(hSrcDS);
     166             :         }
     167             :     }
     168             :     else
     169             :     {
     170          50 :         GDALDatasetH hSrcDS = GDALGetBandDataset(hSrcBand);
     171          50 :         if (hSrcDS)
     172          20 :             bGotGeoTransform =
     173          20 :                 GDALGetGeoTransform(hSrcDS, adfGeoTransform) == CE_None;
     174             :     }
     175          52 :     if (!bGotGeoTransform)
     176             :     {
     177          30 :         adfGeoTransform[0] = 0;
     178          30 :         adfGeoTransform[1] = 1;
     179          30 :         adfGeoTransform[2] = 0;
     180          30 :         adfGeoTransform[3] = 0;
     181          30 :         adfGeoTransform[4] = 0;
     182          30 :         adfGeoTransform[5] = 1;
     183             :     }
     184             : 
     185             :     /* -------------------------------------------------------------------- */
     186             :     /*      The first pass over the raster is only used to build up the     */
     187             :     /*      polygon id map so we will know in advance what polygons are     */
     188             :     /*      what on the second pass.                                        */
     189             :     /* -------------------------------------------------------------------- */
     190         104 :     GDALRasterPolygonEnumeratorT<DataType, EqualityTest> oFirstEnum(
     191             :         nConnectedness);
     192             : 
     193          52 :     CPLErr eErr = CE_None;
     194             : 
     195        1490 :     for (int iY = 0; eErr == CE_None && iY < nYSize; iY++)
     196             :     {
     197        1438 :         eErr = GDALRasterIO(hSrcBand, GF_Read, 0, iY, nXSize, 1, panThisLineVal,
     198             :                             nXSize, 1, eDT, 0, 0);
     199             : 
     200        1438 :         if (eErr == CE_None && hMaskBand != nullptr)
     201        1360 :             eErr = GPMaskImageData(hMaskBand, pabyMaskLine, iY, nXSize,
     202             :                                    panThisLineVal);
     203             : 
     204        1438 :         if (eErr != CE_None)
     205           0 :             break;
     206             : 
     207        1438 :         if (iY == 0)
     208          52 :             eErr = oFirstEnum.ProcessLine(nullptr, panThisLineVal, nullptr,
     209             :                                           panThisLineId, nXSize)
     210          52 :                        ? CE_None
     211             :                        : CE_Failure;
     212             :         else
     213        1386 :             eErr = oFirstEnum.ProcessLine(panLastLineVal, panThisLineVal,
     214             :                                           panLastLineId, panThisLineId, nXSize)
     215        1386 :                        ? CE_None
     216             :                        : CE_Failure;
     217             : 
     218        1438 :         if (eErr != CE_None)
     219           0 :             break;
     220             : 
     221             :         // Swap lines.
     222        1438 :         std::swap(panLastLineVal, panThisLineVal);
     223        1438 :         std::swap(panLastLineId, panThisLineId);
     224             : 
     225             :         /* --------------------------------------------------------------------
     226             :          */
     227             :         /*      Report progress, and support interrupts. */
     228             :         /* --------------------------------------------------------------------
     229             :          */
     230        1438 :         if (!pfnProgress(0.10 * ((iY + 1) / static_cast<double>(nYSize)), "",
     231             :                          pProgressArg))
     232             :         {
     233           0 :             CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
     234           0 :             eErr = CE_Failure;
     235             :         }
     236             :     }
     237             : 
     238             :     /* -------------------------------------------------------------------- */
     239             :     /*      Make a pass through the maps, ensuring every polygon id         */
     240             :     /*      points to the final id it should use, not an intermediate       */
     241             :     /*      value.                                                          */
     242             :     /* -------------------------------------------------------------------- */
     243          52 :     if (eErr == CE_None)
     244          52 :         oFirstEnum.CompleteMerges();
     245             : 
     246             :     /* -------------------------------------------------------------------- */
     247             :     /*      We will use a new enumerator for the second pass primarily      */
     248             :     /*      so we can preserve the first pass map.                          */
     249             :     /* -------------------------------------------------------------------- */
     250         104 :     GDALRasterPolygonEnumeratorT<DataType, EqualityTest> oSecondEnum(
     251             :         nConnectedness);
     252             : 
     253         104 :     OGRPolygonWriter<DataType> oPolygonWriter{hOutLayer, iPixValField,
     254             :                                               adfGeoTransform};
     255          52 :     Polygonizer<GInt32, DataType> oPolygonizer{-1, &oPolygonWriter};
     256          52 :     TwoArm *paoLastLineArm =
     257          52 :         static_cast<TwoArm *>(VSI_CALLOC_VERBOSE(sizeof(TwoArm), nXSize + 2));
     258          52 :     TwoArm *paoThisLineArm =
     259          52 :         static_cast<TwoArm *>(VSI_CALLOC_VERBOSE(sizeof(TwoArm), nXSize + 2));
     260             : 
     261          52 :     if (paoThisLineArm == nullptr || paoLastLineArm == nullptr)
     262             :     {
     263           0 :         eErr = CE_Failure;
     264             :     }
     265             :     else
     266             :     {
     267        1252 :         for (int i = 0; i < nXSize + 2; ++i)
     268             :         {
     269        1200 :             paoLastLineArm[i].poPolyInside = oPolygonizer.getTheOuterPolygon();
     270             :         }
     271             :     }
     272             : 
     273             :     /* ==================================================================== */
     274             :     /*      Second pass during which we will actually collect polygon       */
     275             :     /*      edges as geometries.                                            */
     276             :     /* ==================================================================== */
     277        1542 :     for (int iY = 0; eErr == CE_None && iY < nYSize + 1; iY++)
     278             :     {
     279             :         /* --------------------------------------------------------------------
     280             :          */
     281             :         /*      Read the image data. */
     282             :         /* --------------------------------------------------------------------
     283             :          */
     284        1490 :         if (iY < nYSize)
     285             :         {
     286        1438 :             eErr = GDALRasterIO(hSrcBand, GF_Read, 0, iY, nXSize, 1,
     287             :                                 panThisLineVal, nXSize, 1, eDT, 0, 0);
     288        1438 :             if (eErr == CE_None && hMaskBand != nullptr)
     289        1360 :                 eErr = GPMaskImageData(hMaskBand, pabyMaskLine, iY, nXSize,
     290             :                                        panThisLineVal);
     291             :         }
     292             : 
     293        1490 :         if (eErr != CE_None)
     294           0 :             continue;
     295             : 
     296             :         /* --------------------------------------------------------------------
     297             :          */
     298             :         /*      Determine what polygon the various pixels belong to (redoing */
     299             :         /*      the same thing done in the first pass above). */
     300             :         /* --------------------------------------------------------------------
     301             :          */
     302        1490 :         if (iY == nYSize)
     303             :         {
     304        1148 :             for (int iX = 0; iX < nXSize; iX++)
     305        1096 :                 panThisLineId[iX] =
     306             :                     decltype(oPolygonizer)::THE_OUTER_POLYGON_ID;
     307             :         }
     308        1438 :         else if (iY == 0)
     309             :         {
     310          52 :             eErr = oSecondEnum.ProcessLine(nullptr, panThisLineVal, nullptr,
     311             :                                            panThisLineId, nXSize)
     312          52 :                        ? CE_None
     313             :                        : CE_Failure;
     314             :         }
     315             :         else
     316             :         {
     317        1386 :             eErr = oSecondEnum.ProcessLine(panLastLineVal, panThisLineVal,
     318             :                                            panLastLineId, panThisLineId, nXSize)
     319        1386 :                        ? CE_None
     320             :                        : CE_Failure;
     321             :         }
     322             : 
     323        1490 :         if (eErr != CE_None)
     324           0 :             continue;
     325             : 
     326        1490 :         if (iY < nYSize)
     327             :         {
     328      422103 :             for (int iX = 0; iX < nXSize; iX++)
     329             :             {
     330             :                 // TODO: maybe we can reserve -1 as the lookup result for -1 polygon id in the panPolyIdMap,
     331             :                 //       so the this expression becomes: panLastLineId[iX] = *(oFirstEnum.panPolyIdMap + panThisLineId[iX]).
     332             :                 //       This would eliminate the condition checking.
     333      420665 :                 panLastLineId[iX] =
     334      420665 :                     panThisLineId[iX] == -1
     335      420665 :                         ? -1
     336      367819 :                         : oFirstEnum.panPolyIdMap[panThisLineId[iX]];
     337             :             }
     338             : 
     339        1438 :             oPolygonizer.processLine(panLastLineId, panLastLineVal,
     340             :                                      paoThisLineArm, paoLastLineArm, iY,
     341             :                                      nXSize);
     342        1438 :             eErr = oPolygonWriter.getErr();
     343             :         }
     344             :         else
     345             :         {
     346          52 :             oPolygonizer.processLine(panThisLineId, panLastLineVal,
     347             :                                      paoThisLineArm, paoLastLineArm, iY,
     348             :                                      nXSize);
     349          52 :             eErr = oPolygonWriter.getErr();
     350             :         }
     351             : 
     352        1490 :         if (eErr != CE_None)
     353           0 :             continue;
     354             : 
     355             :         /* --------------------------------------------------------------------
     356             :          */
     357             :         /*      Swap pixel value, and polygon id lines to be ready for the */
     358             :         /*      next line. */
     359             :         /* --------------------------------------------------------------------
     360             :          */
     361        1490 :         std::swap(panLastLineVal, panThisLineVal);
     362        1490 :         std::swap(panLastLineId, panThisLineId);
     363        1490 :         std::swap(paoThisLineArm, paoLastLineArm);
     364             : 
     365             :         /* --------------------------------------------------------------------
     366             :          */
     367             :         /*      Report progress, and support interrupts. */
     368             :         /* --------------------------------------------------------------------
     369             :          */
     370        1490 :         if (!pfnProgress(0.10 + 0.90 * ((iY + 1) / static_cast<double>(nYSize)),
     371             :                          "", pProgressArg))
     372             :         {
     373           0 :             CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
     374           0 :             eErr = CE_Failure;
     375             :         }
     376             :     }
     377             : 
     378             :     /* -------------------------------------------------------------------- */
     379             :     /*      Cleanup                                                         */
     380             :     /* -------------------------------------------------------------------- */
     381          52 :     CPLFree(panThisLineId);
     382          52 :     CPLFree(panLastLineId);
     383          52 :     CPLFree(panThisLineVal);
     384          52 :     CPLFree(panLastLineVal);
     385          52 :     CPLFree(paoThisLineArm);
     386          52 :     CPLFree(paoLastLineArm);
     387          52 :     CPLFree(pabyMaskLine);
     388             : 
     389          52 :     return eErr;
     390             : }
     391             : 
     392             : /******************************************************************************/
     393             : /*                          GDALFloatEquals()                                 */
     394             : /* Code from:                                                                 */
     395             : /* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm  */
     396             : /******************************************************************************/
     397          88 : GBool GDALFloatEquals(float A, float B)
     398             : {
     399             :     // This function will allow maxUlps-1 floats between A and B.
     400          88 :     const int maxUlps = MAX_ULPS;
     401             : 
     402             :     // Make sure maxUlps is non-negative and small enough that the default NAN
     403             :     // won't compare as equal to anything.
     404             : #if MAX_ULPS <= 0 || MAX_ULPS >= 4 * 1024 * 1024
     405             : #error "Invalid MAX_ULPS"
     406             : #endif
     407             : 
     408             :     // This assignation could violate strict aliasing. It causes a warning with
     409             :     // gcc -O2. Use of memcpy preferred. Credits for Even Rouault. Further info
     410             :     // at http://trac.osgeo.org/gdal/ticket/4005#comment:6
     411          88 :     int aInt = 0;
     412          88 :     memcpy(&aInt, &A, 4);
     413             : 
     414             :     // Make aInt lexicographically ordered as a twos-complement int.
     415          88 :     if (aInt < 0)
     416          10 :         aInt = INT_MIN - aInt;
     417             : 
     418             :     // Make bInt lexicographically ordered as a twos-complement int.
     419          88 :     int bInt = 0;
     420          88 :     memcpy(&bInt, &B, 4);
     421             : 
     422          88 :     if (bInt < 0)
     423          10 :         bInt = INT_MIN - bInt;
     424             : #ifdef COMPAT_WITH_ICC_CONVERSION_CHECK
     425             :     const int intDiff =
     426             :         abs(static_cast<int>(static_cast<GUIntBig>(static_cast<GIntBig>(aInt) -
     427             :                                                    static_cast<GIntBig>(bInt)) &
     428             :                              0xFFFFFFFFU));
     429             : #else
     430             :     // To make -ftrapv happy we compute the diff on larger type and
     431             :     // cast down later.
     432          88 :     const int intDiff = abs(static_cast<int>(static_cast<GIntBig>(aInt) -
     433             :                                              static_cast<GIntBig>(bInt)));
     434             : #endif
     435          88 :     if (intDiff <= maxUlps)
     436          30 :         return true;
     437          58 :     return false;
     438             : }
     439             : 
     440             : /************************************************************************/
     441             : /*                           GDALPolygonize()                           */
     442             : /************************************************************************/
     443             : 
     444             : /**
     445             :  * Create polygon coverage from raster data.
     446             :  *
     447             :  * This function creates vector polygons for all connected regions of pixels in
     448             :  * the raster sharing a common pixel value.  Optionally each polygon may be
     449             :  * labeled with the pixel value in an attribute.  Optionally a mask band
     450             :  * can be provided to determine which pixels are eligible for processing.
     451             :  *
     452             :  * Note that currently the source pixel band values are read into a
     453             :  * signed 64bit integer buffer (Int64), so floating point or complex
     454             :  * bands will be implicitly truncated before processing. If you want to use a
     455             :  * version using 32bit float buffers, see GDALFPolygonize().
     456             :  *
     457             :  * Polygon features will be created on the output layer, with polygon
     458             :  * geometries representing the polygons.  The polygon geometries will be
     459             :  * in the georeferenced coordinate system of the image (based on the
     460             :  * geotransform of the source dataset).  It is acceptable for the output
     461             :  * layer to already have features.  Note that GDALPolygonize() does not
     462             :  * set the coordinate system on the output layer.  Application code should
     463             :  * do this when the layer is created, presumably matching the raster
     464             :  * coordinate system.
     465             :  *
     466             :  * The algorithm used attempts to minimize memory use so that very large
     467             :  * rasters can be processed.  However, if the raster has many polygons
     468             :  * or very large/complex polygons, the memory use for holding polygon
     469             :  * enumerations and active polygon geometries may grow to be quite large.
     470             :  *
     471             :  * The algorithm will generally produce very dense polygon geometries, with
     472             :  * edges that follow exactly on pixel boundaries for all non-interior pixels.
     473             :  * For non-thematic raster data (such as satellite images) the result will
     474             :  * essentially be one small polygon per pixel, and memory and output layer
     475             :  * sizes will be substantial.  The algorithm is primarily intended for
     476             :  * relatively simple thematic imagery, masks, and classification results.
     477             :  *
     478             :  * @param hSrcBand the source raster band to be processed.
     479             :  * @param hMaskBand an optional mask band.  All pixels in the mask band with a
     480             :  * value other than zero will be considered suitable for collection as
     481             :  * polygons.
     482             :  * @param hOutLayer the vector feature layer to which the polygons should
     483             :  * be written.
     484             :  * @param iPixValField the attribute field index indicating the feature
     485             :  * attribute into which the pixel value of the polygon should be written. Or
     486             :  * -1 to indicate that the pixel value must not be written.
     487             :  * @param papszOptions a name/value list of additional options
     488             :  * <ul>
     489             :  * <li>8CONNECTED=8: May be set to "8" to use 8 connectedness.
     490             :  * Otherwise 4 connectedness will be applied to the algorithm</li>
     491             :  * <li>DATASET_FOR_GEOREF=dataset_name: Name of a dataset from which to read
     492             :  * the geotransform. This useful if hSrcBand has no related dataset, which is
     493             :  * typical for mask bands.</li>
     494             :  * </ul>
     495             :  * @param pfnProgress callback for reporting algorithm progress matching the
     496             :  * GDALProgressFunc() semantics.  May be NULL.
     497             :  * @param pProgressArg callback argument passed to pfnProgress.
     498             :  *
     499             :  * @return CE_None on success or CE_Failure on a failure.
     500             :  */
     501             : 
     502          51 : CPLErr CPL_STDCALL GDALPolygonize(GDALRasterBandH hSrcBand,
     503             :                                   GDALRasterBandH hMaskBand,
     504             :                                   OGRLayerH hOutLayer, int iPixValField,
     505             :                                   char **papszOptions,
     506             :                                   GDALProgressFunc pfnProgress,
     507             :                                   void *pProgressArg)
     508             : 
     509             : {
     510          51 :     return GDALPolygonizeT<std::int64_t, IntEqualityTest>(
     511             :         hSrcBand, hMaskBand, hOutLayer, iPixValField, papszOptions, pfnProgress,
     512          51 :         pProgressArg, GDT_Int64);
     513             : }
     514             : 
     515             : /************************************************************************/
     516             : /*                           GDALFPolygonize()                           */
     517             : /************************************************************************/
     518             : 
     519             : /**
     520             :  * Create polygon coverage from raster data.
     521             :  *
     522             :  * This function creates vector polygons for all connected regions of pixels in
     523             :  * the raster sharing a common pixel value.  Optionally each polygon may be
     524             :  * labeled with the pixel value in an attribute.  Optionally a mask band
     525             :  * can be provided to determine which pixels are eligible for processing.
     526             :  *
     527             :  * The source pixel band values are read into a 32bit float buffer. If you want
     528             :  * to use a (probably faster) version using signed 32bit integer buffer, see
     529             :  * GDALPolygonize().
     530             :  *
     531             :  * Polygon features will be created on the output layer, with polygon
     532             :  * geometries representing the polygons.  The polygon geometries will be
     533             :  * in the georeferenced coordinate system of the image (based on the
     534             :  * geotransform of the source dataset).  It is acceptable for the output
     535             :  * layer to already have features.  Note that GDALFPolygonize() does not
     536             :  * set the coordinate system on the output layer.  Application code should
     537             :  * do this when the layer is created, presumably matching the raster
     538             :  * coordinate system.
     539             :  *
     540             :  * The algorithm used attempts to minimize memory use so that very large
     541             :  * rasters can be processed.  However, if the raster has many polygons
     542             :  * or very large/complex polygons, the memory use for holding polygon
     543             :  * enumerations and active polygon geometries may grow to be quite large.
     544             :  *
     545             :  * The algorithm will generally produce very dense polygon geometries, with
     546             :  * edges that follow exactly on pixel boundaries for all non-interior pixels.
     547             :  * For non-thematic raster data (such as satellite images) the result will
     548             :  * essentially be one small polygon per pixel, and memory and output layer
     549             :  * sizes will be substantial.  The algorithm is primarily intended for
     550             :  * relatively simple thematic imagery, masks, and classification results.
     551             :  *
     552             :  * @param hSrcBand the source raster band to be processed.
     553             :  * @param hMaskBand an optional mask band.  All pixels in the mask band with a
     554             :  * value other than zero will be considered suitable for collection as
     555             :  * polygons.
     556             :  * @param hOutLayer the vector feature layer to which the polygons should
     557             :  * be written.
     558             :  * @param iPixValField the attribute field index indicating the feature
     559             :  * attribute into which the pixel value of the polygon should be written. Or
     560             :  * -1 to indicate that the pixel value must not be written.
     561             :  * @param papszOptions a name/value list of additional options
     562             :  * <ul>
     563             :  * <li>8CONNECTED=8: May be set to "8" to use 8 connectedness.
     564             :  * Otherwise 4 connectedness will be applied to the algorithm</li>
     565             :  * <li>DATASET_FOR_GEOREF=dataset_name: Name of a dataset from which to read
     566             :  * the geotransform. This useful if hSrcBand has no related dataset, which is
     567             :  * typical for mask bands.</li>
     568             :  * </ul>
     569             :  * @param pfnProgress callback for reporting algorithm progress matching the
     570             :  * GDALProgressFunc() semantics.  May be NULL.
     571             :  * @param pProgressArg callback argument passed to pfnProgress.
     572             :  *
     573             :  * @return CE_None on success or CE_Failure on a failure.
     574             :  *
     575             :  * @since GDAL 1.9.0
     576             :  */
     577             : 
     578           1 : CPLErr CPL_STDCALL GDALFPolygonize(GDALRasterBandH hSrcBand,
     579             :                                    GDALRasterBandH hMaskBand,
     580             :                                    OGRLayerH hOutLayer, int iPixValField,
     581             :                                    char **papszOptions,
     582             :                                    GDALProgressFunc pfnProgress,
     583             :                                    void *pProgressArg)
     584             : 
     585             : {
     586           1 :     return GDALPolygonizeT<float, FloatEqualityTest>(
     587             :         hSrcBand, hMaskBand, hOutLayer, iPixValField, papszOptions, pfnProgress,
     588           1 :         pProgressArg, GDT_Float32);
     589             : }

Generated by: LCOV version 1.14