Exemple #1
0
    void object::test<6>()
    {
        ensure("SRS handle is NULL", NULL != srs_);

        err_ = OSRSetFromUserInput(srs_, "urn:ogc:def:crs:EPSG::4326");
        ensure_equals("OSRSetFromUserInput failed", err_, OGRERR_NONE);

        char* wkt1 = NULL;
        err_ = OSRExportToWkt(srs_, &wkt1);
        ensure_equals("OSRExportToWkt failed", err_, OGRERR_NONE);
        ensure("OSRExportToWkt returned NULL", NULL != wkt1);

        err_ = OSRSetFromUserInput(srs_, "EPSGA:4326");
        ensure_equals("OSRSetFromUserInput failed", err_, OGRERR_NONE);

        char* wkt2 = NULL;
        err_ = OSRExportToWkt(srs_, &wkt2);
        ensure_equals("OSRExportToWkt failed", err_, OGRERR_NONE);
        ensure("OSRExportToWkt returned NULL", NULL != wkt2);

        ensure_equals("EPSG:4326 urn lookup not as expected",
            std::string(wkt1), std::string(wkt2));
        CPLFree(wkt1);
        CPLFree(wkt2);
    }
Exemple #2
0
void InPlaceReprojection::initialize()
{
    Filter::initialize();

    if (m_inferInputSRS)
    {
        m_inSRS = getPrevStage().getSpatialReference();
    }

#ifdef PDAL_HAVE_GDAL
    
    pdal::GlobalEnvironment::get().getGDALDebug()->addLog(log());

    m_in_ref_ptr = ReferencePtr(OSRNewSpatialReference(0), OGRSpatialReferenceDeleter());
    m_out_ref_ptr = ReferencePtr(OSRNewSpatialReference(0), OGRSpatialReferenceDeleter());

    int result = OSRSetFromUserInput(m_in_ref_ptr.get(), m_inSRS.getWKT(pdal::SpatialReference::eCompoundOK).c_str());
    if (result != OGRERR_NONE)
    {
        std::ostringstream msg;
        msg << "Could not import input spatial reference for InPlaceReprojection:: "
            << CPLGetLastErrorMsg() << " code: " << result
            << " wkt: '" << m_inSRS.getWKT() << "'";
        throw std::runtime_error(msg.str());
    }

    result = OSRSetFromUserInput(m_out_ref_ptr.get(), m_outSRS.getWKT(pdal::SpatialReference::eCompoundOK).c_str());
    if (result != OGRERR_NONE)
    {
        std::ostringstream msg;
        msg << "Could not import output spatial reference for InPlaceReprojection:: "
            << CPLGetLastErrorMsg() << " code: " << result
            << " wkt: '" << m_outSRS.getWKT() << "'";
        std::string message(msg.str());
        throw std::runtime_error(message);
    }
    m_transform_ptr = TransformPtr(OCTNewCoordinateTransformation(m_in_ref_ptr.get(), m_out_ref_ptr.get()), OSRTransformDeleter());

    if (!m_transform_ptr.get())
    {
        std::ostringstream msg;
        msg << "Could not construct CoordinateTransformation in InPlaceReprojection:: ";
        std::string message(msg.str());
        throw std::runtime_error(message);
    }

#endif

    setSpatialReference(m_outSRS);
    
    Schema& s = getSchemaRef();
    s = alterSchema(s);


    return;
}
Exemple #3
0
void Reprojection::initialize()
{
    Filter::initialize();

    checkImpedance();

    if (m_inferInputSRS)
    {
        m_inSRS = getPrevStage().getSpatialReference();
    }

#ifdef PDAL_HAVE_GDAL

    m_gdal_debug = boost::shared_ptr<pdal::gdal::Debug>( new pdal::gdal::Debug(isDebug(), log()));

    m_in_ref_ptr = ReferencePtr(OSRNewSpatialReference(0), OGRSpatialReferenceDeleter());
    m_out_ref_ptr = ReferencePtr(OSRNewSpatialReference(0), OGRSpatialReferenceDeleter());
    
    int result = OSRSetFromUserInput(m_in_ref_ptr.get(), m_inSRS.getWKT(pdal::SpatialReference::eCompoundOK).c_str());
    if (result != OGRERR_NONE) 
    {
        std::ostringstream msg; 
        msg << "Could not import input spatial reference for ReprojectionFilter:: " 
            << CPLGetLastErrorMsg() << " code: " << result 
            << " wkt: '" << m_inSRS.getWKT() << "'";
        throw std::runtime_error(msg.str());
    }
    
    result = OSRSetFromUserInput(m_out_ref_ptr.get(), m_outSRS.getWKT(pdal::SpatialReference::eCompoundOK).c_str());
    if (result != OGRERR_NONE) 
    {
        std::ostringstream msg; 
        msg << "Could not import output spatial reference for ReprojectionFilter:: " 
            << CPLGetLastErrorMsg() << " code: " << result 
            << " wkt: '" << m_outSRS.getWKT() << "'";
        std::string message(msg.str());
        throw std::runtime_error(message);
    }
    m_transform_ptr = TransformPtr(OCTNewCoordinateTransformation( m_in_ref_ptr.get(), m_out_ref_ptr.get()), OSRTransformDeleter());
    
    if (!m_transform_ptr.get())
    {
        std::ostringstream msg; 
        msg << "Could not construct CoordinateTransformation in ReprojectionFilter:: ";
        std::string message(msg.str());
        throw std::runtime_error(message);
    }    
    
#endif
    
    setSpatialReference(m_outSRS);

    updateBounds();

    return;
}
Exemple #4
0
void ReprojectionFilter::ready(PointTableRef table)
{
    if (m_inferInputSRS)
    {
        m_inSRS = table.spatialRef();
        if (m_inSRS.getWKT().empty())
            throw pdal_error("Source data has no spatial reference and none "
                "is specified with the 'in_srs' option.");
    }

    m_in_ref_ptr = ReferencePtr(OSRNewSpatialReference(0),
        OGRSpatialReferenceDeleter());
    m_out_ref_ptr = ReferencePtr(OSRNewSpatialReference(0),
        OGRSpatialReferenceDeleter());

    int result =
        OSRSetFromUserInput(m_in_ref_ptr.get(),
            m_inSRS.getWKT(pdal::SpatialReference::eCompoundOK).c_str());
    if (result != OGRERR_NONE)
    {
        std::ostringstream msg;
        msg << "Invalid input spatial reference '" << m_inSRS.getWKT() <<
            "'.  This is usually caused by a bad value for the 'in_srs'"
            "option or an invalid spatial reference in the source file.";
        throw pdal_error(msg.str());
    }

    result = OSRSetFromUserInput(m_out_ref_ptr.get(),
        m_outSRS.getWKT(pdal::SpatialReference::eCompoundOK).c_str());
    if (result != OGRERR_NONE)
    {
        std::ostringstream msg;
        msg << "Invalid output spatial reference '" << m_outSRS.getWKT() <<
            "'.  This is usually caused by a bad value for the 'out_srs'"
            "option.";
        throw pdal_error(msg.str());
    }
    m_transform_ptr = TransformPtr(
        OCTNewCoordinateTransformation(m_in_ref_ptr.get(),
            m_out_ref_ptr.get()), OSRTransformDeleter());

    if (!m_transform_ptr.get())
    {
        std::string msg = "Could not construct CoordinateTransformation in "
            "ReprojectionFilter:: ";
        throw std::runtime_error(msg);
    }

    setSpatialReference(m_outSRS);
}
Exemple #5
0
    void object::test<7 >()
    {
        ensure("SRS handle is NULL", NULL != srs_);

        err_ = OSRSetFromUserInput(srs_, "urn:ogc:def:crs:OGC::AUTO42001:-117:33");
        ensure_equals("OSRSetFromUserInput failed", err_, OGRERR_NONE);

        char* wkt1 = NULL;
        err_ = OSRExportToWkt(srs_, &wkt1);
        ensure_equals("OSRExportToWkt failed", err_, OGRERR_NONE);
        ensure("OSRExportToWkt returned NULL", NULL != wkt1);

        std::string expect("PROJCS[\"UTM Zone 11, Northern Hemisphere\","
                           "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\","
                           "SPHEROID[\"WGS 84\",6378137,298.257223563,"
                           "AUTHORITY[\"EPSG\",\"7030\"]],"
                           "AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,"
                           "AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,"
                           "AUTHORITY[\"EPSG\",\"9122\"]],"
                           "AUTHORITY[\"EPSG\",\"4326\"]],"
                           "PROJECTION[\"Transverse_Mercator\"],"
                           "PARAMETER[\"latitude_of_origin\",0],"
                           "PARAMETER[\"central_meridian\",-117],"
                           "PARAMETER[\"scale_factor\",0.9996],"
                           "PARAMETER[\"false_easting\",500000],"
                           "PARAMETER[\"false_northing\",0],"
                           "UNIT[\"Meter\",1,AUTHORITY[\"EPSG\",\"9001\"]]]");

        ensure_equals("AUTO42001 urn lookup not as expected", std::string(wkt1), expect);
        CPLFree(wkt1);
    }
Exemple #6
0
    void object::test<5>()
    {
        ensure("SRS handle is NULL", nullptr != srs_);

        err_ = OSRSetFromUserInput(srs_, "urn:ogc:def:crs:OGC:1.3:CRS84");
        ensure_equals("OSRSetFromUserInput failed", err_, OGRERR_NONE);

        char* wkt1 = nullptr;
        err_ = OSRExportToWkt(srs_, &wkt1);
        ensure_equals("OSRExportToWkt failed", err_, OGRERR_NONE);
        ensure("OSRExportToWkt returned NULL", nullptr != wkt1);

        CPLFree(wkt1);
    }
static QString _setSourceCrsFromESRI(const QString& wkt)
{
    QString ret;

    QString wkt2("ESRI::" + wkt);
    OGRSpatialReferenceH hSRS = OSRNewSpatialReference(NULL);
    QByteArray arr = wkt2.toUtf8();
    if (OSRSetFromUserInput(hSRS, arr.constData()) == OGRERR_NONE)
    {
        char * ppszReturn = 0;
        if (OSRExportToProj4(hSRS, &ppszReturn) == OGRERR_NONE && ppszReturn != 0)
        {
            ret = ppszReturn;
        }
    }
    OSRDestroySpatialReference(hSRS);

    return ret;
}
Exemple #8
0
static bool IsValidSRS( const char *pszUserInput )

{
    OGRSpatialReferenceH hSRS;
    bool bRes = true;

    CPLErrorReset();

    hSRS = OSRNewSpatialReference( nullptr );
    if( OSRSetFromUserInput( hSRS, pszUserInput ) != OGRERR_NONE )
    {
        bRes = false;
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Translating source or target SRS failed:\n%s",
                  pszUserInput );
    }

    OSRDestroySpatialReference( hSRS );

    return bRes;
}
char *SanitizeSRS( const char *pszUserInput )

