PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/gdal-1.9.1-fedora/apps/gdal_grid.cpp

#
C++ | 1002 lines | 772 code | 124 blank | 106 comment | 210 complexity | ee71cd84ff2c5ff4f5876f886ba83c6f MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0
  1. /* ****************************************************************************
  2. * $Id: gdal_grid.cpp 22783 2011-07-23 19:28:16Z rouault $
  3. *
  4. * Project: GDAL Utilities
  5. * Purpose: GDAL scattered data gridding (interpolation) tool
  6. * Author: Andrey Kiselev, dron@ak4719.spb.edu
  7. *
  8. * ****************************************************************************
  9. * Copyright (c) 2007, Andrey Kiselev <dron@ak4719.spb.edu>
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a
  12. * copy of this software and associated documentation files (the "Software"),
  13. * to deal in the Software without restriction, including without limitation
  14. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15. * and/or sell copies of the Software, and to permit persons to whom the
  16. * Software is furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included
  19. * in all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  22. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  24. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  26. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  27. * DEALINGS IN THE SOFTWARE.
  28. ****************************************************************************/
  29. #include <cstdlib>
  30. #include <vector>
  31. #include <algorithm>
  32. #include "cpl_string.h"
  33. #include "gdal.h"
  34. #include "gdal_alg.h"
  35. #include "ogr_spatialref.h"
  36. #include "ogr_api.h"
  37. #include "ogrsf_frmts.h"
  38. #include "gdalgrid.h"
  39. #include "commonutils.h"
  40. CPL_CVSID("$Id: gdal_grid.cpp 22783 2011-07-23 19:28:16Z rouault $");
  41. /************************************************************************/
  42. /* Usage() */
  43. /************************************************************************/
  44. static void Usage()
  45. {
  46. printf(
  47. "Usage: gdal_grid [--help-general] [--formats]\n"
  48. " [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
  49. " CInt16/CInt32/CFloat32/CFloat64}]\n"
  50. " [-of format] [-co \"NAME=VALUE\"]\n"
  51. " [-zfield field_name]\n"
  52. " [-a_srs srs_def] [-spat xmin ymin xmax ymax]\n"
  53. " [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]\n"
  54. " [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
  55. " [-clipsrcwhere expression]\n"
  56. " [-l layername]* [-where expression] [-sql select_statement]\n"
  57. " [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]\n"
  58. " [-a algorithm[:parameter1=value1]*]"
  59. " [-q]\n"
  60. " <src_datasource> <dst_filename>\n"
  61. "\n"
  62. "Available algorithms and parameters with their's defaults:\n"
  63. " Inverse distance to a power (default)\n"
  64. " invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:angle=0.0:max_points=0:min_points=0:nodata=0.0\n"
  65. " Moving average\n"
  66. " average:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
  67. " Nearest neighbor\n"
  68. " nearest:radius1=0.0:radius2=0.0:angle=0.0:nodata=0.0\n"
  69. " Various data metrics\n"
  70. " <metric name>:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
  71. " possible metrics are:\n"
  72. " minimum\n"
  73. " maximum\n"
  74. " range\n"
  75. " count\n"
  76. " average_distance\n"
  77. " average_distance_pts\n"
  78. "\n");
  79. GDALDestroyDriverManager();
  80. exit( 1 );
  81. }
  82. /************************************************************************/
  83. /* GetAlgorithmName() */
  84. /* */
  85. /* Translates algortihm code into mnemonic name. */
  86. /************************************************************************/
  87. static void PrintAlgorithmAndOptions( GDALGridAlgorithm eAlgorithm,
  88. void *pOptions )
  89. {
  90. switch ( eAlgorithm )
  91. {
  92. case GGA_InverseDistanceToAPower:
  93. printf( "Algorithm name: \"%s\".\n", szAlgNameInvDist );
  94. printf( "Options are "
  95. "\"power=%f:smoothing=%f:radius1=%f:radius2=%f:angle=%f"
  96. ":max_points=%lu:min_points=%lu:nodata=%f\"\n",
  97. ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfPower,
  98. ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfSmoothing,
  99. ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius1,
  100. ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius2,
  101. ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfAngle,
  102. (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMaxPoints,
  103. (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMinPoints,
  104. ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfNoDataValue);
  105. break;
  106. case GGA_MovingAverage:
  107. printf( "Algorithm name: \"%s\".\n", szAlgNameAverage );
  108. printf( "Options are "
  109. "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
  110. ":nodata=%f\"\n",
  111. ((GDALGridMovingAverageOptions *)pOptions)->dfRadius1,
  112. ((GDALGridMovingAverageOptions *)pOptions)->dfRadius2,
  113. ((GDALGridMovingAverageOptions *)pOptions)->dfAngle,
  114. (unsigned long)((GDALGridMovingAverageOptions *)pOptions)->nMinPoints,
  115. ((GDALGridMovingAverageOptions *)pOptions)->dfNoDataValue);
  116. break;
  117. case GGA_NearestNeighbor:
  118. printf( "Algorithm name: \"%s\".\n", szAlgNameNearest );
  119. printf( "Options are "
  120. "\"radius1=%f:radius2=%f:angle=%f:nodata=%f\"\n",
  121. ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius1,
  122. ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius2,
  123. ((GDALGridNearestNeighborOptions *)pOptions)->dfAngle,
  124. ((GDALGridNearestNeighborOptions *)pOptions)->dfNoDataValue);
  125. break;
  126. case GGA_MetricMinimum:
  127. printf( "Algorithm name: \"%s\".\n", szAlgNameMinimum );
  128. printf( "Options are "
  129. "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
  130. ":nodata=%f\"\n",
  131. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
  132. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
  133. ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
  134. (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
  135. ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
  136. break;
  137. case GGA_MetricMaximum:
  138. printf( "Algorithm name: \"%s\".\n", szAlgNameMaximum );
  139. printf( "Options are "
  140. "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
  141. ":nodata=%f\"\n",
  142. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
  143. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
  144. ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
  145. (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
  146. ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
  147. break;
  148. case GGA_MetricRange:
  149. printf( "Algorithm name: \"%s\".\n", szAlgNameRange );
  150. printf( "Options are "
  151. "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
  152. ":nodata=%f\"\n",
  153. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
  154. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
  155. ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
  156. (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
  157. ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
  158. break;
  159. case GGA_MetricCount:
  160. printf( "Algorithm name: \"%s\".\n", szAlgNameCount );
  161. printf( "Options are "
  162. "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
  163. ":nodata=%f\"\n",
  164. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
  165. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
  166. ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
  167. (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
  168. ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
  169. break;
  170. case GGA_MetricAverageDistance:
  171. printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistance );
  172. printf( "Options are "
  173. "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
  174. ":nodata=%f\"\n",
  175. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
  176. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
  177. ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
  178. (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
  179. ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
  180. break;
  181. case GGA_MetricAverageDistancePts:
  182. printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistancePts );
  183. printf( "Options are "
  184. "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
  185. ":nodata=%f\"\n",
  186. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
  187. ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
  188. ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
  189. (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
  190. ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
  191. break;
  192. default:
  193. printf( "Algorithm is unknown.\n" );
  194. break;
  195. }
  196. }
  197. /************************************************************************/
  198. /* ProcessGeometry() */
  199. /* */
  200. /* Extract point coordinates from the geometry reference and set the */
  201. /* Z value as requested. Test whther we are in the clipped region */
  202. /* before processing. */
  203. /************************************************************************/
  204. static void ProcessGeometry( OGRPoint *poGeom, OGRGeometry *poClipSrc,
  205. int iBurnField, double dfBurnValue,
  206. std::vector<double> &adfX,
  207. std::vector<double> &adfY,
  208. std::vector<double> &adfZ )
  209. {
  210. if ( poClipSrc && !poGeom->Within(poClipSrc) )
  211. return;
  212. adfX.push_back( poGeom->getX() );
  213. adfY.push_back( poGeom->getY() );
  214. if ( iBurnField < 0 )
  215. adfZ.push_back( poGeom->getZ() );
  216. else
  217. adfZ.push_back( dfBurnValue );
  218. }
  219. /************************************************************************/
  220. /* ProcessLayer() */
  221. /* */
  222. /* Process all the features in a layer selection, collecting */
  223. /* geometries and burn values. */
  224. /************************************************************************/
  225. static void ProcessLayer( OGRLayerH hSrcLayer, GDALDatasetH hDstDS,
  226. OGRGeometry *poClipSrc,
  227. GUInt32 nXSize, GUInt32 nYSize, int nBand,
  228. int& bIsXExtentSet, int& bIsYExtentSet,
  229. double& dfXMin, double& dfXMax,
  230. double& dfYMin, double& dfYMax,
  231. const char *pszBurnAttribute,
  232. GDALDataType eType,
  233. GDALGridAlgorithm eAlgorithm, void *pOptions,
  234. int bQuiet, GDALProgressFunc pfnProgress )
  235. {
  236. /* -------------------------------------------------------------------- */
  237. /* Get field index, and check. */
  238. /* -------------------------------------------------------------------- */
  239. int iBurnField = -1;
  240. if ( pszBurnAttribute )
  241. {
  242. iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
  243. pszBurnAttribute );
  244. if( iBurnField == -1 )
  245. {
  246. printf( "Failed to find field %s on layer %s, skipping.\n",
  247. pszBurnAttribute,
  248. OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
  249. return;
  250. }
  251. }
  252. /* -------------------------------------------------------------------- */
  253. /* Collect the geometries from this layer, and build list of */
  254. /* values to be interpolated. */
  255. /* -------------------------------------------------------------------- */
  256. OGRFeature *poFeat;
  257. std::vector<double> adfX, adfY, adfZ;
  258. OGR_L_ResetReading( hSrcLayer );
  259. while( (poFeat = (OGRFeature *)OGR_L_GetNextFeature( hSrcLayer )) != NULL )
  260. {
  261. OGRGeometry *poGeom = poFeat->GetGeometryRef();
  262. if ( poGeom != NULL )
  263. {
  264. OGRwkbGeometryType eType = wkbFlatten( poGeom->getGeometryType() );
  265. double dfBurnValue = 0.0;
  266. if ( iBurnField >= 0 )
  267. dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
  268. if ( eType == wkbMultiPoint )
  269. {
  270. int iGeom;
  271. int nGeomCount = ((OGRMultiPoint *)poGeom)->getNumGeometries();
  272. for ( iGeom = 0; iGeom < nGeomCount; iGeom++ )
  273. {
  274. ProcessGeometry( (OGRPoint *)((OGRMultiPoint *)poGeom)->getGeometryRef(iGeom),
  275. poClipSrc, iBurnField, dfBurnValue,
  276. adfX, adfY, adfZ);
  277. }
  278. }
  279. else if ( eType == wkbPoint )
  280. {
  281. ProcessGeometry( (OGRPoint *)poGeom, poClipSrc,
  282. iBurnField, dfBurnValue, adfX, adfY, adfZ);
  283. }
  284. }
  285. OGRFeature::DestroyFeature( poFeat );
  286. }
  287. if ( adfX.size() == 0 )
  288. {
  289. printf( "No point geometry found on layer %s, skipping.\n",
  290. OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
  291. return;
  292. }
  293. /* -------------------------------------------------------------------- */
  294. /* Compute grid geometry. */
  295. /* -------------------------------------------------------------------- */
  296. if ( !bIsXExtentSet || !bIsYExtentSet )
  297. {
  298. OGREnvelope sEnvelope;
  299. OGR_L_GetExtent( hSrcLayer, &sEnvelope, TRUE );
  300. if ( !bIsXExtentSet )
  301. {
  302. dfXMin = sEnvelope.MinX;
  303. dfXMax = sEnvelope.MaxX;
  304. bIsXExtentSet = TRUE;
  305. }
  306. if ( !bIsYExtentSet )
  307. {
  308. dfYMin = sEnvelope.MinY;
  309. dfYMax = sEnvelope.MaxY;
  310. bIsYExtentSet = TRUE;
  311. }
  312. }
  313. /* -------------------------------------------------------------------- */
  314. /* Perform gridding. */
  315. /* -------------------------------------------------------------------- */
  316. const double dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
  317. const double dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
  318. if ( !bQuiet )
  319. {
  320. printf( "Grid data type is \"%s\"\n", GDALGetDataTypeName(eType) );
  321. printf( "Grid size = (%lu %lu).\n",
  322. (unsigned long)nXSize, (unsigned long)nYSize );
  323. printf( "Corner coordinates = (%f %f)-(%f %f).\n",
  324. dfXMin - dfDeltaX / 2, dfYMax + dfDeltaY / 2,
  325. dfXMax + dfDeltaX / 2, dfYMin - dfDeltaY / 2 );
  326. printf( "Grid cell size = (%f %f).\n", dfDeltaX, dfDeltaY );
  327. printf( "Source point count = %lu.\n", (unsigned long)adfX.size() );
  328. PrintAlgorithmAndOptions( eAlgorithm, pOptions );
  329. printf("\n");
  330. }
  331. GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, nBand );
  332. if (adfX.size() == 0)
  333. {
  334. // FIXME: Shoulda' set to nodata value instead
  335. GDALFillRaster( hBand, 0.0 , 0.0 );
  336. return;
  337. }
  338. GUInt32 nXOffset, nYOffset;
  339. int nBlockXSize, nBlockYSize;
  340. GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
  341. void *pData =
  342. CPLMalloc( nBlockXSize * nBlockYSize * GDALGetDataTypeSize(eType) );
  343. GUInt32 nBlock = 0;
  344. GUInt32 nBlockCount = ((nXSize + nBlockXSize - 1) / nBlockXSize)
  345. * ((nYSize + nBlockYSize - 1) / nBlockYSize);
  346. for ( nYOffset = 0; nYOffset < nYSize; nYOffset += nBlockYSize )
  347. {
  348. for ( nXOffset = 0; nXOffset < nXSize; nXOffset += nBlockXSize )
  349. {
  350. void *pScaledProgress;
  351. pScaledProgress =
  352. GDALCreateScaledProgress( 0.0,
  353. (double)++nBlock / nBlockCount,
  354. pfnProgress, NULL );
  355. int nXRequest = nBlockXSize;
  356. if (nXOffset + nXRequest > nXSize)
  357. nXRequest = nXSize - nXOffset;
  358. int nYRequest = nBlockYSize;
  359. if (nYOffset + nYRequest > nYSize)
  360. nYRequest = nYSize - nYOffset;
  361. GDALGridCreate( eAlgorithm, pOptions,
  362. adfX.size(), &(adfX[0]), &(adfY[0]), &(adfZ[0]),
  363. dfXMin + dfDeltaX * nXOffset,
  364. dfXMin + dfDeltaX * (nXOffset + nXRequest),
  365. dfYMin + dfDeltaY * nYOffset,
  366. dfYMin + dfDeltaY * (nYOffset + nYRequest),
  367. nXRequest, nYRequest, eType, pData,
  368. GDALScaledProgress, pScaledProgress );
  369. GDALRasterIO( hBand, GF_Write, nXOffset, nYOffset,
  370. nXRequest, nYRequest, pData,
  371. nXRequest, nYRequest, eType, 0, 0 );
  372. GDALDestroyScaledProgress( pScaledProgress );
  373. }
  374. }
  375. CPLFree( pData );
  376. }
  377. /************************************************************************/
  378. /* LoadGeometry() */
  379. /* */
  380. /* Read geometries from the given dataset using specified filters and */
  381. /* returns a collection of read geometries. */
  382. /************************************************************************/
  383. static OGRGeometryCollection* LoadGeometry( const char* pszDS,
  384. const char* pszSQL,
  385. const char* pszLyr,
  386. const char* pszWhere )
  387. {
  388. OGRDataSource *poDS;
  389. OGRLayer *poLyr;
  390. OGRFeature *poFeat;
  391. OGRGeometryCollection *poGeom = NULL;
  392. poDS = OGRSFDriverRegistrar::Open( pszDS, FALSE );
  393. if ( poDS == NULL )
  394. return NULL;
  395. if ( pszSQL != NULL )
  396. poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL );
  397. else if ( pszLyr != NULL )
  398. poLyr = poDS->GetLayerByName( pszLyr );
  399. else
  400. poLyr = poDS->GetLayer(0);
  401. if ( poLyr == NULL )
  402. {
  403. fprintf( stderr,
  404. "FAILURE: Failed to identify source layer from datasource.\n" );
  405. OGRDataSource::DestroyDataSource( poDS );
  406. return NULL;
  407. }
  408. if ( pszWhere )
  409. poLyr->SetAttributeFilter( pszWhere );
  410. while ( (poFeat = poLyr->GetNextFeature()) != NULL )
  411. {
  412. OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
  413. if ( poSrcGeom )
  414. {
  415. OGRwkbGeometryType eType =
  416. wkbFlatten( poSrcGeom->getGeometryType() );
  417. if ( poGeom == NULL )
  418. poGeom = new OGRMultiPolygon();
  419. if ( eType == wkbPolygon )
  420. poGeom->addGeometry( poSrcGeom );
  421. else if ( eType == wkbMultiPolygon )
  422. {
  423. int iGeom;
  424. int nGeomCount =
  425. ((OGRMultiPolygon *)poSrcGeom)->getNumGeometries();
  426. for ( iGeom = 0; iGeom < nGeomCount; iGeom++ )
  427. {
  428. poGeom->addGeometry(
  429. ((OGRMultiPolygon *)poSrcGeom)->getGeometryRef(iGeom) );
  430. }
  431. }
  432. else
  433. {
  434. fprintf( stderr, "FAILURE: Geometry not of polygon type.\n" );
  435. OGRGeometryFactory::destroyGeometry( poGeom );
  436. OGRFeature::DestroyFeature( poFeat );
  437. if ( pszSQL != NULL )
  438. poDS->ReleaseResultSet( poLyr );
  439. OGRDataSource::DestroyDataSource( poDS );
  440. return NULL;
  441. }
  442. }
  443. OGRFeature::DestroyFeature( poFeat );
  444. }
  445. if( pszSQL != NULL )
  446. poDS->ReleaseResultSet( poLyr );
  447. OGRDataSource::DestroyDataSource( poDS );
  448. return poGeom;
  449. }
  450. /************************************************************************/
  451. /* main() */
  452. /************************************************************************/
  453. int main( int argc, char ** argv )
  454. {
  455. GDALDriverH hDriver;
  456. const char *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
  457. int bFormatExplicitelySet = FALSE;
  458. char **papszLayers = NULL;
  459. const char *pszBurnAttribute = NULL;
  460. const char *pszWHERE = NULL, *pszSQL = NULL;
  461. GDALDataType eOutputType = GDT_Float64;
  462. char **papszCreateOptions = NULL;
  463. GUInt32 nXSize = 0, nYSize = 0;
  464. double dfXMin = 0.0, dfXMax = 0.0, dfYMin = 0.0, dfYMax = 0.0;
  465. int bIsXExtentSet = FALSE, bIsYExtentSet = FALSE;
  466. GDALGridAlgorithm eAlgorithm = GGA_InverseDistanceToAPower;
  467. void *pOptions = NULL;
  468. char *pszOutputSRS = NULL;
  469. int bQuiet = FALSE;
  470. GDALProgressFunc pfnProgress = GDALTermProgress;
  471. int i;
  472. OGRGeometry *poSpatialFilter = NULL;
  473. int bClipSrc = FALSE;
  474. OGRGeometry *poClipSrc = NULL;
  475. const char *pszClipSrcDS = NULL;
  476. const char *pszClipSrcSQL = NULL;
  477. const char *pszClipSrcLayer = NULL;
  478. const char *pszClipSrcWhere = NULL;
  479. /* Check strict compilation and runtime library version as we use C++ API */
  480. if (! GDAL_CHECK_VERSION(argv[0]))
  481. exit(1);
  482. GDALAllRegister();
  483. OGRRegisterAll();
  484. argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
  485. if( argc < 1 )
  486. exit( -argc );
  487. /* -------------------------------------------------------------------- */
  488. /* Parse arguments. */
  489. /* -------------------------------------------------------------------- */
  490. for( i = 1; i < argc; i++ )
  491. {
  492. if( EQUAL(argv[i], "--utility_version") )
  493. {
  494. printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
  495. argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
  496. return 0;
  497. }
  498. else if( EQUAL(argv[i],"-of") && i < argc-1 )
  499. {
  500. pszFormat = argv[++i];
  501. bFormatExplicitelySet = TRUE;
  502. }
  503. else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
  504. {
  505. bQuiet = TRUE;
  506. pfnProgress = GDALDummyProgress;
  507. }
  508. else if( EQUAL(argv[i],"-ot") && i < argc-1 )
  509. {
  510. int iType;
  511. for( iType = 1; iType < GDT_TypeCount; iType++ )
  512. {
  513. if( GDALGetDataTypeName((GDALDataType)iType) != NULL
  514. && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
  515. argv[i+1]) )
  516. {
  517. eOutputType = (GDALDataType) iType;
  518. }
  519. }
  520. if( eOutputType == GDT_Unknown )
  521. {
  522. fprintf( stderr, "FAILURE: Unknown output pixel type: %s\n",
  523. argv[i + 1] );
  524. Usage();
  525. }
  526. i++;
  527. }
  528. else if( EQUAL(argv[i],"-txe") && i < argc-2 )
  529. {
  530. dfXMin = atof(argv[++i]);
  531. dfXMax = atof(argv[++i]);
  532. bIsXExtentSet = TRUE;
  533. }
  534. else if( EQUAL(argv[i],"-tye") && i < argc-2 )
  535. {
  536. dfYMin = atof(argv[++i]);
  537. dfYMax = atof(argv[++i]);
  538. bIsYExtentSet = TRUE;
  539. }
  540. else if( EQUAL(argv[i],"-outsize") && i < argc-2 )
  541. {
  542. nXSize = atoi(argv[++i]);
  543. nYSize = atoi(argv[++i]);
  544. }
  545. else if( EQUAL(argv[i],"-co") && i < argc-1 )
  546. {
  547. papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
  548. }
  549. else if( EQUAL(argv[i],"-zfield") && i < argc-1 )
  550. {
  551. pszBurnAttribute = argv[++i];
  552. }
  553. else if( EQUAL(argv[i],"-where") && i < argc-1 )
  554. {
  555. pszWHERE = argv[++i];
  556. }
  557. else if( EQUAL(argv[i],"-l") && i < argc-1 )
  558. {
  559. papszLayers = CSLAddString( papszLayers, argv[++i] );
  560. }
  561. else if( EQUAL(argv[i],"-sql") && i < argc-1 )
  562. {
  563. pszSQL = argv[++i];
  564. }
  565. else if( EQUAL(argv[i],"-spat")
  566. && argv[i+1] != NULL
  567. && argv[i+2] != NULL
  568. && argv[i+3] != NULL
  569. && argv[i+4] != NULL )
  570. {
  571. OGRLinearRing oRing;
  572. oRing.addPoint( atof(argv[i+1]), atof(argv[i+2]) );
  573. oRing.addPoint( atof(argv[i+1]), atof(argv[i+4]) );
  574. oRing.addPoint( atof(argv[i+3]), atof(argv[i+4]) );
  575. oRing.addPoint( atof(argv[i+3]), atof(argv[i+2]) );
  576. oRing.addPoint( atof(argv[i+1]), atof(argv[i+2]) );
  577. poSpatialFilter = new OGRPolygon();
  578. ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
  579. i += 4;
  580. }
  581. else if ( EQUAL(argv[i],"-clipsrc") && i < argc - 1 )
  582. {
  583. bClipSrc = TRUE;
  584. errno = 0;
  585. const double unused = strtod( argv[i + 1], NULL ); // XXX: is it a number or not?
  586. if ( errno != 0
  587. && argv[i + 2] != NULL
  588. && argv[i + 3] != NULL
  589. && argv[i + 4] != NULL)
  590. {
  591. OGRLinearRing oRing;
  592. oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 2]) );
  593. oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 4]) );
  594. oRing.addPoint( atof(argv[i + 3]), atof(argv[i + 4]) );
  595. oRing.addPoint( atof(argv[i + 3]), atof(argv[i + 2]) );
  596. oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 2]) );
  597. poClipSrc = new OGRPolygon();
  598. ((OGRPolygon *) poClipSrc)->addRing( &oRing );
  599. i += 4;
  600. (void)unused;
  601. }
  602. else if (EQUALN(argv[i + 1], "POLYGON", 7)
  603. || EQUALN(argv[i + 1], "MULTIPOLYGON", 12))
  604. {
  605. OGRGeometryFactory::createFromWkt(&argv[i + 1], NULL, &poClipSrc);
  606. if ( poClipSrc == NULL )
  607. {
  608. fprintf( stderr, "FAILURE: Invalid geometry. "
  609. "Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
  610. Usage();
  611. }
  612. i++;
  613. }
  614. else if (EQUAL(argv[i + 1], "spat_extent") )
  615. {
  616. i++;
  617. }
  618. else
  619. {
  620. pszClipSrcDS = argv[i + 1];
  621. i++;
  622. }
  623. }
  624. else if ( EQUAL(argv[i], "-clipsrcsql") && i < argc - 1 )
  625. {
  626. pszClipSrcSQL = argv[i + 1];
  627. i++;
  628. }
  629. else if ( EQUAL(argv[i], "-clipsrclayer") && i < argc - 1 )
  630. {
  631. pszClipSrcLayer = argv[i + 1];
  632. i++;
  633. }
  634. else if ( EQUAL(argv[i], "-clipsrcwhere") && i < argc - 1 )
  635. {
  636. pszClipSrcWhere = argv[i + 1];
  637. i++;
  638. }
  639. else if( EQUAL(argv[i],"-a_srs") && i < argc-1 )
  640. {
  641. OGRSpatialReference oOutputSRS;
  642. if( oOutputSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE )
  643. {
  644. fprintf( stderr, "Failed to process SRS definition: %s\n",
  645. argv[i+1] );
  646. GDALDestroyDriverManager();
  647. exit( 1 );
  648. }
  649. oOutputSRS.exportToWkt( &pszOutputSRS );
  650. i++;
  651. }
  652. else if( EQUAL(argv[i],"-a") && i < argc-1 )
  653. {
  654. if ( ParseAlgorithmAndOptions( argv[++i], &eAlgorithm, &pOptions )
  655. != CE_None )
  656. {
  657. fprintf( stderr,
  658. "Failed to process algoritm name and parameters.\n" );
  659. exit( 1 );
  660. }
  661. }
  662. else if( argv[i][0] == '-' )
  663. {
  664. fprintf( stderr,
  665. "FAILURE: Option %s incomplete, or not recognised.\n\n",
  666. argv[i] );
  667. Usage();
  668. }
  669. else if( pszSource == NULL )
  670. {
  671. pszSource = argv[i];
  672. }
  673. else if( pszDest == NULL )
  674. {
  675. pszDest = argv[i];
  676. }
  677. else
  678. {
  679. fprintf( stderr, "FAILURE: Too many command options.\n\n" );
  680. Usage();
  681. }
  682. }
  683. if( pszSource == NULL || pszDest == NULL
  684. || (pszSQL == NULL && papszLayers == NULL) )
  685. {
  686. Usage();
  687. }
  688. if ( bClipSrc && pszClipSrcDS != NULL )
  689. {
  690. poClipSrc = LoadGeometry( pszClipSrcDS, pszClipSrcSQL,
  691. pszClipSrcLayer, pszClipSrcWhere );
  692. if ( poClipSrc == NULL )
  693. {
  694. fprintf( stderr, "FAILURE: cannot load source clip geometry\n\n" );
  695. Usage();
  696. }
  697. }
  698. else if ( bClipSrc && poClipSrc == NULL && !poSpatialFilter )
  699. {
  700. fprintf( stderr,
  701. "FAILURE: -clipsrc must be used with -spat option or \n"
  702. "a bounding box, WKT string or datasource must be "
  703. "specified\n\n" );
  704. Usage();
  705. }
  706. if ( poSpatialFilter )
  707. {
  708. if ( poClipSrc )
  709. {
  710. OGRGeometry *poTemp = poSpatialFilter->Intersection( poClipSrc );
  711. if ( poTemp )
  712. {
  713. OGRGeometryFactory::destroyGeometry( poSpatialFilter );
  714. poSpatialFilter = poTemp;
  715. }
  716. OGRGeometryFactory::destroyGeometry( poClipSrc );
  717. poClipSrc = NULL;
  718. }
  719. }
  720. else
  721. {
  722. if ( poClipSrc )
  723. {
  724. poSpatialFilter = poClipSrc;
  725. poClipSrc = NULL;
  726. }
  727. }
  728. /* -------------------------------------------------------------------- */
  729. /* Find the output driver. */
  730. /* -------------------------------------------------------------------- */
  731. hDriver = GDALGetDriverByName( pszFormat );
  732. if( hDriver == NULL )
  733. {
  734. int iDr;
  735. fprintf( stderr,
  736. "FAILURE: Output driver `%s' not recognised.\n", pszFormat );
  737. fprintf( stderr,
  738. "The following format drivers are configured and support output:\n" );
  739. for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
  740. {
  741. GDALDriverH hDriver = GDALGetDriver(iDr);
  742. if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
  743. || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
  744. NULL ) != NULL )
  745. {
  746. fprintf( stderr, " %s: %s\n",
  747. GDALGetDriverShortName( hDriver ),
  748. GDALGetDriverLongName( hDriver ) );
  749. }
  750. }
  751. printf( "\n" );
  752. Usage();
  753. }
  754. /* -------------------------------------------------------------------- */
  755. /* Open input datasource. */
  756. /* -------------------------------------------------------------------- */
  757. OGRDataSourceH hSrcDS;
  758. hSrcDS = OGROpen( pszSource, FALSE, NULL );
  759. if( hSrcDS == NULL )
  760. {
  761. fprintf( stderr, "Unable to open input datasource \"%s\".\n",
  762. pszSource );
  763. fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
  764. exit( 3 );
  765. }
  766. /* -------------------------------------------------------------------- */
  767. /* Create target raster file. */
  768. /* -------------------------------------------------------------------- */
  769. GDALDatasetH hDstDS;
  770. int nLayerCount = CSLCount(papszLayers);
  771. int nBands = nLayerCount;
  772. if ( pszSQL )
  773. nBands++;
  774. // FIXME
  775. if ( nXSize == 0 )
  776. nXSize = 256;
  777. if ( nYSize == 0 )
  778. nYSize = 256;
  779. if (!bQuiet && !bFormatExplicitelySet)
  780. CheckExtensionConsistency(pszDest, pszFormat);
  781. hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands,
  782. eOutputType, papszCreateOptions );
  783. if ( hDstDS == NULL )
  784. {
  785. fprintf( stderr, "Unable to create target dataset \"%s\".\n",
  786. pszDest );
  787. fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
  788. exit( 3 );
  789. }
  790. /* -------------------------------------------------------------------- */
  791. /* If algorithm was not specified assigh default one. */
  792. /* -------------------------------------------------------------------- */
  793. if ( !pOptions )
  794. ParseAlgorithmAndOptions( szAlgNameInvDist, &eAlgorithm, &pOptions );
  795. /* -------------------------------------------------------------------- */
  796. /* Process SQL request. */
  797. /* -------------------------------------------------------------------- */
  798. if( pszSQL != NULL )
  799. {
  800. OGRLayerH hLayer;
  801. hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL,
  802. (OGRGeometryH)poSpatialFilter, NULL );
  803. if( hLayer != NULL )
  804. {
  805. // Custom layer will be rasterized in the first band.
  806. ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize, 1,
  807. bIsXExtentSet, bIsYExtentSet,
  808. dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
  809. eOutputType, eAlgorithm, pOptions,
  810. bQuiet, pfnProgress );
  811. }
  812. }
  813. /* -------------------------------------------------------------------- */
  814. /* Process each layer. */
  815. /* -------------------------------------------------------------------- */
  816. for( i = 0; i < nLayerCount; i++ )
  817. {
  818. OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
  819. if( hLayer == NULL )
  820. {
  821. fprintf( stderr, "Unable to find layer \"%s\", skipping.\n",
  822. papszLayers[i] );
  823. continue;
  824. }
  825. if( pszWHERE )
  826. {
  827. if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE )
  828. break;
  829. }
  830. if ( poSpatialFilter != NULL )
  831. OGR_L_SetSpatialFilter( hLayer, (OGRGeometryH)poSpatialFilter );
  832. // Fetch the first meaningful SRS definition
  833. if ( !pszOutputSRS )
  834. {
  835. OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( hLayer );
  836. if ( hSRS )
  837. OSRExportToWkt( hSRS, &pszOutputSRS );
  838. }
  839. ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize,
  840. i + 1 + nBands - nLayerCount,
  841. bIsXExtentSet, bIsYExtentSet,
  842. dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
  843. eOutputType, eAlgorithm, pOptions,
  844. bQuiet, pfnProgress );
  845. }
  846. /* -------------------------------------------------------------------- */
  847. /* Apply geotransformation matrix. */
  848. /* -------------------------------------------------------------------- */
  849. double adfGeoTransform[6];
  850. adfGeoTransform[0] = dfXMin;
  851. adfGeoTransform[1] = (dfXMax - dfXMin) / nXSize;
  852. adfGeoTransform[2] = 0.0;
  853. adfGeoTransform[3] = dfYMin;
  854. adfGeoTransform[4] = 0.0;
  855. adfGeoTransform[5] = (dfYMax - dfYMin) / nYSize;
  856. GDALSetGeoTransform( hDstDS, adfGeoTransform );
  857. /* -------------------------------------------------------------------- */
  858. /* Apply SRS definition if set. */
  859. /* -------------------------------------------------------------------- */
  860. if ( pszOutputSRS )
  861. {
  862. GDALSetProjection( hDstDS, pszOutputSRS );
  863. CPLFree( pszOutputSRS );
  864. }
  865. /* -------------------------------------------------------------------- */
  866. /* Cleanup */
  867. /* -------------------------------------------------------------------- */
  868. OGR_DS_Destroy( hSrcDS );
  869. GDALClose( hDstDS );
  870. OGRGeometryFactory::destroyGeometry( poSpatialFilter );
  871. CPLFree( pOptions );
  872. CSLDestroy( papszCreateOptions );
  873. CSLDestroy( argv );
  874. CSLDestroy( papszLayers );
  875. OGRCleanupAll();
  876. GDALDestroyDriverManager();
  877. return 0;
  878. }