GDAL的柵格化算法中有GDALRasterizeLayers
、GDALRasterizeLayersBuf
和GDALRasterizeGeometries
函數,可是沒有GDALRasterizeGeometriesBuf
函數(GDAL項目不打算添加這個函數,由於增長一個函數會增長維護成本)。而柵格化算法的實際實現函數gv_rasterize_one_shape
並不導出,因此在使用的時候形成了必定的不便。
雖然能夠經過MEMDataset
的方式,調用GDALRasterizeGeometries
達到目的,可是不夠直接和高效,因此我寫了GDALRasterizeGeometriesBuf
函數。
我的認爲比較靈活的方式,仍是將gv_rasterize_one_shape
函數導出,以便自由使用。算法
修改gdal/alg/gdal_alg.h
頭文件,在GDALRasterizeGeometries
函數聲明下添加GDALRasterizeGeometriesBuf
函數聲明。app
CPLErr CPL_DLL GDALRasterizeGeometriesBuf( void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace, int nGeomCount, OGRGeometryH *pahGeometries, const char *pszGeomProjection, const char *pszDstProjection, double *padfDstGeoTransform, GDALTransformerFunc pfnTransformer, void *pTransformArg, double dfBurnValue, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg );
修改gdal/alg/gdalrasterize.cpp
文件,添加GDALRasterizeGeometriesBuf
函數的實現,代碼以下:函數
/************************************************************************/ /* GDALRasterizeGeometriesBuf() */ /************************************************************************/ /** * Burn geometries into raster. * * Rasterize a list of geometric objects into a raster dataset. The * geometries are passed as an array of OGRGeometryH handlers. * * If the geometries are in the georeferenced coordinates of the raster * dataset, then the pfnTransform may be passed in NULL and one will be * derived internally from the geotransform of the dataset. The transform * needs to transform the geometry locations into pixel/line coordinates * of the target raster. * * The output raster may be of any GDAL supported datatype, though currently * internally the burning is done either as GDT_Byte or GDT_Float32. This * may be improved in the future. * * @param pData pointer to the output data array. * @param nBufXSize width of the output data array in pixels. * @param nBufYSize height of the output data array in pixels. * @param eBufType data type of the output data array. * * @param nPixelSpace The byte offset from the start of one pixel value in * pData to the start of the next pixel value within a scanline. If defaulted * (0) the size of the datatype eBufType is used. * * @param nLineSpace The byte offset from the start of one scanline in * pData to the start of the next. If defaulted the size of the datatype * eBufType * nBufXSize is used. * * @param nGeomCount the number of geometries being passed in pahGeometries. * @param pahGeometries the array of geometries to burn in. * @param pszGeomProjection WKT defining the coordinate system of the geometries. * * @param pszDstProjection WKT defining the coordinate system of the target * raster. * * @param padfDstGeoTransform geotransformation matrix of the target raster. * * @param pfnTransformer transformation to apply to geometries to put into * pixel/line coordinates on raster. If NULL a geotransform based one will * be created internally. * * @param pTransformArg callback data for transformer. * @param dfBurnValue the value to burn into the raster. * * @param papszOptions special options controlling rasterization: * <ul> * <li>"ALL_TOUCHED": May be set to TRUE to set all pixels touched * by the line or polygons, not just those whose center is within the polygon * or that are selected by brezenhams line algorithm. Defaults to FALSE.</li> * <li>"BURN_VALUE_FROM": May be set to "Z" to use * the Z values of the geometries. dfBurnValue or the attribute field value is * added to this before burning. In default case dfBurnValue is burned as it * is. This is implemented properly only for points and lines for now. Polygons * will be burned using the Z value from the first point. The M value may * be supported in the future.</li> * <li>"MERGE_ALG": May be REPLACE (the default) or ADD. REPLACE * results in overwriting of value, while ADD adds the new value to the * existing raster, suitable for heatmaps for instance.</li> * </ul> * * @param pfnProgress the progress function to report completion. * * @param pProgressArg callback data for progress function. * * * @return CE_None on success or CE_Failure on error. */ CPLErr GDALRasterizeGeometriesBuf( void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace, int nGeomCount, OGRGeometryH *pahGeometries, const char *pszGeomProjection, const char *pszDstProjection, double *padfDstGeoTransform, GDALTransformerFunc pfnTransformer, void *pTransformArg, double dfBurnValue, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg ) { /* -------------------------------------------------------------------- */ /* If pixel and line spaceing are defaulted assign reasonable */ /* value assuming a packed buffer. */ /* -------------------------------------------------------------------- */ if( nPixelSpace != 0 ) { nPixelSpace = GDALGetDataTypeSizeBytes( eBufType ); } if( nPixelSpace != GDALGetDataTypeSizeBytes( eBufType ) ) { CPLError(CE_Failure, CPLE_NotSupported, "GDALRasterizeGeometriesBuf(): unsupported value of nPixelSpace"); return CE_Failure; } if( nLineSpace == 0 ) { nLineSpace = nPixelSpace * nBufXSize; } if( nLineSpace != nPixelSpace * nBufXSize ) { CPLError(CE_Failure, CPLE_NotSupported, "GDALRasterizeGeometriesBuf(): unsupported value of nLineSpace"); return CE_Failure; } if( pfnProgress == nullptr ) pfnProgress = GDALDummyProgress; /* -------------------------------------------------------------------- */ /* Do some rudimentary arg checking. */ /* -------------------------------------------------------------------- */ if( nGeomCount == 0 ) return CE_None; /* -------------------------------------------------------------------- */ /* Options */ /* -------------------------------------------------------------------- */ int bAllTouched = FALSE; GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue; GDALRasterMergeAlg eMergeAlg = GRMA_Replace; GDALRasterizeOptim eOptim = GRO_Auto; if( GDALRasterizeOptions(papszOptions, &bAllTouched, &eBurnValueSource, &eMergeAlg, &eOptim) == CE_Failure ) { return CE_Failure; } /* -------------------------------------------------------------------- */ /* If we have no transformer, create the one from input file */ /* projection. Note that each layer can be georefernced */ /* separately. */ /* -------------------------------------------------------------------- */ bool bNeedToFreeTransformer = false; if( pfnTransformer == nullptr ) { if( !pszGeomProjection ) { CPLError( CE_Warning, CPLE_AppDefined, "There is no specified spatial reference for the" " geometry to build transformer, assuming" " matching coordinate systems."); } pTransformArg = GDALCreateGenImgProjTransformer3( pszGeomProjection, nullptr, pszDstProjection, padfDstGeoTransform ); pfnTransformer = GDALGenImgProjTransform; } /* ==================================================================== */ /* Write geometry to the raster individually. */ /* ==================================================================== */ CPLErr eErr = CE_None; pfnProgress( 0.0, nullptr, pProgressArg ); int iGeometry; for(iGeometry = 0; iGeometry < nGeomCount; ++iGeometry ) { OGRGeometry *poGeom = reinterpret_cast<OGRGeometry*>(pahGeometries[iGeometry]); // 後期gv_rasterize_one_shape函數可能會變,此處後期須要修改 gv_rasterize_one_shape( static_cast<unsigned char *>(pData), 0, 0, nBufXSize, nBufYSize, 1, eBufType, bAllTouched, poGeom, &dfBurnValue, eBurnValueSource, eMergeAlg, pfnTransformer, pTransformArg ); if( !pfnProgress((iGeometry+1)/static_cast<double>(nGeomCount), "", pProgressArg) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); eErr = CE_Failure; } } if( bNeedToFreeTransformer ) GDALDestroyTransformer( pTransformArg ); return eErr; }