{
    OGRSpatialReferenceH hSRS;
    char *pszResult = NULL;

    CPLErrorReset();
    
    hSRS = OSRNewSpatialReference( NULL );
    if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
        OSRExportToWkt( hSRS, &pszResult );
    else
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Translating source or target SRS failed:\n%s",
                  pszUserInput );
        exit( 1 );
    }
    
    OSRDestroySpatialReference( hSRS );

    return pszResult;
}
int QgsRasterCalculator::processCalculation( QProgressDialog* p )
{
  //prepare search string / tree
  QString errorString;
  QgsRasterCalcNode* calcNode = QgsRasterCalcNode::parseRasterCalcString( mFormulaString, errorString );
  if ( !calcNode )
  {
    //error
  }

  double targetGeoTransform[6];
  outputGeoTransform( targetGeoTransform );

  //open all input rasters for reading
  QMap< QString, GDALRasterBandH > mInputRasterBands; //raster references and corresponding scanline data
  QMap< QString, QgsRasterMatrix* > inputScanLineData; //stores raster references and corresponding scanline data
  QVector< GDALDatasetH > mInputDatasets; //raster references and corresponding dataset

  QVector<QgsRasterCalculatorEntry>::const_iterator it = mRasterEntries.constBegin();
  for ( ; it != mRasterEntries.constEnd(); ++it )
  {
    if ( !it->raster ) // no raster layer in entry
    {
      return 2;
    }
    GDALDatasetH inputDataset = GDALOpen( TO8( it->raster->source() ), GA_ReadOnly );
    if ( inputDataset == NULL )
    {
      return 2;
    }

    //check if the input dataset is south up or rotated. If yes, use GDALAutoCreateWarpedVRT to create a north up raster
    double inputGeoTransform[6];
    if ( GDALGetGeoTransform( inputDataset, inputGeoTransform ) == CE_None
         && ( inputGeoTransform[1] < 0.0
              || inputGeoTransform[2] != 0.0
              || inputGeoTransform[4] != 0.0
              || inputGeoTransform[5] > 0.0 ) )
    {
      GDALDatasetH vDataset = GDALAutoCreateWarpedVRT( inputDataset, NULL, NULL, GRA_NearestNeighbour, 0.2, NULL );
      mInputDatasets.push_back( vDataset );
      mInputDatasets.push_back( inputDataset );
      inputDataset = vDataset;
    }
    else
    {
      mInputDatasets.push_back( inputDataset );
    }


    GDALRasterBandH inputRasterBand = GDALGetRasterBand( inputDataset, it->bandNumber );
    if ( inputRasterBand == NULL )
    {
      return 2;
    }

    int nodataSuccess;
    double nodataValue = GDALGetRasterNoDataValue( inputRasterBand, &nodataSuccess );

    mInputRasterBands.insert( it->ref, inputRasterBand );
    inputScanLineData.insert( it->ref, new QgsRasterMatrix( mNumOutputColumns, 1, new float[mNumOutputColumns], nodataValue ) );
  }

  //open output dataset for writing
  GDALDriverH outputDriver = openOutputDriver();
  if ( outputDriver == NULL )
  {
    return 1;
  }
  GDALDatasetH outputDataset = openOutputFile( outputDriver );

  //copy the projection info from the first input raster
  if ( mRasterEntries.size() > 0 )
  {
    QgsRasterLayer* rl = mRasterEntries.at( 0 ).raster;
    if ( rl )
    {
      char* crsWKT = 0;
      OGRSpatialReferenceH ogrSRS = OSRNewSpatialReference( NULL );
      if ( OSRSetFromUserInput( ogrSRS, rl->crs().authid().toUtf8().constData() ) == OGRERR_NONE )
      {
        OSRExportToWkt( ogrSRS, &crsWKT );
        GDALSetProjection( outputDataset, crsWKT );
      }
      else
      {
        GDALSetProjection( outputDataset, TO8( rl->crs().toWkt() ) );
      }
      OSRDestroySpatialReference( ogrSRS );
      CPLFree( crsWKT );
    }
  }


  GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset, 1 );

  float outputNodataValue = -FLT_MAX;
  GDALSetRasterNoDataValue( outputRasterBand, outputNodataValue );

  float* resultScanLine = ( float * ) CPLMalloc( sizeof( float ) * mNumOutputColumns );

  if ( p )
  {
    p->setMaximum( mNumOutputRows );
  }

  QgsRasterMatrix resultMatrix;

  //read / write line by line
  for ( int i = 0; i < mNumOutputRows; ++i )
  {
    if ( p )
    {
      p->setValue( i );
    }

    if ( p && p->wasCanceled() )
    {
      break;
    }

    //fill buffers
    QMap< QString, QgsRasterMatrix* >::iterator bufferIt = inputScanLineData.begin();
    for ( ; bufferIt != inputScanLineData.end(); ++bufferIt )
    {
      double sourceTransformation[6];
      GDALRasterBandH sourceRasterBand = mInputRasterBands[bufferIt.key()];
      GDALGetGeoTransform( GDALGetBandDataset( sourceRasterBand ), sourceTransformation );
      //the function readRasterPart calls GDALRasterIO (and ev. does some conversion if raster transformations are not the same)
      readRasterPart( targetGeoTransform, 0, i, mNumOutputColumns, 1, sourceTransformation, sourceRasterBand, bufferIt.value()->data() );
    }

    if ( calcNode->calculate( inputScanLineData, resultMatrix ) )
    {
      bool resultIsNumber = resultMatrix.isNumber();
      float* calcData;

      if ( resultIsNumber ) //scalar result. Insert number for every pixel
      {
        calcData = new float[mNumOutputColumns];
        for ( int j = 0; j < mNumOutputColumns; ++j )
        {
          calcData[j] = resultMatrix.number();
        }
      }
      else //result is real matrix
      {
        calcData = resultMatrix.data();
      }

      //replace all matrix nodata values with output nodatas
      for ( int j = 0; j < mNumOutputColumns; ++j )
      {
        if ( calcData[j] == resultMatrix.nodataValue() )
        {
          calcData[j] = outputNodataValue;
        }
      }

      //write scanline to the dataset
      if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, mNumOutputColumns, 1, calcData, mNumOutputColumns, 1, GDT_Float32, 0, 0 ) != CE_None )
      {
        qWarning( "RasterIO error!" );
      }

      if ( resultIsNumber )
      {
        delete[] calcData;
      }
    }

  }

  if ( p )
  {
    p->setValue( mNumOutputRows );
  }

  //close datasets and release memory
  delete calcNode;
  QMap< QString, QgsRasterMatrix* >::iterator bufferIt = inputScanLineData.begin();
  for ( ; bufferIt != inputScanLineData.end(); ++bufferIt )
  {
    delete bufferIt.value();
  }
  inputScanLineData.clear();

  QVector< GDALDatasetH >::iterator datasetIt = mInputDatasets.begin();
  for ( ; datasetIt != mInputDatasets.end(); ++ datasetIt )
  {
    GDALClose( *datasetIt );
  }

  if ( p && p->wasCanceled() )
  {
    //delete the dataset without closing (because it is faster)
    GDALDeleteDataset( outputDriver, mOutputFile.toLocal8Bit().data() );
    return 3;
  }
  GDALClose( outputDataset );
  CPLFree( resultScanLine );
  return 0;
}
Exemple #11
0
 SpatialRef(const std::string& srs)
 {
     newRef(OSRNewSpatialReference(""));
     OSRSetFromUserInput(get(), srs.data());
 }
Exemple #12
0
/**
 * \private \memberof mapcache_source_gdal
 * \sa mapcache_source::render_metatile()
 */
void _mapcache_source_gdal_render_metatile(mapcache_context *ctx, mapcache_metatile *tile)
{
  mapcache_source_gdal *gdal = (mapcache_source_gdal*)tile->tile.tileset->source;
  char *srcSRS = "", *dstSRS;
  mapcache_buffer *data = mapcache_buffer_create(0,ctx->pool);
  GC_CHECK_ERROR(ctx);
  GDALDatasetH  hDataset;

  GDALAllRegister();
  OGRSpatialReferenceH hSRS;
  CPLErrorReset();

  hSRS = OSRNewSpatialReference( NULL );
  if( OSRSetFromUserInput( hSRS, tile->tile.grid->srs ) == OGRERR_NONE )
    OSRExportToWkt( hSRS, &dstSRS );
  else {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"failed to parse gdal srs %s",tile->tile.grid->srs);
    return;
  }

  OSRDestroySpatialReference( hSRS );

  hDataset = GDALOpen( gdal->datastr, GA_ReadOnly );
  if( hDataset == NULL ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"GDAL failed to open %s",gdal->datastr);
    return;
  }

  /* -------------------------------------------------------------------- */
  /*      Check that there's at least one raster band                     */
  /* -------------------------------------------------------------------- */
  if ( GDALGetRasterCount(hDataset) == 0 ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"raster %s has no bands",gdal->datastr);
    return;
  }

  if( GDALGetProjectionRef( hDataset ) != NULL
      && strlen(GDALGetProjectionRef( hDataset )) > 0 )
    srcSRS = apr_pstrdup(ctx->pool,GDALGetProjectionRef( hDataset ));

  else if( GDALGetGCPProjection( hDataset ) != NULL
           && strlen(GDALGetGCPProjection(hDataset)) > 0
           && GDALGetGCPCount( hDataset ) > 1 )
    srcSRS = apr_pstrdup(ctx->pool,GDALGetGCPProjection( hDataset ));

  GDALDriverH hDriver = GDALGetDriverByName( "MEM" );
  GDALDatasetH hDstDS;
  /* -------------------------------------------------------------------- */
  /*      Create a transformation object from the source to               */
  /*      destination coordinate system.                                  */
  /* -------------------------------------------------------------------- */
  void *hTransformArg =
    GDALCreateGenImgProjTransformer( hDataset, srcSRS,
                                     NULL, dstSRS,
                                     TRUE, 1000.0, 0 );

  if( hTransformArg == NULL ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal failed to create SRS transformation object");
    return;
  }

  /* -------------------------------------------------------------------- */
  /*      Get approximate output definition.                              */
  /* -------------------------------------------------------------------- */
  int nPixels, nLines;
  double adfDstGeoTransform[6];
  if( GDALSuggestedWarpOutput( hDataset,
                               GDALGenImgProjTransform, hTransformArg,
                               adfDstGeoTransform, &nPixels, &nLines )
      != CE_None ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal failed to create suggested warp output");
    return;
  }

  GDALDestroyGenImgProjTransformer( hTransformArg );
  double dfXRes = (tile->bbox[2] - tile->bbox[0]) / tile->sx;
  double dfYRes = (tile->bbox[3] - tile->bbox[1]) / tile->sy;

  adfDstGeoTransform[0] = tile->bbox[0];
  adfDstGeoTransform[3] = tile->bbox[3];
  adfDstGeoTransform[1] = dfXRes;
  adfDstGeoTransform[5] = -dfYRes;
  hDstDS = GDALCreate( hDriver, "tempd_gdal_image", tile->sx, tile->sy, 4, GDT_Byte, NULL );

  /* -------------------------------------------------------------------- */
  /*      Write out the projection definition.                            */
  /* -------------------------------------------------------------------- */
  GDALSetProjection( hDstDS, dstSRS );
  GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
  char               **papszWarpOptions = NULL;
  papszWarpOptions = CSLSetNameValue( papszWarpOptions, "INIT", "0" );



  /* -------------------------------------------------------------------- */
  /*      Create a transformation object from the source to               */
  /*      destination coordinate system.                                  */
  /* -------------------------------------------------------------------- */
  GDALTransformerFunc pfnTransformer = NULL;
  void               *hGenImgProjArg=NULL, *hApproxArg=NULL;
  hTransformArg = hGenImgProjArg =
                    GDALCreateGenImgProjTransformer( hDataset, srcSRS,
                        hDstDS, dstSRS,
                        TRUE, 1000.0, 0 );

  if( hTransformArg == NULL )
    exit( 1 );

  pfnTransformer = GDALGenImgProjTransform;

  hTransformArg = hApproxArg =
                    GDALCreateApproxTransformer( GDALGenImgProjTransform,
                        hGenImgProjArg, 0.125 );
  pfnTransformer = GDALApproxTransform;

  /* -------------------------------------------------------------------- */
  /*      Now actually invoke the warper to do the work.                  */
  /* -------------------------------------------------------------------- */
  GDALSimpleImageWarp( hDataset, hDstDS, 0, NULL,
                       pfnTransformer, hTransformArg,
                       GDALDummyProgress, NULL, papszWarpOptions );

  CSLDestroy( papszWarpOptions );

  if( hApproxArg != NULL )
    GDALDestroyApproxTransformer( hApproxArg );

  if( hGenImgProjArg != NULL )
    GDALDestroyGenImgProjTransformer( hGenImgProjArg );

  if(GDALGetRasterCount(hDstDS) != 4) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal did not create a 4 band image");
    return;
  }

  GDALRasterBandH *redband, *greenband, *blueband, *alphaband;

  redband = GDALGetRasterBand(hDstDS,1);
  greenband = GDALGetRasterBand(hDstDS,2);
  blueband = GDALGetRasterBand(hDstDS,3);
  alphaband = GDALGetRasterBand(hDstDS,4);

  unsigned char *rasterdata = apr_palloc(ctx->pool,tile->sx*tile->sy*4);
  data->buf = rasterdata;
  data->avail = tile->sx*tile->sy*4;
  data->size = tile->sx*tile->sy*4;

  GDALRasterIO(redband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  GDALRasterIO(greenband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+1),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  GDALRasterIO(blueband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+2),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  if(GDALGetRasterCount(hDataset)==4)
    GDALRasterIO(alphaband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+3),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  else {
    unsigned char *alphaptr;
    int i;
    for(alphaptr = rasterdata+3, i=0; i<tile->sx*tile->sy; i++, alphaptr+=4) {
      *alphaptr = 255;
    }
  }

  tile->imdata = mapcache_image_create(ctx);
  tile->imdata->w = tile->sx;
  tile->imdata->h = tile->sy;
  tile->imdata->stride = tile->sx * 4;
  tile->imdata->data = rasterdata;


  GDALClose( hDstDS );
  GDALClose( hDataset);
}
GDALRasterizeOptions *GDALRasterizeOptionsNew(char** papszArgv,
                                                      GDALRasterizeOptionsForBinary* psOptionsForBinary)
{
    GDALRasterizeOptions *psOptions = new GDALRasterizeOptions;

    psOptions->pszFormat = CPLStrdup("GTiff");
    psOptions->pfnProgress = GDALDummyProgress;
    psOptions->pProgressData = NULL;
    psOptions->bCreateOutput = FALSE;
    psOptions->b3D = FALSE;
    psOptions->bInverse = FALSE;
    memset(&(psOptions->sEnvelop), 0, sizeof(psOptions->sEnvelop));
    psOptions->papszCreationOptions = NULL;
    psOptions->papszLayers = NULL;
    psOptions->pszSQL = NULL;
    psOptions->pszDialect = NULL;
    psOptions->pszBurnAttribute = NULL;
    psOptions->pszWHERE = NULL;
    psOptions->papszRasterizeOptions = NULL;
    psOptions->dfXRes = 0;
    psOptions->dfYRes = 0;
    psOptions->bCreateOutput = FALSE;
    psOptions->eOutputType = GDT_Float64;
    psOptions->bNoDataSet = FALSE;
    psOptions->dfNoData = 0;
    psOptions->bGotBounds = FALSE;
    psOptions->nXSize = 0;
    psOptions->nYSize = 0;
    psOptions->hSRS = NULL;
    psOptions->bTargetAlignedPixels = FALSE;

/* -------------------------------------------------------------------- */
/*      Handle command line arguments.                                  */
/* -------------------------------------------------------------------- */
    int argc = CSLCount(papszArgv);
    for( int i = 0; i < argc; i++ )
    {
        if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
        {
            ++i;
            CPLFree(psOptions->pszFormat);
            psOptions->pszFormat = CPLStrdup(papszArgv[i]);
            psOptions->bCreateOutput = TRUE;
            if( psOptionsForBinary )
            {
                psOptionsForBinary->bFormatExplicitlySet = TRUE;
            }
        }

        else if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
        {
            if( psOptionsForBinary )
                psOptionsForBinary->bQuiet = TRUE;
        }

        else if( EQUAL(papszArgv[i],"-a") && i < argc-1 )
        {
            CPLFree(psOptions->pszBurnAttribute);
            psOptions->pszBurnAttribute = CPLStrdup(papszArgv[++i]);
        }
        else if( EQUAL(papszArgv[i],"-b") && i < argc-1 )
        {
            if (strchr(papszArgv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( papszArgv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    psOptions->anBandList.push_back(atoi(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(papszArgv[i+1]))
                {
                    psOptions->anBandList.push_back(atoi(papszArgv[i+1]));
                    i += 1;
                }
            }
        }
        else if( EQUAL(papszArgv[i],"-3d")  )
        {
            psOptions->b3D = TRUE;
            psOptions->papszRasterizeOptions =
                CSLSetNameValue( psOptions->papszRasterizeOptions, "BURN_VALUE_FROM", "Z");
        }
        else if( EQUAL(papszArgv[i],"-add")  )
        {
            psOptions->papszRasterizeOptions =
                CSLSetNameValue( psOptions->papszRasterizeOptions, "MERGE_ALG", "ADD");
        }
        else if( EQUAL(papszArgv[i],"-chunkysize") && i < argc-1 )
        {
            psOptions->papszRasterizeOptions =
                CSLSetNameValue( psOptions->papszRasterizeOptions, "CHUNKYSIZE",
                                 papszArgv[++i] );
        }
        else if( EQUAL(papszArgv[i],"-i")  )
        {
            psOptions->bInverse = TRUE;
        }
        else if( EQUAL(papszArgv[i],"-at")  )
        {
            psOptions->papszRasterizeOptions =
                CSLSetNameValue( psOptions->papszRasterizeOptions, "ALL_TOUCHED", "TRUE" );
        }
        else if( EQUAL(papszArgv[i],"-burn") && i < argc-1 )
        {
            if (strchr(papszArgv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( papszArgv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    psOptions->adfBurnValues.push_back(CPLAtof(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(papszArgv[i+1]))
                {
                    psOptions->adfBurnValues.push_back(CPLAtof(papszArgv[i+1]));
                    i += 1;
                }
            }
        }
        else if( EQUAL(papszArgv[i],"-where") && i < argc-1 )
        {
            CPLFree(psOptions->pszWHERE);
            psOptions->pszWHERE = CPLStrdup(papszArgv[++i]);
        }
        else if( EQUAL(papszArgv[i],"-l") && i < argc-1 )
        {
            psOptions->papszLayers = CSLAddString( psOptions->papszLayers, papszArgv[++i] );
        }
        else if( EQUAL(papszArgv[i],"-sql") && i < argc-1 )
        {
            CPLFree(psOptions->pszSQL);
            psOptions->pszSQL = CPLStrdup(papszArgv[++i]);
        }
        else if( EQUAL(papszArgv[i],"-dialect") && i < argc-1 )
        {
            CPLFree(psOptions->pszDialect);
            psOptions->pszDialect = CPLStrdup(papszArgv[++i]);
        }
        else if( EQUAL(papszArgv[i],"-init") && i < argc - 1 )
        {
            if (strchr(papszArgv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( papszArgv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    psOptions->adfInitVals.push_back(CPLAtof(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(papszArgv[i+1]))
                {
                    psOptions->adfInitVals.push_back(CPLAtof(papszArgv[i+1]));
                    i += 1;
                }
            }
            psOptions->bCreateOutput = TRUE;
        }
        else if( EQUAL(papszArgv[i],"-a_nodata") && i < argc - 1 )
        {
            psOptions->dfNoData = CPLAtof(papszArgv[i+1]);
            psOptions->bNoDataSet = TRUE;
            i += 1;
            psOptions->bCreateOutput = TRUE;
        }
        else if( EQUAL(papszArgv[i],"-a_srs") && i < argc-1 )
        {
            OSRDestroySpatialReference(psOptions->hSRS);
            psOptions->hSRS = OSRNewSpatialReference( NULL );

            if( OSRSetFromUserInput(psOptions->hSRS, papszArgv[i+1]) != OGRERR_NONE )
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Failed to process SRS definition: %s",
                         papszArgv[i+1] );
                GDALRasterizeOptionsFree(psOptions);
                return NULL;
            }

            i++;
            psOptions->bCreateOutput = TRUE;
        }

        else if( EQUAL(papszArgv[i],"-te") && i < argc - 4 )
        {
            psOptions->sEnvelop.MinX = CPLAtof(papszArgv[++i]);
            psOptions->sEnvelop.MinY = CPLAtof(papszArgv[++i]);
            psOptions->sEnvelop.MaxX = CPLAtof(papszArgv[++i]);
            psOptions->sEnvelop.MaxY = CPLAtof(papszArgv[++i]);
            psOptions->bGotBounds = TRUE;
            psOptions->bCreateOutput = TRUE;
        }
        else if( EQUAL(papszArgv[i],"-a_ullr") && i < argc - 4 )
        {
            psOptions->sEnvelop.MinX = CPLAtof(papszArgv[++i]);
            psOptions->sEnvelop.MaxY = CPLAtof(papszArgv[++i]);
            psOptions->sEnvelop.MaxX = CPLAtof(papszArgv[++i]);
            psOptions->sEnvelop.MinY = CPLAtof(papszArgv[++i]);
            psOptions->bGotBounds = TRUE;
            psOptions->bCreateOutput = TRUE;
        }
        else if( EQUAL(papszArgv[i],"-co") && i < argc-1 )
        {
            psOptions->papszCreationOptions = CSLAddString( psOptions->papszCreationOptions, papszArgv[++i] );
            psOptions->bCreateOutput = TRUE;
        }
        else if( EQUAL(papszArgv[i],"-ot") && i < argc-1 )
        {
            int iType;

            for( iType = 1; iType < GDT_TypeCount; iType++ )
            {
                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
                             papszArgv[i+1]) )
                {
                    psOptions->eOutputType = (GDALDataType) iType;
                }
            }

            if( psOptions->eOutputType == GDT_Unknown )
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Unknown output pixel type: %s", papszArgv[i+1] );
                GDALRasterizeOptionsFree(psOptions);
                return NULL;
            }
            i++;
            psOptions->bCreateOutput = TRUE;
        }
        else if( (EQUAL(papszArgv[i],"-ts") || EQUAL(papszArgv[i],"-outsize")) && i < argc-2 )
        {
            psOptions->nXSize = atoi(papszArgv[++i]);
            psOptions->nYSize = atoi(papszArgv[++i]);
            if (psOptions->nXSize <= 0 || psOptions->nYSize <= 0)
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Wrong value for -outsize parameter.");
                GDALRasterizeOptionsFree(psOptions);
                return NULL;
            }
            psOptions->bCreateOutput = TRUE;
        }
        else if( EQUAL(papszArgv[i],"-tr") && i < argc-2 )
        {
            psOptions->dfXRes = CPLAtof(papszArgv[++i]);
            psOptions->dfYRes = fabs(CPLAtof(papszArgv[++i]));
            if( psOptions->dfXRes == 0 || psOptions->dfYRes == 0 )
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Wrong value for -tr parameter.");
                GDALRasterizeOptionsFree(psOptions);
                return NULL;
            }
            psOptions->bCreateOutput = TRUE;
        }
        else if( EQUAL(papszArgv[i],"-tap") )
        {
            psOptions->bTargetAlignedPixels = TRUE;
            psOptions->bCreateOutput = TRUE;
        }

        else if( papszArgv[i][0] == '-' )
        {
            CPLError(CE_Failure, CPLE_NotSupported,
                     "Unknown option name '%s'", papszArgv[i]);
            GDALRasterizeOptionsFree(psOptions);
            return NULL;
        }
        else if( psOptionsForBinary && psOptionsForBinary->pszSource == NULL )
        {
            psOptionsForBinary->pszSource = CPLStrdup(papszArgv[i]);
        }
        else if( psOptionsForBinary && psOptionsForBinary->pszDest == NULL )
        {
            psOptionsForBinary->pszDest = CPLStrdup(papszArgv[i]);
        }
        else
        {
            CPLError(CE_Failure, CPLE_NotSupported,
                     "Too many command options '%s'", papszArgv[i]);
            GDALRasterizeOptionsFree(psOptions);
            return NULL;
        }
    }

    if( psOptions->adfBurnValues.size() == 0 &&
        psOptions->pszBurnAttribute == NULL && !(psOptions->b3D) )
    {
        if( psOptionsForBinary == NULL )
            psOptions->adfBurnValues.push_back(255);
        else
        {
            CPLError(CE_Failure, CPLE_NotSupported, "At least one of -3d, -burn or -a required." );
            GDALRasterizeOptionsFree(psOptions);
            return NULL;
        }
    }

    if( psOptions->bCreateOutput )
    {
        if( psOptions->dfXRes == 0 && psOptions->dfYRes == 0 && psOptions->nXSize == 0 && psOptions->nYSize == 0 )
        {
            CPLError(CE_Failure, CPLE_NotSupported, "'-tr xres yres' or '-ts xsize ysize' is required." );
            GDALRasterizeOptionsFree(psOptions);
            return NULL;
        }

        if (psOptions->bTargetAlignedPixels && psOptions->dfXRes == 0 && psOptions->dfYRes == 0)
        {
            CPLError(CE_Failure, CPLE_NotSupported, "-tap option cannot be used without using -tr.");
            GDALRasterizeOptionsFree(psOptions);
            return NULL;;
        }

        if( psOptions->anBandList.size() != 0 )
        {
            CPLError(CE_Failure, CPLE_NotSupported, "-b option cannot be used when creating a GDAL dataset." );
            GDALRasterizeOptionsFree(psOptions);
            return NULL;
        }

        int nBandCount = 1;

        if (psOptions->adfBurnValues.size() != 0)
            nBandCount = static_cast<int>(psOptions->adfBurnValues.size());

        if ((int)psOptions->adfInitVals.size() > nBandCount)
            nBandCount = static_cast<int>(psOptions->adfInitVals.size());

        if (psOptions->adfInitVals.size() == 1)
        {
            for(int i=1;i<=nBandCount - 1;i++)
                psOptions->adfInitVals.push_back( psOptions->adfInitVals[0] );
        }

        int i;
        for(i=1;i<=nBandCount;i++)
            psOptions->anBandList.push_back( i );
    }
    else
    {
        if( psOptions->anBandList.size() == 0 )
            psOptions->anBandList.push_back( 1 );
    }

    if( psOptions->pszDialect != NULL && psOptions->pszWHERE != NULL && psOptions->pszSQL == NULL )
    {
        CPLError( CE_Warning, CPLE_AppDefined,
                  "-dialect is ignored with -where. Use -sql instead" );
    }

    if( psOptionsForBinary )
    {
        psOptionsForBinary->bCreateOutput = psOptions->bCreateOutput;
        psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
    }

    return psOptions;
}
Exemple #14
0
MAIN_START(argc, argv)
{
    // Check that we are running against at least GDAL 1.4.
    // Note to developers: if we use newer API, please change the requirement.
    if( atoi(GDALVersionInfo("VERSION_NUM")) < 1400 )
    {
        fprintf(stderr,
                "At least, GDAL >= 1.4.0 is required for this version of %s, "
                "which was compiled against GDAL %s\n",
                argv[0], GDAL_RELEASE_NAME);
        exit(1);
    }

    GDALAllRegister();
    OGRRegisterAll();

    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

/* -------------------------------------------------------------------- */
/*      Get commandline arguments other than the GDAL raster filenames. */
/* -------------------------------------------------------------------- */
    const char* pszIndexLayerName = nullptr;
    const char *index_filename = nullptr;
    const char *tile_index = "location";
    const char* pszDriverName = nullptr;
    size_t nMaxFieldSize = 254;
    bool write_absolute_path = false;
    char* current_path = nullptr;
    bool skip_different_projection = false;
    const char *pszTargetSRS = "";
    bool bSetTargetSRS = false;
    const char* pszSrcSRSName = nullptr;
    int i_SrcSRSName = -1;
    bool bSrcSRSFormatSpecified = false;
    SrcSRSFormat eSrcSRSFormat = FORMAT_AUTO;

    int iArg = 1;  // Used after for.
    for( ; iArg < argc; iArg++ )
    {
        if( EQUAL(argv[iArg], "--utility_version") )
        {
            printf("%s was compiled against GDAL %s and is running against "
                   "GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            CSLDestroy( argv );
            return 0;
        }
        else if( EQUAL(argv[iArg],"--help") )
            Usage(nullptr);
        else if( (strcmp(argv[iArg],"-f") == 0 || strcmp(argv[iArg],"-of") == 0) )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszDriverName = argv[++iArg];
        }
        else if( strcmp(argv[iArg],"-lyr_name") == 0 )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszIndexLayerName = argv[++iArg];
        }
        else if( strcmp(argv[iArg],"-tileindex") == 0 )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            tile_index = argv[++iArg];
        }
        else if( strcmp(argv[iArg],"-t_srs") == 0 )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszTargetSRS = argv[++iArg];
            bSetTargetSRS = true;
        }
        else if ( strcmp(argv[iArg],"-write_absolute_path") == 0 )
        {
            write_absolute_path = true;
        }
        else if ( strcmp(argv[iArg],"-skip_different_projection") == 0 )
        {
            skip_different_projection = true;
        }
        else if( strcmp(argv[iArg], "-src_srs_name") == 0 )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszSrcSRSName = argv[++iArg];
        }
        else if( strcmp(argv[iArg], "-src_srs_format") == 0 )
        {
            const char* pszFormat;
            bSrcSRSFormatSpecified = true;
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszFormat = argv[++iArg];
            if( EQUAL(pszFormat, "AUTO") )
                eSrcSRSFormat = FORMAT_AUTO;
            else if( EQUAL(pszFormat, "WKT") )
                eSrcSRSFormat = FORMAT_WKT;
            else if( EQUAL(pszFormat, "EPSG") )
                eSrcSRSFormat = FORMAT_EPSG;
            else if( EQUAL(pszFormat, "PROJ") )
                eSrcSRSFormat = FORMAT_PROJ;
        }
        else if( argv[iArg][0] == '-' )
            Usage(CPLSPrintf("Unknown option name '%s'", argv[iArg]));
        else if( index_filename == nullptr )
        {
            index_filename = argv[iArg];
            iArg++;
            break;
        }
    }

    if( index_filename == nullptr )
        Usage("No index filename specified.");
    if( iArg == argc )
        Usage("No file to index specified.");
    if( bSrcSRSFormatSpecified && pszSrcSRSName == nullptr )
        Usage("-src_srs_name must be specified when -src_srs_format is "
              "specified.");

/* -------------------------------------------------------------------- */
/*      Create and validate target SRS if given.                        */
/* -------------------------------------------------------------------- */
    OGRSpatialReferenceH hTargetSRS = nullptr;
    if( bSetTargetSRS )
    {
        if( skip_different_projection )
        {
            fprintf( stderr,
                     "Warning : -skip_different_projection does not apply "
                     "when -t_srs is requested.\n" );
        }
        hTargetSRS = OSRNewSpatialReference("");
        OSRSetAxisMappingStrategy(hTargetSRS, OAMS_TRADITIONAL_GIS_ORDER);
        // coverity[tainted_data]
        if( OSRSetFromUserInput( hTargetSRS, pszTargetSRS ) != CE_None )
        {
            OSRDestroySpatialReference( hTargetSRS );
            fprintf( stderr, "Invalid target SRS `%s'.\n",
                     pszTargetSRS );
            exit(1);
        }
    }

/* -------------------------------------------------------------------- */
/*      Open or create the target datasource                            */
/* -------------------------------------------------------------------- */
    GDALDatasetH hTileIndexDS = GDALOpenEx(
        index_filename, GDAL_OF_VECTOR | GDAL_OF_UPDATE, nullptr, nullptr, nullptr );
    OGRLayerH hLayer = nullptr;
    CPLString osFormat;
    if( hTileIndexDS != nullptr )
    {
        GDALDriverH hDriver = GDALGetDatasetDriver(hTileIndexDS);
        if( hDriver )
            osFormat = GDALGetDriverShortName(hDriver);

        if( GDALDatasetGetLayerCount(hTileIndexDS) == 1 )
        {
            hLayer = GDALDatasetGetLayer(hTileIndexDS, 0);
        }
        else
        {
            if( pszIndexLayerName == nullptr )
            {
                printf( "-lyr_name must be specified.\n" );
                exit( 1 );
            }
            CPLPushErrorHandler(CPLQuietErrorHandler);
            hLayer = GDALDatasetGetLayerByName(hTileIndexDS, pszIndexLayerName);
            CPLPopErrorHandler();
        }
    }
    else
    {
        printf( "Creating new index file...\n" );
        if( pszDriverName == nullptr )
        {
            std::vector<CPLString> aoDrivers =
                GetOutputDriversFor(index_filename, GDAL_OF_VECTOR);
            if( aoDrivers.empty() )
            {
                CPLError( CE_Failure, CPLE_AppDefined,
                        "Cannot guess driver for %s", index_filename);
                exit( 10 );
            }
            else
            {
                if( aoDrivers.size() > 1 )
                {
                    CPLError( CE_Warning, CPLE_AppDefined,
                            "Several drivers matching %s extension. Using %s",
                            CPLGetExtension(index_filename), aoDrivers[0].c_str() );
                }
                osFormat = aoDrivers[0];
            }
        }
        else
        {
            osFormat = pszDriverName;
        }
        if( !EQUAL(osFormat, "ESRI Shapefile") )
            nMaxFieldSize = 0;


        GDALDriverH hDriver = GDALGetDriverByName( osFormat.c_str() );
        if( hDriver == nullptr )
        {
            printf( "%s driver not available.\n", osFormat.c_str() );
            exit( 1 );
        }

        hTileIndexDS = 
            GDALCreate( hDriver, index_filename, 0, 0, 0, GDT_Unknown, nullptr );
    }

    if( hTileIndexDS != nullptr && hLayer == nullptr )
    {
        OGRSpatialReferenceH hSpatialRef = nullptr;
        char* pszLayerName = nullptr;
        if( pszIndexLayerName == nullptr )
        {
            VSIStatBuf sStat;
            if( EQUAL(osFormat, "ESRI Shapefile") ||
                VSIStat(index_filename, &sStat) == 0 )
            {
                pszLayerName = CPLStrdup(CPLGetBasename(index_filename));
            }
            else
            {
                printf( "-lyr_name must be specified.\n" );
                exit( 1 );
            }
        }
        else
        {
            pszLayerName = CPLStrdup(pszIndexLayerName);
        }

        /* get spatial reference for output file from target SRS (if set) */
        /* or from first input file */
        if( bSetTargetSRS )
        {
            hSpatialRef = OSRClone( hTargetSRS );
        }
        else
        {
            GDALDatasetH hDS = GDALOpen( argv[iArg], GA_ReadOnly );
            if( hDS )
            {
                const char* pszWKT = GDALGetProjectionRef(hDS);
                if (pszWKT != nullptr && pszWKT[0] != '\0')
                {
                    hSpatialRef = OSRNewSpatialReference(pszWKT);
                    OSRSetAxisMappingStrategy(hSpatialRef, OAMS_TRADITIONAL_GIS_ORDER);
                }
                GDALClose(hDS);
            }
        }

        hLayer =
            GDALDatasetCreateLayer( hTileIndexDS, pszLayerName, hSpatialRef,
                                wkbPolygon, nullptr );
        CPLFree(pszLayerName);
        if( hSpatialRef )
            OSRRelease(hSpatialRef);

        if( hLayer )
        {
            OGRFieldDefnH hFieldDefn = OGR_Fld_Create( tile_index, OFTString );
            if( nMaxFieldSize )
                OGR_Fld_SetWidth( hFieldDefn, static_cast<int>(nMaxFieldSize));
            OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
            OGR_Fld_Destroy(hFieldDefn);
            if( pszSrcSRSName != nullptr )
            {
                hFieldDefn = OGR_Fld_Create( pszSrcSRSName, OFTString );
                if( nMaxFieldSize )
                    OGR_Fld_SetWidth(hFieldDefn,
                                     static_cast<int>(nMaxFieldSize));
                OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
                OGR_Fld_Destroy(hFieldDefn);
            }
        }
    }

    if( hTileIndexDS == nullptr || hLayer == nullptr )
    {
        fprintf( stderr, "Unable to open/create shapefile `%s'.\n",
                 index_filename );
        exit(2);
    }

    OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hLayer);

    const int ti_field = OGR_FD_GetFieldIndex( hFDefn, tile_index );
    if( ti_field < 0 )
    {
        fprintf( stderr, "Unable to find field `%s' in file `%s'.\n",
                 tile_index, index_filename );
        exit(2);
    }

    if( pszSrcSRSName != nullptr )
        i_SrcSRSName = OGR_FD_GetFieldIndex( hFDefn, pszSrcSRSName );

    // Load in memory existing file names in SHP.
    int nExistingFiles = static_cast<int>(OGR_L_GetFeatureCount(hLayer, FALSE));
    if( nExistingFiles < 0)
        nExistingFiles = 0;

    char** existingFilesTab = nullptr;
    bool alreadyExistingProjectionRefValid = false;
    char* alreadyExistingProjectionRef = nullptr;
    if( nExistingFiles > 0 )
    {
        OGRFeatureH hFeature = nullptr;
        existingFilesTab = static_cast<char **>(
            CPLMalloc(nExistingFiles * sizeof(char*)));
        for( int i = 0; i < nExistingFiles; i++ )
        {
            hFeature = OGR_L_GetNextFeature(hLayer);
            existingFilesTab[i] =
                CPLStrdup(OGR_F_GetFieldAsString( hFeature, ti_field ));
            if( i == 0 )
            {
                GDALDatasetH hDS = GDALOpen(existingFilesTab[i], GA_ReadOnly );
                if( hDS )
                {
                    alreadyExistingProjectionRefValid = true;
                    alreadyExistingProjectionRef =
                        CPLStrdup(GDALGetProjectionRef(hDS));
                    GDALClose(hDS);
                }
            }
            OGR_F_Destroy( hFeature );
        }
    }

    if( write_absolute_path )
    {
        current_path = CPLGetCurrentDir();
        if (current_path == nullptr)
        {
            fprintf( stderr,
                     "This system does not support the CPLGetCurrentDir call. "
                     "The option -write_absolute_path will have no effect\n" );
            write_absolute_path = FALSE;
        }
    }

/* -------------------------------------------------------------------- */
/*      loop over GDAL files, processing.                               */
/* -------------------------------------------------------------------- */
    for( ; iArg < argc; iArg++ )
    {
        char *fileNameToWrite = nullptr;
        VSIStatBuf sStatBuf;

        // Make sure it is a file before building absolute path name.
        if( write_absolute_path && CPLIsFilenameRelative( argv[iArg] ) &&
            VSIStat( argv[iArg], &sStatBuf ) == 0 )
        {
            fileNameToWrite =
                CPLStrdup(CPLProjectRelativeFilename(current_path, argv[iArg]));
        }
        else
        {
            fileNameToWrite = CPLStrdup(argv[iArg]);
        }

        // Checks that file is not already in tileindex.
        {
            int i = 0;  // Used after for.
            for( ; i < nExistingFiles; i++ )
            {
                if (EQUAL(fileNameToWrite, existingFilesTab[i]))
                {
                    fprintf(stderr,
                            "File %s is already in tileindex. Skipping it.\n",
                            fileNameToWrite);
                    break;
                }
            }
            if (i != nExistingFiles)
            {
                CPLFree(fileNameToWrite);
                continue;
            }
        }

        GDALDatasetH hDS = GDALOpen( argv[iArg], GA_ReadOnly );
        if( hDS == nullptr )
        {
            fprintf( stderr, "Unable to open %s, skipping.\n",
                     argv[iArg] );
            CPLFree(fileNameToWrite);
            continue;
        }

        double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
        GDALGetGeoTransform( hDS, adfGeoTransform );
        if( adfGeoTransform[0] == 0.0
            && adfGeoTransform[1] == 1.0
            && adfGeoTransform[3] == 0.0
            && std::abs(adfGeoTransform[5]) == 1.0 )
        {
            fprintf( stderr,
                     "It appears no georeferencing is available for\n"
                     "`%s', skipping.\n",
                     argv[iArg] );
            GDALClose( hDS );
            CPLFree(fileNameToWrite);
            continue;
        }

        const char *projectionRef = GDALGetProjectionRef(hDS);

        // If not set target srs, test that the current file uses same
        // projection as others.
        if( !bSetTargetSRS )
        {
            if( alreadyExistingProjectionRefValid )
            {
                int projectionRefNotNull, alreadyExistingProjectionRefNotNull;
                projectionRefNotNull = projectionRef && projectionRef[0];
                alreadyExistingProjectionRefNotNull =
                    alreadyExistingProjectionRef &&
                    alreadyExistingProjectionRef[0];
                if ((projectionRefNotNull &&
                     alreadyExistingProjectionRefNotNull &&
                     EQUAL(projectionRef, alreadyExistingProjectionRef) == 0) ||
                    (projectionRefNotNull != alreadyExistingProjectionRefNotNull))
                {
                    fprintf(
                        stderr,
                        "Warning : %s is not using the same projection system "
                        "as other files in the tileindex.\n"
                        "This may cause problems when using it in MapServer "
                        "for example.\n"
                        "Use -t_srs option to set target projection system "
                        "(not supported by MapServer).\n"
                        "%s\n", argv[iArg],
                        skip_different_projection ? "Skipping this file." : "");
                    if( skip_different_projection )
                    {
                        CPLFree(fileNameToWrite);
                        GDALClose( hDS );
                        continue;
                    }
                }
            }
            else
            {
                alreadyExistingProjectionRefValid = true;
                alreadyExistingProjectionRef = CPLStrdup(projectionRef);
            }
        }

        const int nXSize = GDALGetRasterXSize( hDS );
        const int nYSize = GDALGetRasterYSize( hDS );

        double adfX[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
        double adfY[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
        adfX[0] = adfGeoTransform[0]
            + 0 * adfGeoTransform[1]
            + 0 * adfGeoTransform[2];
        adfY[0] = adfGeoTransform[3]
            + 0 * adfGeoTransform[4]
            + 0 * adfGeoTransform[5];

        adfX[1] = adfGeoTransform[0]
            + nXSize * adfGeoTransform[1]
            + 0 * adfGeoTransform[2];
        adfY[1] = adfGeoTransform[3]
            + nXSize * adfGeoTransform[4]
            + 0 * adfGeoTransform[5];

        adfX[2] = adfGeoTransform[0]
            + nXSize * adfGeoTransform[1]
            + nYSize * adfGeoTransform[2];
        adfY[2] = adfGeoTransform[3]
            + nXSize * adfGeoTransform[4]
            + nYSize * adfGeoTransform[5];

        adfX[3] = adfGeoTransform[0]
            + 0 * adfGeoTransform[1]
            + nYSize * adfGeoTransform[2];
        adfY[3] = adfGeoTransform[3]
            + 0 * adfGeoTransform[4]
            + nYSize * adfGeoTransform[5];

        adfX[4] = adfGeoTransform[0]
            + 0 * adfGeoTransform[1]
            + 0 * adfGeoTransform[2];
        adfY[4] = adfGeoTransform[3]
            + 0 * adfGeoTransform[4]
            + 0 * adfGeoTransform[5];

        OGRSpatialReferenceH hSourceSRS = nullptr;
        if( (bSetTargetSRS || i_SrcSRSName >= 0) &&
            projectionRef != nullptr &&
            projectionRef[0] != '\0' )
        {
            hSourceSRS = OSRNewSpatialReference( projectionRef );
            OSRSetAxisMappingStrategy(hSourceSRS, OAMS_TRADITIONAL_GIS_ORDER);
        }

        // If set target srs, do the forward transformation of all points.
        if( bSetTargetSRS && projectionRef != nullptr && projectionRef[0] != '\0' )
        {
            OGRCoordinateTransformationH hCT = nullptr;
            if( hSourceSRS && !OSRIsSame( hSourceSRS, hTargetSRS ) )
            {
                hCT = OCTNewCoordinateTransformation( hSourceSRS, hTargetSRS );
                if( hCT == nullptr || !OCTTransform( hCT, 5, adfX, adfY, nullptr ) )
                {
                    fprintf(
                        stderr,
                        "Warning : unable to transform points from source "
                        "SRS `%s' to target SRS `%s'\n"
                        "for file `%s' - file skipped\n",
                        projectionRef, pszTargetSRS, fileNameToWrite );
                    if( hCT )
                        OCTDestroyCoordinateTransformation( hCT );
                    if( hSourceSRS )
                        OSRDestroySpatialReference( hSourceSRS );
                    continue;
                }
                if( hCT )
                    OCTDestroyCoordinateTransformation( hCT );
            }
        }

        OGRFeatureH hFeature = OGR_F_Create( OGR_L_GetLayerDefn( hLayer ) );
        OGR_F_SetFieldString( hFeature, ti_field, fileNameToWrite );

        if( i_SrcSRSName >= 0 && hSourceSRS != nullptr )
        {
            const char* pszAuthorityCode =
                OSRGetAuthorityCode(hSourceSRS, nullptr);
            const char* pszAuthorityName =
                OSRGetAuthorityName(hSourceSRS, nullptr);
            if( eSrcSRSFormat == FORMAT_AUTO )
            {
                if( pszAuthorityName != nullptr && pszAuthorityCode != nullptr )
                {
                    OGR_F_SetFieldString(
                        hFeature, i_SrcSRSName,
                        CPLSPrintf("%s:%s",
                                   pszAuthorityName, pszAuthorityCode) );
                }
                else if( nMaxFieldSize == 0 ||
                         strlen(projectionRef) <= nMaxFieldSize )
                {
                    OGR_F_SetFieldString(hFeature, i_SrcSRSName, projectionRef);
                }
                else
                {
                    char* pszProj4 = nullptr;
                    if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE )
                    {
                        OGR_F_SetFieldString( hFeature, i_SrcSRSName,
                                              pszProj4 );
                        CPLFree(pszProj4);
                    }
                    else
                    {
                        OGR_F_SetFieldString( hFeature, i_SrcSRSName,
                                              projectionRef );
                    }
                }
            }
            else if( eSrcSRSFormat == FORMAT_WKT )
            {
                if( nMaxFieldSize == 0 ||
                    strlen(projectionRef) <= nMaxFieldSize )
                {
                    OGR_F_SetFieldString( hFeature, i_SrcSRSName,
                                          projectionRef );
                }
                else
                {
                    fprintf(stderr,
                            "Cannot write WKT for file %s as it is too long!\n",
                            fileNameToWrite);
                }
            }
            else if( eSrcSRSFormat == FORMAT_PROJ )
            {
                char* pszProj4 = nullptr;
                if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE )
                {
                    OGR_F_SetFieldString( hFeature, i_SrcSRSName, pszProj4 );
                    CPLFree(pszProj4);
                }
            }
            else if( eSrcSRSFormat == FORMAT_EPSG )
            {
                if( pszAuthorityName != nullptr && pszAuthorityCode != nullptr )
                    OGR_F_SetFieldString(
                        hFeature, i_SrcSRSName,
                        CPLSPrintf("%s:%s",
                                   pszAuthorityName, pszAuthorityCode) );
            }
        }
        if( hSourceSRS )
            OSRDestroySpatialReference( hSourceSRS );

        OGRGeometryH hPoly = OGR_G_CreateGeometry(wkbPolygon);
        OGRGeometryH hRing = OGR_G_CreateGeometry(wkbLinearRing);
        for( int k = 0; k < 5; k++ )
            OGR_G_SetPoint_2D(hRing, k, adfX[k], adfY[k]);
        OGR_G_AddGeometryDirectly( hPoly, hRing );
        OGR_F_SetGeometryDirectly( hFeature, hPoly );

        if( OGR_L_CreateFeature( hLayer, hFeature ) != OGRERR_NONE )
        {
           printf( "Failed to create feature in shapefile.\n" );
           break;
        }

        OGR_F_Destroy( hFeature );

        CPLFree(fileNameToWrite);

        GDALClose( hDS );
    }

    CPLFree(current_path);

    if (nExistingFiles)
    {
        for( int i = 0; i < nExistingFiles; i++ )
        {
            CPLFree(existingFilesTab[i]);
        }
        CPLFree(existingFilesTab);
    }
    CPLFree(alreadyExistingProjectionRef);

    if ( hTargetSRS )
        OSRDestroySpatialReference( hTargetSRS );

    GDALClose( hTileIndexDS );

    GDALDestroyDriverManager();
    OGRCleanupAll();
    CSLDestroy(argv);

    exit( 0 );
}
int main( int argc, char ** argv )

{
    int i, b3D = FALSE;
    int bInverse = FALSE;
    const char *pszSrcFilename = NULL;
    const char *pszDstFilename = NULL;
    char **papszLayers = NULL;
    const char *pszSQL = NULL;
    const char *pszBurnAttribute = NULL;
    const char *pszWHERE = NULL;
    std::vector<int> anBandList;
    std::vector<double> adfBurnValues;
    char **papszRasterizeOptions = NULL;
    double dfXRes = 0, dfYRes = 0;
    int bCreateOutput = FALSE;
    const char* pszFormat = "GTiff";
    int bFormatExplicitelySet = FALSE;
    char **papszCreateOptions = NULL;
    GDALDriverH hDriver = NULL;
    GDALDataType eOutputType = GDT_Float64;
    std::vector<double> adfInitVals;
    int bNoDataSet = FALSE;
    double dfNoData = 0;
    OGREnvelope sEnvelop;
    int bGotBounds = FALSE;
    int nXSize = 0, nYSize = 0;
    int bQuiet = FALSE;
    GDALProgressFunc pfnProgress = GDALTermProgress;
    OGRSpatialReferenceH hSRS = NULL;
    int bTargetAlignedPixels = FALSE;
    

    /* Check that we are running against at least GDAL 1.4 */
    /* Note to developers : if we use newer API, please change the requirement */
    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
    {
        fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
        exit(1);
    }

    GDALAllRegister();
    OGRRegisterAll();

    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

/* -------------------------------------------------------------------- */
/*      Parse arguments.                                                */
/* -------------------------------------------------------------------- */
    for( i = 1; i < argc; i++ )
    {
        if( EQUAL(argv[i], "--utility_version") )
        {
            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            return 0;
        }
        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
        {
            bQuiet = TRUE;
            pfnProgress = GDALDummyProgress;
        }
        else if( EQUAL(argv[i],"-a") && i < argc-1 )
        {
            pszBurnAttribute = argv[++i];
        }
        else if( EQUAL(argv[i],"-b") && i < argc-1 )
        {
            if (strchr(argv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( argv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    anBandList.push_back(atoi(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
                {
                    anBandList.push_back(atoi(argv[i+1]));
                    i += 1;
                }
            }
        }
        else if( EQUAL(argv[i],"-3d")  )
        {
            b3D = TRUE;
            papszRasterizeOptions = 
                CSLSetNameValue( papszRasterizeOptions, "BURN_VALUE_FROM", "Z");
        }
        else if( EQUAL(argv[i],"-i")  )
        {
            bInverse = TRUE;
        }
        else if( EQUAL(argv[i],"-at")  )
        {
            papszRasterizeOptions = 
                CSLSetNameValue( papszRasterizeOptions, "ALL_TOUCHED", "TRUE" );
        }
        else if( EQUAL(argv[i],"-burn") && i < argc-1 )
        {
            if (strchr(argv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( argv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    adfBurnValues.push_back(atof(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
                {
                    adfBurnValues.push_back(atof(argv[i+1]));
                    i += 1;
                }
            }
        }
        else if( EQUAL(argv[i],"-where") && i < argc-1 )
        {
            pszWHERE = argv[++i];
        }
        else if( EQUAL(argv[i],"-l") && i < argc-1 )
        {
            papszLayers = CSLAddString( papszLayers, argv[++i] );
        }
        else if( EQUAL(argv[i],"-sql") && i < argc-1 )
        {
            pszSQL = argv[++i];
        }
        else if( EQUAL(argv[i],"-of") && i < argc-1 )
        {
            pszFormat = argv[++i];
            bFormatExplicitelySet = TRUE;
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-init") && i < argc - 1 )
        {
            if (strchr(argv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( argv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    adfInitVals.push_back(atof(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
                {
                    adfInitVals.push_back(atof(argv[i+1]));
                    i += 1;
                }
            }
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-a_nodata") && i < argc - 1 )
        {
            dfNoData = atof(argv[i+1]);
            bNoDataSet = TRUE;
            i += 1;
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-a_srs") && i < argc-1 )
        {
            hSRS = OSRNewSpatialReference( NULL );

            if( OSRSetFromUserInput(hSRS, argv[i+1]) != OGRERR_NONE )
            {
                fprintf( stderr, "Failed to process SRS definition: %s\n", 
                         argv[i+1] );
                exit( 1 );
            }

            i++;
            bCreateOutput = TRUE;
        }   

        else if( EQUAL(argv[i],"-te") && i < argc - 4 )
        {
            sEnvelop.MinX = atof(argv[++i]);
            sEnvelop.MinY = atof(argv[++i]);
            sEnvelop.MaxX = atof(argv[++i]);
            sEnvelop.MaxY = atof(argv[++i]);
            bGotBounds = TRUE;
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-a_ullr") && i < argc - 4 )
        {
            sEnvelop.MinX = atof(argv[++i]);
            sEnvelop.MaxY = atof(argv[++i]);
            sEnvelop.MaxX = atof(argv[++i]);
            sEnvelop.MinY = atof(argv[++i]);
            bGotBounds = TRUE;
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-co") && i < argc-1 )
        {
            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-ot") && i < argc-1 )
        {
            int	iType;
            
            for( iType = 1; iType < GDT_TypeCount; iType++ )
            {
                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
                             argv[i+1]) )
                {
                    eOutputType = (GDALDataType) iType;
                }
            }

            if( eOutputType == GDT_Unknown )
            {
                printf( "Unknown output pixel type: %s\n", argv[i+1] );
                Usage();
            }
            i++;
            bCreateOutput = TRUE;
        }
        else if( (EQUAL(argv[i],"-ts") || EQUAL(argv[i],"-outsize")) && i < argc-2 )
        {
            nXSize = atoi(argv[++i]);
            nYSize = atoi(argv[++i]);
            if (nXSize <= 0 || nYSize <= 0)
            {
                printf( "Wrong value for -outsize parameters\n");
                Usage();
            }
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-tr") && i < argc-2 )
        {
            dfXRes = atof(argv[++i]);
            dfYRes = fabs(atof(argv[++i]));
            if( dfXRes == 0 || dfYRes == 0 )
            {
                printf( "Wrong value for -tr parameters\n");
                Usage();
            }
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-tap") )
        {
            bTargetAlignedPixels = TRUE;
            bCreateOutput = TRUE;
        }
        else if( pszSrcFilename == NULL )
        {
            pszSrcFilename = argv[i];
        }
        else if( pszDstFilename == NULL )
        {
            pszDstFilename = argv[i];
        }
        else
            Usage();
    }

    if( pszSrcFilename == NULL || pszDstFilename == NULL )
    {
        fprintf( stderr, "Missing source or destination.\n\n" );
        Usage();
    }

    if( adfBurnValues.size() == 0 && pszBurnAttribute == NULL && !b3D )
    {
        fprintf( stderr, "At least one of -3d, -burn or -a required.\n\n" );
        Usage();
    }

    if( bCreateOutput )
    {
        if( dfXRes == 0 && dfYRes == 0 && nXSize == 0 && nYSize == 0 )
        {
            fprintf( stderr, "'-tr xres yes' or '-ts xsize ysize' is required.\n\n" );
            Usage();
        }
    
        if (bTargetAlignedPixels && dfXRes == 0 && dfYRes == 0)
        {
            fprintf( stderr, "-tap option cannot be used without using -tr\n");
            Usage();
        }

        if( anBandList.size() != 0 )
        {
            fprintf( stderr, "-b option cannot be used when creating a GDAL dataset.\n\n" );
            Usage();
        }

        int nBandCount = 1;

        if (adfBurnValues.size() != 0)
            nBandCount = adfBurnValues.size();

        if ((int)adfInitVals.size() > nBandCount)
            nBandCount = adfInitVals.size();

        if (adfInitVals.size() == 1)
        {
            for(i=1;i<=nBandCount - 1;i++)
                adfInitVals.push_back( adfInitVals[0] );
        }

        int i;
        for(i=1;i<=nBandCount;i++)
            anBandList.push_back( i );
    }
    else
    {
        if( anBandList.size() == 0 )
            anBandList.push_back( 1 );
    }

/* -------------------------------------------------------------------- */
/*      Open source vector dataset.                                     */
/* -------------------------------------------------------------------- */
    OGRDataSourceH hSrcDS;

    hSrcDS = OGROpen( pszSrcFilename, FALSE, NULL );
    if( hSrcDS == NULL )
    {
        fprintf( stderr, "Failed to open feature source: %s\n", 
                 pszSrcFilename);
        exit( 1 );
    }

    if( pszSQL == NULL && papszLayers == NULL )
    {
        if( OGR_DS_GetLayerCount(hSrcDS) == 1 )
        {
            papszLayers = CSLAddString(NULL, OGR_L_GetName(OGR_DS_GetLayer(hSrcDS, 0)));
        }
        else
        {
            fprintf( stderr, "At least one of -l or -sql required.\n\n" );
            Usage();
        }
    }

/* -------------------------------------------------------------------- */
/*      Open target raster file.  Eventually we will add optional       */
/*      creation.                                                       */
/* -------------------------------------------------------------------- */
    GDALDatasetH hDstDS = NULL;

    if (bCreateOutput)
    {
/* -------------------------------------------------------------------- */
/*      Find the output driver.                                         */
/* -------------------------------------------------------------------- */
        hDriver = GDALGetDriverByName( pszFormat );
        if( hDriver == NULL 
            || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
        {
            int	iDr;

            printf( "Output driver `%s' not recognised or does not support\n", 
                    pszFormat );
            printf( "direct output file creation.  The following format drivers are configured\n"
                    "and support direct output:\n" );

            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
            {
                GDALDriverH hDriver = GDALGetDriver(iDr);

                if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
                {
                    printf( "  %s: %s\n",
                            GDALGetDriverShortName( hDriver  ),
                            GDALGetDriverLongName( hDriver ) );
                }
            }
            printf( "\n" );
            exit( 1 );
        }

        if (!bQuiet && !bFormatExplicitelySet)
            CheckExtensionConsistency(pszDstFilename, pszFormat);
    }
    else
    {
        hDstDS = GDALOpen( pszDstFilename, GA_Update );
        if( hDstDS == NULL )
            exit( 2 );
    }

/* -------------------------------------------------------------------- */
/*      Process SQL request.                                            */
/* -------------------------------------------------------------------- */
    if( pszSQL != NULL )
    {
        OGRLayerH hLayer;

        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL, NULL, NULL ); 
        if( hLayer != NULL )
        {
            if (bCreateOutput)
            {
                std::vector<OGRLayerH> ahLayers;
                ahLayers.push_back(hLayer);

                hDstDS = CreateOutputDataset(ahLayers, hSRS,
                                 bGotBounds, sEnvelop,
                                 hDriver, pszDstFilename,
                                 nXSize, nYSize, dfXRes, dfYRes,
                                 bTargetAlignedPixels,
                                 anBandList.size(), eOutputType,
                                 papszCreateOptions, adfInitVals,
                                 bNoDataSet, dfNoData);
            }

            ProcessLayer( hLayer, hSRS != NULL, hDstDS, anBandList, 
                          adfBurnValues, b3D, bInverse, pszBurnAttribute,
                          papszRasterizeOptions, pfnProgress, NULL );

            OGR_DS_ReleaseResultSet( hSrcDS, hLayer );
        }
    }

/* -------------------------------------------------------------------- */
/*      Create output file if necessary.                                */
/* -------------------------------------------------------------------- */
    int nLayerCount = CSLCount(papszLayers);

    if (bCreateOutput && hDstDS == NULL)
    {
        std::vector<OGRLayerH> ahLayers;

        for( i = 0; i < nLayerCount; i++ )
        {
            OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
            if( hLayer == NULL )
            {
                continue;
            }
            ahLayers.push_back(hLayer);
        }

        hDstDS = CreateOutputDataset(ahLayers, hSRS,
                                bGotBounds, sEnvelop,
                                hDriver, pszDstFilename,
                                nXSize, nYSize, dfXRes, dfYRes,
                                bTargetAlignedPixels,
                                anBandList.size(), eOutputType,
                                papszCreateOptions, adfInitVals,
                                bNoDataSet, dfNoData);
    }

/* -------------------------------------------------------------------- */
/*      Process each layer.                                             */
/* -------------------------------------------------------------------- */

    for( i = 0; i < nLayerCount; i++ )
    {
        OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
        if( hLayer == NULL )
        {
            fprintf( stderr, "Unable to find layer %s, skipping.\n", 
                      papszLayers[i] );
            continue;
        }

        if( pszWHERE )
        {
            if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE )
                break;
        }

        void *pScaledProgress;
        pScaledProgress =
            GDALCreateScaledProgress( 0.0, 1.0 * (i + 1) / nLayerCount,
                                      pfnProgress, NULL );

        ProcessLayer( hLayer, hSRS != NULL, hDstDS, anBandList, 
                      adfBurnValues, b3D, bInverse, pszBurnAttribute,
                      papszRasterizeOptions, GDALScaledProgress, pScaledProgress );

        GDALDestroyScaledProgress( pScaledProgress );
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */

    OGR_DS_Destroy( hSrcDS );
    GDALClose( hDstDS );

    OSRDestroySpatialReference(hSRS);

    CSLDestroy( argv );
    CSLDestroy( papszRasterizeOptions );
    CSLDestroy( papszLayers );
    CSLDestroy( papszCreateOptions );
    
    GDALDestroyDriverManager();
    OGRCleanupAll();

    return 0;
}
Exemple #16
0
int main(int argc, char *argv[])
{
    const char *index_filename = NULL;
    const char *tile_index = "location";
    int		i_arg, ti_field;
    OGRDataSourceH hTileIndexDS;
    OGRLayerH hLayer = NULL;
    OGRFeatureDefnH hFDefn;
    int write_absolute_path = FALSE;
    char* current_path = NULL;
    int i;
    int nExistingFiles;
    int skip_different_projection = FALSE;
    char** existingFilesTab = NULL;
    int alreadyExistingProjectionRefValid = FALSE;
    char* alreadyExistingProjectionRef = NULL;
    char* index_filename_mod;
    int bExists;
    VSIStatBuf sStatBuf;
    const char *pszTargetSRS = "";
    int bSetTargetSRS = FALSE;
    OGRSpatialReferenceH hTargetSRS = NULL;

    /* Check that we are running against at least GDAL 1.4 */
    /* Note to developers : if we use newer API, please change the requirement */
    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
    {
        fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
        exit(1);
    }

    GDALAllRegister();
    OGRRegisterAll();

    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

/* -------------------------------------------------------------------- */
/*      Get commandline arguments other than the GDAL raster filenames. */
/* -------------------------------------------------------------------- */
    for( i_arg = 1; i_arg < argc; i_arg++ )
    {
        if( EQUAL(argv[i_arg], "--utility_version") )
        {
            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            return 0;
        }
        else if( strcmp(argv[i_arg],"-tileindex") == 0 )
        {
            tile_index = argv[++i_arg];
        }
        else if( strcmp(argv[i_arg],"-t_srs") == 0 )
        {
            pszTargetSRS = argv[++i_arg];
            bSetTargetSRS = TRUE;
        }
        else if ( strcmp(argv[i_arg],"-write_absolute_path") == 0 )
        {
            write_absolute_path = TRUE;
        }
        else if ( strcmp(argv[i_arg],"-skip_different_projection") == 0 )
        {
            skip_different_projection = TRUE;
        }
        else if( argv[i_arg][0] == '-' )
            Usage();
        else if( index_filename == NULL )
        {
            index_filename = argv[i_arg];
            i_arg++;
            break;
        }
    }
 
    if( index_filename == NULL || i_arg == argc )
        Usage();

/* -------------------------------------------------------------------- */
/*      Create and validate target SRS if given.                        */
/* -------------------------------------------------------------------- */
   if( bSetTargetSRS )
   {  
       if ( skip_different_projection )
       {
           fprintf( stderr, 
                    "Warning : -skip_different_projection does not apply "
                    "when -t_srs is requested.\n" );
       }
       hTargetSRS = OSRNewSpatialReference("");
       if( OSRSetFromUserInput( hTargetSRS, pszTargetSRS ) != CE_None )
       {
           OSRDestroySpatialReference( hTargetSRS );
           fprintf( stderr, "Invalid target SRS `%s'.\n", 
                    pszTargetSRS );
           exit(1);
       }
   }

/* -------------------------------------------------------------------- */
/*      Open or create the target shapefile and DBF file.               */
/* -------------------------------------------------------------------- */
    index_filename_mod = CPLStrdup(CPLResetExtension(index_filename, "shp"));

    bExists = (VSIStat(index_filename_mod, &sStatBuf) == 0);
    if (!bExists)
    {
        CPLFree(index_filename_mod);
        index_filename_mod = CPLStrdup(CPLResetExtension(index_filename, "SHP"));
        bExists = (VSIStat(index_filename_mod, &sStatBuf) == 0);
    }
    CPLFree(index_filename_mod);

    if (bExists)
    {
        hTileIndexDS = OGROpen( index_filename, TRUE, NULL );
        if (hTileIndexDS != NULL)
        {
            hLayer = OGR_DS_GetLayer(hTileIndexDS, 0);
        }
    }
    else
    {
        OGRSFDriverH hDriver;
        const char* pszDriverName = "ESRI Shapefile";

        printf( "Creating new index file...\n" );
        hDriver = OGRGetDriverByName( pszDriverName );
        if( hDriver == NULL )
        {
            printf( "%s driver not available.\n", pszDriverName );
            exit( 1 );
        }

        hTileIndexDS = OGR_Dr_CreateDataSource( hDriver, index_filename, NULL );
        if (hTileIndexDS)
        {
            char* pszLayerName = CPLStrdup(CPLGetBasename(index_filename));

            /* get spatial reference for output file from target SRS (if set) */
            /* or from first input file */
            OGRSpatialReferenceH hSpatialRef = NULL;
            if( bSetTargetSRS )
            {
                hSpatialRef = OSRClone( hTargetSRS );
            }
            else
            {
                GDALDatasetH hDS = GDALOpen( argv[i_arg], GA_ReadOnly );
                if (hDS)
                {
                    const char* pszWKT = GDALGetProjectionRef(hDS);
                    if (pszWKT != NULL && pszWKT[0] != '\0')
                    {
                        hSpatialRef = OSRNewSpatialReference(pszWKT);
                    }
                    GDALClose(hDS);
                }
            }

            hLayer = OGR_DS_CreateLayer( hTileIndexDS, pszLayerName, hSpatialRef, wkbPolygon, NULL );
            CPLFree(pszLayerName);
            if (hSpatialRef)
                OSRRelease(hSpatialRef);

            if (hLayer)
            {
                OGRFieldDefnH hFieldDefn = OGR_Fld_Create( tile_index, OFTString );
                OGR_Fld_SetWidth( hFieldDefn, 255);
                OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
                OGR_Fld_Destroy(hFieldDefn);
            }
        }
    }

    if( hTileIndexDS == NULL || hLayer == NULL )
    {
        fprintf( stderr, "Unable to open/create shapefile `%s'.\n", 
                 index_filename );
        exit(2);
    }

    hFDefn = OGR_L_GetLayerDefn(hLayer);

    for( ti_field = 0; ti_field < OGR_FD_GetFieldCount(hFDefn); ti_field++ )
    {
        OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn( hFDefn, ti_field );
        if( strcmp(OGR_Fld_GetNameRef(hFieldDefn), tile_index) == 0 )
            break;
    }

    if( ti_field == OGR_FD_GetFieldCount(hFDefn) )
    {
        fprintf( stderr, "Unable to find field `%s' in DBF file `%s'.\n", 
                 tile_index, index_filename );
        exit(2);
    }

    /* Load in memory existing file names in SHP */
    nExistingFiles = OGR_L_GetFeatureCount(hLayer, FALSE);
    if (nExistingFiles)
    {
        OGRFeatureH hFeature;
        existingFilesTab = (char**)CPLMalloc(nExistingFiles * sizeof(char*));
        for(i=0;i<nExistingFiles;i++)
        {
            hFeature = OGR_L_GetNextFeature(hLayer);
            existingFilesTab[i] = CPLStrdup(OGR_F_GetFieldAsString( hFeature, ti_field ));
            if (i == 0)
            {
                GDALDatasetH hDS = GDALOpen(existingFilesTab[i], GA_ReadOnly );
                if (hDS)
                {
                    alreadyExistingProjectionRefValid = TRUE;
                    alreadyExistingProjectionRef = CPLStrdup(GDALGetProjectionRef(hDS));
                    GDALClose(hDS);
                }
            }
            OGR_F_Destroy( hFeature );
        }
    }

    if (write_absolute_path)
    {
        current_path = CPLGetCurrentDir();
        if (current_path == NULL)
        {
            fprintf( stderr, "This system does not support the CPLGetCurrentDir call. "
                             "The option -write_absolute_path will have no effect\n");
            write_absolute_path = FALSE;
        }
    }

/* -------------------------------------------------------------------- */
/*      loop over GDAL files, processing.                               */
/* -------------------------------------------------------------------- */
    for( ; i_arg < argc; i_arg++ )
    {
        GDALDatasetH	hDS;
        double	        adfGeoTransform[6];
        double		adfX[5], adfY[5];
        int		nXSize, nYSize;
        char* fileNameToWrite;
        const char* projectionRef;
        VSIStatBuf sStatBuf;
        int k;
        OGRFeatureH hFeature;
        OGRGeometryH hPoly, hRing;

        /* Make sure it is a file before building absolute path name */
        if (write_absolute_path && CPLIsFilenameRelative( argv[i_arg] ) &&
            VSIStat( argv[i_arg], &sStatBuf ) == 0)
        {
            fileNameToWrite = CPLStrdup(CPLProjectRelativeFilename(current_path, argv[i_arg]));
        }
        else
        {
            fileNameToWrite = CPLStrdup(argv[i_arg]);
        }

        /* Checks that file is not already in tileindex */
        for(i=0;i<nExistingFiles;i++)
        {
            if (EQUAL(fileNameToWrite, existingFilesTab[i]))
            {
                fprintf(stderr, "File %s is already in tileindex. Skipping it.\n",
                        fileNameToWrite);
                break;
            }
        }
        if (i != nExistingFiles)
        {
            CPLFree(fileNameToWrite);
            continue;
        }

        hDS = GDALOpen( argv[i_arg], GA_ReadOnly );
        if( hDS == NULL )
        {
            fprintf( stderr, "Unable to open %s, skipping.\n", 
                     argv[i_arg] );
            CPLFree(fileNameToWrite);
            continue;
        }

        GDALGetGeoTransform( hDS, adfGeoTransform );
        if( adfGeoTransform[0] == 0.0 
            && adfGeoTransform[1] == 1.0
            && adfGeoTransform[3] == 0.0
            && ABS(adfGeoTransform[5]) == 1.0 )
        {
            fprintf( stderr, 
                     "It appears no georeferencing is available for\n"
                     "`%s', skipping.\n", 
                     argv[i_arg] );
            GDALClose( hDS );
            CPLFree(fileNameToWrite);
            continue;
        }

        projectionRef = GDALGetProjectionRef(hDS);

        /* if not set target srs, test that the current file uses same projection as others */
        if( !bSetTargetSRS )
        { 
            if (alreadyExistingProjectionRefValid)
            {
                int projectionRefNotNull, alreadyExistingProjectionRefNotNull;
                projectionRefNotNull = projectionRef && projectionRef[0];
                alreadyExistingProjectionRefNotNull = alreadyExistingProjectionRef && alreadyExistingProjectionRef[0];
                if ((projectionRefNotNull &&
                     alreadyExistingProjectionRefNotNull &&
                     EQUAL(projectionRef, alreadyExistingProjectionRef) == 0) ||
                    (projectionRefNotNull != alreadyExistingProjectionRefNotNull))
                {
                    fprintf(stderr, "Warning : %s is not using the same projection system as "
                            "other files in the tileindex.\n"
			    "This may cause problems when using it in MapServer for example.\n"
                            "Use -t_srs option to set target projection system (not supported by MapServer).\n"
                            "%s\n", argv[i_arg],
                            (skip_different_projection) ? "Skipping this file." : "");
                    if (skip_different_projection)
                    {
                        CPLFree(fileNameToWrite);
                        GDALClose( hDS );
                        continue;
                    }
                }
            }
            else
            {
                alreadyExistingProjectionRefValid = TRUE;
                alreadyExistingProjectionRef = CPLStrdup(projectionRef);
            }
        }

        nXSize = GDALGetRasterXSize( hDS );
        nYSize = GDALGetRasterYSize( hDS );
        
        adfX[0] = adfGeoTransform[0] 
            + 0 * adfGeoTransform[1] 
            + 0 * adfGeoTransform[2];
        adfY[0] = adfGeoTransform[3] 
            + 0 * adfGeoTransform[4] 
            + 0 * adfGeoTransform[5];
        
        adfX[1] = adfGeoTransform[0] 
            + nXSize * adfGeoTransform[1] 
            + 0 * adfGeoTransform[2];
        adfY[1] = adfGeoTransform[3] 
            + nXSize * adfGeoTransform[4] 
            + 0 * adfGeoTransform[5];
        
        adfX[2] = adfGeoTransform[0] 
            + nXSize * adfGeoTransform[1] 
            + nYSize * adfGeoTransform[2];
        adfY[2] = adfGeoTransform[3] 
            + nXSize * adfGeoTransform[4] 
            + nYSize * adfGeoTransform[5];
        
        adfX[3] = adfGeoTransform[0] 
            + 0 * adfGeoTransform[1] 
            + nYSize * adfGeoTransform[2];
        adfY[3] = adfGeoTransform[3] 
            + 0 * adfGeoTransform[4] 
            + nYSize * adfGeoTransform[5];
        
        adfX[4] = adfGeoTransform[0] 
            + 0 * adfGeoTransform[1] 
            + 0 * adfGeoTransform[2];
        adfY[4] = adfGeoTransform[3] 
            + 0 * adfGeoTransform[4] 
            + 0 * adfGeoTransform[5];

        /* if set target srs, do the forward transformation of all points */
        if( bSetTargetSRS )
        {
            OGRSpatialReferenceH hSourceSRS = NULL;
            OGRCoordinateTransformationH hCT = NULL;
            hSourceSRS = OSRNewSpatialReference( projectionRef );
            if( hSourceSRS && !OSRIsSame( hSourceSRS, hTargetSRS ) )
            {
                hCT = OCTNewCoordinateTransformation( hSourceSRS, hTargetSRS );
                if( hCT == NULL || !OCTTransform( hCT, 5, adfX, adfY, NULL ) )
                {
                    fprintf( stderr, 
                             "Warning : unable to transform points from source SRS `%s' to target SRS `%s'\n"
                             "for file `%s' - file skipped\n", 
                             projectionRef, pszTargetSRS, fileNameToWrite );
                    if ( hCT ) 
                        OCTDestroyCoordinateTransformation( hCT );
                    if ( hSourceSRS )
                        OSRDestroySpatialReference( hSourceSRS );
                    continue;
                }
                if ( hCT ) 
                    OCTDestroyCoordinateTransformation( hCT );
            }
            if ( hSourceSRS )
                OSRDestroySpatialReference( hSourceSRS );
        }

        hFeature = OGR_F_Create( OGR_L_GetLayerDefn( hLayer ) );
        OGR_F_SetFieldString( hFeature, ti_field, fileNameToWrite );

        hPoly = OGR_G_CreateGeometry(wkbPolygon);
        hRing = OGR_G_CreateGeometry(wkbLinearRing);
        for(k=0;k<5;k++)
            OGR_G_SetPoint_2D(hRing, k, adfX[k], adfY[k]);
        OGR_G_AddGeometryDirectly( hPoly, hRing );
        OGR_F_SetGeometryDirectly( hFeature, hPoly );

        if( OGR_L_CreateFeature( hLayer, hFeature ) != OGRERR_NONE )
        {
           printf( "Failed to create feature in shapefile.\n" );
           break;
        }

        OGR_F_Destroy( hFeature );

        
        CPLFree(fileNameToWrite);

        GDALClose( hDS );
    }
    
    CPLFree(current_path);
    
    if (nExistingFiles)
    {
        for(i=0;i<nExistingFiles;i++)
        {
            CPLFree(existingFilesTab[i]);
        }
        CPLFree(existingFilesTab);
    }
    CPLFree(alreadyExistingProjectionRef);

    if ( hTargetSRS )
        OSRDestroySpatialReference( hTargetSRS );

    OGR_DS_Destroy( hTileIndexDS );
    
    GDALDestroyDriverManager();
    OGRCleanupAll();
    CSLDestroy(argv);
    
    exit( 0 );
} 
int SpatialReference::computeUTMZone(const BOX3D& box) const
{
    // Nothing we can do if we're an empty SRS
    if (empty())
        return 0;

    OGRSpatialReferenceH current =
        OSRNewSpatialReference(getWKT(eHorizontalOnly, false).c_str());
    if (! current)
        throw std::invalid_argument("Could not fetch current SRS");

    OGRSpatialReferenceH wgs84 = OSRNewSpatialReference(0);

    if (OSRSetFromUserInput(wgs84, "EPSG:4326") != OGRERR_NONE)
    {
        OSRDestroySpatialReference(current);
        OSRDestroySpatialReference(wgs84);
        std::ostringstream msg;
        msg << "Could not import GDAL input spatial reference for WGS84";
        throw std::runtime_error(msg.str());
    }

    void* transform = OCTNewCoordinateTransformation(current, wgs84);

    if (! transform)
    {
        OSRDestroySpatialReference(current);
        OSRDestroySpatialReference(wgs84);
        throw std::invalid_argument("could not comput transform from "
            "coordinate system to WGS84");
    }

    double minx(0.0), miny(0.0), minz(0.0);
    double maxx(0.0), maxy(0.0), maxz(0.0);

    // OCTTransform modifies values in-place
    minx = box.minx; miny = box.miny; minz = box.minz;
    maxx = box.maxx; maxy = box.maxy; maxz = box.maxz;

    int ret = OCTTransform(transform, 1, &minx, &miny, &minz);
    if (ret == 0)
    {
        OCTDestroyCoordinateTransformation(transform);
        OSRDestroySpatialReference(current);
        OSRDestroySpatialReference(wgs84);
        std::ostringstream msg;
        msg << "Could not project minimum point for computeUTMZone::" <<
            CPLGetLastErrorMsg() << ret;
        throw pdal_error(msg.str());
    }

    ret = OCTTransform(transform, 1, &maxx, &maxy, &maxz);
    if (ret == 0)
    {
        OCTDestroyCoordinateTransformation(transform);
        OSRDestroySpatialReference(current);
        OSRDestroySpatialReference(wgs84);
        std::ostringstream msg;
        msg << "Could not project maximum point for computeUTMZone::" <<
            CPLGetLastErrorMsg() << ret;
        throw pdal_error(msg.str());
    }

    int min_zone(0);
    int max_zone(0);
    min_zone = calculateZone(minx, miny);
    max_zone = calculateZone(maxx, maxy);

    if (min_zone != max_zone)
    {
        OCTDestroyCoordinateTransformation(transform);
        OSRDestroySpatialReference(current);
        OSRDestroySpatialReference(wgs84);
        std::ostringstream msg;
        msg << "Minimum zone is " << min_zone <<"' and maximum zone is '" <<
            max_zone << "'. They do not match because they cross a "
            "zone boundary";
        throw pdal_error(msg.str());
    }

    OCTDestroyCoordinateTransformation(transform);
    OSRDestroySpatialReference(current);
    OSRDestroySpatialReference(wgs84);

    return min_zone;
}