Beispiel #1
0
 void setFromLayer(OGRLayerH layer)
 {
     if (layer)
     {
         OGRSpatialReferenceH s = OGR_L_GetSpatialRef(layer);
         if (s)
         {
             OGRSpatialReferenceH clone = OSRClone(s);
             newRef(clone);
         }
     }
 }
Beispiel #2
0
GDALWSpatialInfo GDALWGetSpatialInfo(GDALWConnection conn) {
	GDALWSpatialInfo spatialInfo;
	OGRSpatialReferenceH spatialRef = OGR_L_GetSpatialRef(conn.layer);
	char * proj4, * srsText, * srid;

	OSRExportToProj4(spatialRef, &proj4);
	OSRExportToWkt(spatialRef, &srsText);
	srid = (char *) OSRGetAttrValue(spatialRef, "AUTHORITY", 1);
	if (srid == NULL) {
		spatialInfo.epsg = 4326;
	}
	else {
		spatialInfo.epsg = atoi(OSRGetAttrValue(spatialRef, "AUTHORITY", 1));
	}
	spatialInfo.authName = OSRGetAttrValue(spatialRef, "AUTHORITY", 0);
	if (spatialInfo.authName == NULL) {
		spatialInfo.authName = "EPSG";
	}
	spatialInfo.proj4Text = proj4;
	spatialInfo.srsText = srsText;

	return spatialInfo;

}
Beispiel #3
0
int readoutlets(char *outletsds,char *lyrname, int uselayername,int outletslyr,OGRSpatialReferenceH hSRSRaster,int *noutlets, double*& x, double*& y,int*& id)

{   
	// initializing datasoruce,layer,feature, geomtery, spatial reference
    OGRSFDriverH    driver;
    OGRDataSourceH  hDS1;
	OGRLayerH       hLayer1;
	OGRFeatureDefnH hFDefn1;
	OGRFieldDefnH   hFieldDefn1;
	OGRFeatureH     hFeature1;
	OGRGeometryH    geometry, line;
	OGRSpatialReferenceH hRSOutlet;
	// register all ogr driver related to OGR
	OGRRegisterAll(); 

	// open data source
	hDS1 = OGROpen(outletsds, FALSE, NULL );
	if( hDS1 == NULL )
	{
	printf( "Error Opening OGR Data Source .\n" );
	return 1;
	}
	
    //get layer from layer name
	if(uselayername==1) { hLayer1 = OGR_DS_GetLayerByName(hDS1,lyrname);}
		//get layerinfo from layer number
	else { hLayer1 = OGR_DS_GetLayer(hDS1,outletslyr);} // get layerinfo from layername

	if(hLayer1 == NULL)getlayerfail(hDS1,outletsds,outletslyr);
	OGRwkbGeometryType gtype;
	gtype=OGR_L_GetGeomType(hLayer1);

	// Test that the type is a point
	if(gtype != wkbPoint)getlayerfail(hDS1,outletsds,outletslyr);

	const char* RasterProjectionName;
	const char* sprs;
	const char* sprso;
	const char* OutletProjectionName;
	int pj_raster,pj_outlet;

	// Spatial reference of outlet
	hRSOutlet = OGR_L_GetSpatialRef(hLayer1);
	if(hSRSRaster!=NULL){
	  pj_raster=OSRIsProjected(hSRSRaster); // find if projected or not
	  if(pj_raster==0) {sprs="GEOGCS";} else { sprs="PROJCS"; }
	  RasterProjectionName = OSRGetAttrValue(hSRSRaster,sprs,0); // get projection name
	}
	if(hRSOutlet!=NULL){
	  pj_outlet=OSRIsProjected(hRSOutlet);
	  if(pj_outlet==0) {sprso="GEOGCS";} else { sprso="PROJCS"; }
	  OutletProjectionName = OSRGetAttrValue(hRSOutlet,sprso,0);
	}

	//Write warnings where projections may not match
	if(hRSOutlet!=NULL && hSRSRaster!=NULL){
	
		if (pj_raster==pj_outlet){
			  
			 int rc= strcmp(RasterProjectionName,OutletProjectionName); // compare string
			 if(rc!=0){
				printf( "Warning: Projection of Outlet feature and Raster data may be different.\n" );
				printf("Projection of Raster datasource %s.\n",RasterProjectionName);
                printf("Projection of Outlet feature %s.\n",OutletProjectionName);
			}
		}
    
		else {
			  printf( "Warning: Spatial References of Outlet feature and Raster data are different.\n" );
			  printf("Projection of Raster datasource %s.\n",RasterProjectionName);
              printf("Projection of Outlet feature %s.\n",OutletProjectionName);
		}
	}
	
	else if(hSRSRaster==NULL && hRSOutlet!=NULL) {
		      printf( "Warning: Spatial Reference of Raster is missing.\n" );
              printf("Projection of Outlet feature %s.\n",OutletProjectionName);

	}
	else if(hSRSRaster!=NULL && hRSOutlet==NULL) {
	          printf( "Warning: Spatial Reference of Outlet feature is missing.\n" );
			  printf("Projection of Raster datasource %s.\n",RasterProjectionName);
	}
	else {
	          printf( "Warning: Spatial References of Outlet feature and Raster data are missing.\n" );
	}



	long countPts=0;
	// count number of feature
	countPts=OGR_L_GetFeatureCount(hLayer1,0); 
	// get schema i.e geometry, properties (e.g. ID)
	hFDefn1 = OGR_L_GetLayerDefn(hLayer1); 
	x = new double[countPts];
	y = new double[countPts];
	int iField;
	int nxy=0;
	id = new int[countPts];
	// loop through each feature and get lat,lon and id information

    OGR_L_ResetReading(hLayer1);
    while( (hFeature1 = OGR_L_GetNextFeature(hLayer1)) != NULL ) {

		 //hFeature1=OGR_L_GetFeature(hLayer1,j); // get feature info
		 geometry = OGR_F_GetGeometryRef(hFeature1); // get geometry
         x[nxy] = OGR_G_GetX(geometry, 0);
		 y[nxy] =  OGR_G_GetY(geometry, 0);
		 int idfld =OGR_F_GetFieldIndex(hFeature1,"id");
		 if (idfld >= 0)
		   {
			 
			hFieldDefn1 = OGR_FD_GetFieldDefn( hFDefn1,idfld); // get field definiton based on index
			if( OGR_Fld_GetType(hFieldDefn1) == OFTInteger ) {
					id[nxy] =OGR_F_GetFieldAsInteger( hFeature1, idfld );} // get id value 
		    }
		 else {
		      id[nxy]=1;// if there is no id field         
		 } 
		 nxy++; // count number of outlets point
		 OGR_F_Destroy( hFeature1 ); // destroy feature
	}
	*noutlets=nxy;
	OGR_DS_Destroy( hDS1); // destroy data source
	return 0;
}
static
GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
                                 OGRSpatialReferenceH hSRS,
                                 int bGotBounds, OGREnvelope sEnvelop,
                                 GDALDriverH hDriver, const char* pszDest,
                                 int nXSize, int nYSize, double dfXRes, double dfYRes,
                                 int bTargetAlignedPixels,
                                 int nBandCount, GDALDataType eOutputType,
                                 char** papszCreationOptions, std::vector<double> adfInitVals,
                                 int bNoDataSet, double dfNoData)
{
    int bFirstLayer = TRUE;
    char* pszWKT = NULL;
    GDALDatasetH hDstDS = NULL;
    unsigned int i;

    for( i = 0; i < ahLayers.size(); i++ )
    {
        OGRLayerH hLayer = ahLayers[i];

        if (!bGotBounds)
        {
            OGREnvelope sLayerEnvelop;

            if (OGR_L_GetExtent(hLayer, &sLayerEnvelop, TRUE) != OGRERR_NONE)
            {
                CPLError(CE_Failure, CPLE_AppDefined, "Cannot get layer extent");
                return NULL;
            }

            /* Voluntarily increase the extent by a half-pixel size to avoid */
            /* missing points on the border */
            if (!bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0)
            {
                sLayerEnvelop.MinX -= dfXRes / 2;
                sLayerEnvelop.MaxX += dfXRes / 2;
                sLayerEnvelop.MinY -= dfYRes / 2;
                sLayerEnvelop.MaxY += dfYRes / 2;
            }

            if (bFirstLayer)
            {
                sEnvelop.MinX = sLayerEnvelop.MinX;
                sEnvelop.MinY = sLayerEnvelop.MinY;
                sEnvelop.MaxX = sLayerEnvelop.MaxX;
                sEnvelop.MaxY = sLayerEnvelop.MaxY;

                if (hSRS == NULL)
                    hSRS = OGR_L_GetSpatialRef(hLayer);

                bFirstLayer = FALSE;
            }
            else
            {
                sEnvelop.MinX = MIN(sEnvelop.MinX, sLayerEnvelop.MinX);
                sEnvelop.MinY = MIN(sEnvelop.MinY, sLayerEnvelop.MinY);
                sEnvelop.MaxX = MAX(sEnvelop.MaxX, sLayerEnvelop.MaxX);
                sEnvelop.MaxY = MAX(sEnvelop.MaxY, sLayerEnvelop.MaxY);
            }
        }
        else
        {
            if (bFirstLayer)
            {
                if (hSRS == NULL)
                    hSRS = OGR_L_GetSpatialRef(hLayer);

                bFirstLayer = FALSE;
            }
        }
    }

    if (dfXRes == 0 && dfYRes == 0)
    {
        dfXRes = (sEnvelop.MaxX - sEnvelop.MinX) / nXSize;
        dfYRes = (sEnvelop.MaxY - sEnvelop.MinY) / nYSize;
    }
    else if (bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0)
    {
        sEnvelop.MinX = floor(sEnvelop.MinX / dfXRes) * dfXRes;
        sEnvelop.MaxX = ceil(sEnvelop.MaxX / dfXRes) * dfXRes;
        sEnvelop.MinY = floor(sEnvelop.MinY / dfYRes) * dfYRes;
        sEnvelop.MaxY = ceil(sEnvelop.MaxY / dfYRes) * dfYRes;
    }

    double adfProjection[6];
    adfProjection[0] = sEnvelop.MinX;
    adfProjection[1] = dfXRes;
    adfProjection[2] = 0;
    adfProjection[3] = sEnvelop.MaxY;
    adfProjection[4] = 0;
    adfProjection[5] = -dfYRes;

    if (nXSize == 0 && nYSize == 0)
    {
        nXSize = (int)(0.5 + (sEnvelop.MaxX - sEnvelop.MinX) / dfXRes);
        nYSize = (int)(0.5 + (sEnvelop.MaxY - sEnvelop.MinY) / dfYRes);
    }

    hDstDS = GDALCreate(hDriver, pszDest, nXSize, nYSize,
                        nBandCount, eOutputType, papszCreationOptions);
    if (hDstDS == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s", pszDest);
        return NULL;
    }

    GDALSetGeoTransform(hDstDS, adfProjection);

    if (hSRS)
        OSRExportToWkt(hSRS, &pszWKT);
    if (pszWKT)
        GDALSetProjection(hDstDS, pszWKT);
    CPLFree(pszWKT);

    int iBand;
    /*if( nBandCount == 3 || nBandCount == 4 )
    {
        for(iBand = 0; iBand < nBandCount; iBand++)
        {
            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
            GDALSetRasterColorInterpretation(hBand, (GDALColorInterp)(GCI_RedBand + iBand));
        }
    }*/

    if (bNoDataSet)
    {
        for(iBand = 0; iBand < nBandCount; iBand++)
        {
            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
            GDALSetRasterNoDataValue(hBand, dfNoData);
        }
    }

    if (adfInitVals.size() != 0)
    {
        for(iBand = 0; iBand < MIN(nBandCount,(int)adfInitVals.size()); iBand++)
        {
            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
            GDALFillRaster(hBand, adfInitVals[iBand], 0);
        }
    }

    return hDstDS;
}
static CPLErr ProcessLayer(
    OGRLayerH hSrcLayer, int bSRSIsSet,
    GDALDatasetH hDstDS, std::vector<int> anBandList,
    const std::vector<double> &adfBurnValues, int b3D, int bInverse,
    const char *pszBurnAttribute, char **papszRasterizeOptions,
    GDALProgressFunc pfnProgress, void* pProgressData )

{
/* -------------------------------------------------------------------- */
/*      Checkout that SRS are the same.                                 */
/*      If -a_srs is specified, skip the test                           */
/* -------------------------------------------------------------------- */
    OGRCoordinateTransformationH hCT = NULL;
    if (!bSRSIsSet)
    {
        OGRSpatialReferenceH  hDstSRS = NULL;
        if( GDALGetProjectionRef( hDstDS ) != NULL )
        {
            char *pszProjection;

            pszProjection = (char *) GDALGetProjectionRef( hDstDS );

            hDstSRS = OSRNewSpatialReference(NULL);
            if( OSRImportFromWkt( hDstSRS, &pszProjection ) != OGRERR_NONE )
            {
                OSRDestroySpatialReference(hDstSRS);
                hDstSRS = NULL;
            }
        }

        OGRSpatialReferenceH hSrcSRS = OGR_L_GetSpatialRef(hSrcLayer);
        if( hDstSRS != NULL && hSrcSRS != NULL )
        {
            if( OSRIsSame(hSrcSRS, hDstSRS) == FALSE )
            {
                hCT = OCTNewCoordinateTransformation(hSrcSRS, hDstSRS);
                if( hCT == NULL )
                {
                    CPLError(CE_Warning, CPLE_AppDefined,
                        "The output raster dataset and the input vector layer do not have the same SRS.\n"
                        "And reprojection of input data did not work. Results might be incorrect.");
                }
            }
        }
        else if( hDstSRS != NULL && hSrcSRS == NULL )
        {
            CPLError(CE_Warning, CPLE_AppDefined,
                    "The output raster dataset has a SRS, but the input vector layer SRS is unknown.\n"
                    "Ensure input vector has the same SRS, otherwise results might be incorrect.");
        }
        else if( hDstSRS == NULL && hSrcSRS != NULL )
        {
            CPLError(CE_Warning, CPLE_AppDefined,
                    "The input vector layer has a SRS, but the output raster dataset SRS is unknown.\n"
                    "Ensure output raster dataset has the same SRS, otherwise results might be incorrect.");
        }

        if( hDstSRS != NULL )
        {
            OSRDestroySpatialReference(hDstSRS);
        }
    }

/* -------------------------------------------------------------------- */
/*      Get field index, and check.                                     */
/* -------------------------------------------------------------------- */
    int iBurnField = -1;

    if( pszBurnAttribute )
    {
        iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
                                           pszBurnAttribute );
        if( iBurnField == -1 )
        {
            CPLError(CE_Failure, CPLE_AppDefined, "Failed to find field %s on layer %s, skipping.",
                    pszBurnAttribute,
                    OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
            if( hCT != NULL )
                OCTDestroyCoordinateTransformation(hCT);
            return CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Collect the geometries from this layer, and build list of       */
/*      burn values.                                                    */
/* -------------------------------------------------------------------- */
    OGRFeatureH hFeat;
    std::vector<OGRGeometryH> ahGeometries;
    std::vector<double> adfFullBurnValues;

    OGR_L_ResetReading( hSrcLayer );

    while( (hFeat = OGR_L_GetNextFeature( hSrcLayer )) != NULL )
    {
        OGRGeometryH hGeom;

        if( OGR_F_GetGeometryRef( hFeat ) == NULL )
        {
            OGR_F_Destroy( hFeat );
            continue;
        }

        hGeom = OGR_G_Clone( OGR_F_GetGeometryRef( hFeat ) );
        if( hCT != NULL )
        {
            if( OGR_G_Transform(hGeom, hCT) != OGRERR_NONE )
            {
                OGR_F_Destroy( hFeat );
                OGR_G_DestroyGeometry(hGeom);
                continue;
            }
        }
        ahGeometries.push_back( hGeom );

        for( unsigned int iBand = 0; iBand < anBandList.size(); iBand++ )
        {
            if( adfBurnValues.size() > 0 )
                adfFullBurnValues.push_back(
                    adfBurnValues[MIN(iBand,adfBurnValues.size()-1)] );
            else if( pszBurnAttribute )
            {
                adfFullBurnValues.push_back( OGR_F_GetFieldAsDouble( hFeat, iBurnField ) );
            }
            /* I have made the 3D option exclusive to other options since it
               can be used to modify the value from "-burn value" or
               "-a attribute_name" */
            if( b3D )
            {
                // TODO: get geometry "z" value
                /* Points and Lines will have their "z" values collected at the
                   point and line levels respectively. However filled polygons
                   (GDALdllImageFilledPolygon) can use some help by getting
                   their "z" values here. */
                adfFullBurnValues.push_back( 0.0 );
            }
        }

        OGR_F_Destroy( hFeat );
    }

    if( hCT != NULL )
        OCTDestroyCoordinateTransformation(hCT);

/* -------------------------------------------------------------------- */
/*      If we are in inverse mode, we add one extra ring around the     */
/*      whole dataset to invert the concept of insideness and then      */
/*      merge everything into one geometry collection.                  */
/* -------------------------------------------------------------------- */
    if( bInverse )
    {
        if( ahGeometries.size() == 0 )
        {
            for( unsigned int iBand = 0; iBand < anBandList.size(); iBand++ )
            {
                if( adfBurnValues.size() > 0 )
                    adfFullBurnValues.push_back(
                        adfBurnValues[MIN(iBand,adfBurnValues.size()-1)] );
                else /* FIXME? Not sure what to do exactly in the else case, but we must insert a value */
                    adfFullBurnValues.push_back( 0.0 );
            }
        }

        InvertGeometries( hDstDS, ahGeometries );
    }

/* -------------------------------------------------------------------- */
/*      Perform the burn.                                               */
/* -------------------------------------------------------------------- */
    CPLErr eErr = GDALRasterizeGeometries( hDstDS, static_cast<int>(anBandList.size()), &(anBandList[0]),
                             static_cast<int>(ahGeometries.size()), &(ahGeometries[0]),
                             NULL, NULL, &(adfFullBurnValues[0]),
                             papszRasterizeOptions,
                             pfnProgress, pProgressData );

/* -------------------------------------------------------------------- */
/*      Cleanup geometries.                                             */
/* -------------------------------------------------------------------- */
    int iGeom;

    for( iGeom = static_cast<int>(ahGeometries.size())-1; iGeom >= 0; iGeom-- )
        OGR_G_DestroyGeometry( ahGeometries[iGeom] );

    return eErr;
}
Beispiel #6
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct _param {
        struct Option *dsn, *out, *layer, *spat, *where,
                   *min_area;
        struct Option *snap, *type, *outloc, *cnames;
    } param;
    struct _flag {
        struct Flag *list, *tlist, *no_clean, *z, *notab,
                   *region;
        struct Flag *over, *extend, *formats, *tolower, *no_import;
    } flag;

    int i, j, layer, arg_s_num, nogeom, ncnames;
    float xmin, ymin, xmax, ymax;
    int ncols = 0, type;
    double min_area, snap;
    char buf[2000], namebuf[2000], tempvect[GNAME_MAX];
    char *separator;

    struct Key_Value *loc_proj_info, *loc_proj_units;
    struct Key_Value *proj_info, *proj_units;
    struct Cell_head cellhd, loc_wind, cur_wind;
    char error_msg[8192];

    /* Vector */
    struct Map_info Map, Tmp, *Out;
    int cat;

    /* Attributes */
    struct field_info *Fi;
    dbDriver *driver;
    dbString sql, strval;
    int dim, with_z;

    /* OGR */
    OGRDataSourceH Ogr_ds;
    OGRLayerH Ogr_layer;
    OGRFieldDefnH Ogr_field;
    char *Ogr_fieldname;
    OGRFieldType Ogr_ftype;
    OGRFeatureH Ogr_feature;
    OGRFeatureDefnH Ogr_featuredefn;
    OGRGeometryH Ogr_geometry, Ogr_oRing, poSpatialFilter;
    OGRSpatialReferenceH Ogr_projection;
    OGREnvelope oExt;
    OGRwkbGeometryType Ogr_geom_type;

    int OFTIntegerListlength;

    char *output;
    char **layer_names;		/* names of layers to be imported */
    int *layers;		/* layer indexes */
    int nlayers;		/* number of layers to import */
    char **available_layer_names;	/* names of layers to be imported */
    int navailable_layers;
    int layer_id;
    unsigned int n_features, feature_count;
    int overwrite;
    double area_size;
    int use_tmp_vect;

    xmin = ymin = xmax = ymax = 0.0;
    loc_proj_info = loc_proj_units = NULL;
    Ogr_ds = Ogr_oRing = poSpatialFilter = NULL;
    OFTIntegerListlength = 40;	/* hack due to limitation in OGR */
    area_size = 0.0;
    use_tmp_vect = FALSE;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("import"));
    module->description = _("Converts vector data into a GRASS vector map using OGR library.");

    param.dsn = G_define_option();
    param.dsn->key = "dsn";
    param.dsn->type = TYPE_STRING;
    param.dsn->required =YES;
    param.dsn->label = _("OGR datasource name");
    param.dsn->description = _("Examples:\n"
                               "\t\tESRI Shapefile: directory containing shapefiles\n"
                               "\t\tMapInfo File: directory containing mapinfo files");

    param.layer = G_define_option();
    param.layer->key = "layer";
    param.layer->type = TYPE_STRING;
    param.layer->required = NO;
    param.layer->multiple = YES;
    param.layer->label =
        _("OGR layer name. If not given, all available layers are imported");
    param.layer->description =
        _("Examples:\n" "\t\tESRI Shapefile: shapefile name\n"
          "\t\tMapInfo File: mapinfo file name");
    param.layer->guisection = _("Selection");

    param.out = G_define_standard_option(G_OPT_V_OUTPUT);
    param.out->required = NO;
    param.out->guisection = _("Output");

    param.spat = G_define_option();
    param.spat->key = "spatial";
    param.spat->type = TYPE_DOUBLE;
    param.spat->multiple = YES;
    param.spat->required = NO;
    param.spat->key_desc = "xmin,ymin,xmax,ymax";
    param.spat->label = _("Import subregion only");
    param.spat->guisection = _("Selection");
    param.spat->description =
        _("Format: xmin,ymin,xmax,ymax - usually W,S,E,N");

    param.where = G_define_standard_option(G_OPT_DB_WHERE);
    param.where->guisection = _("Selection");

    param.min_area = G_define_option();
    param.min_area->key = "min_area";
    param.min_area->type = TYPE_DOUBLE;
    param.min_area->required = NO;
    param.min_area->answer = "0.0001";
    param.min_area->label =
        _("Minimum size of area to be imported (square units)");
    param.min_area->guisection = _("Selection");
    param.min_area->description = _("Smaller areas and "
                                    "islands are ignored. Should be greater than snap^2");

    param.type = G_define_standard_option(G_OPT_V_TYPE);
    param.type->options = "point,line,boundary,centroid";
    param.type->answer = "";
    param.type->description = _("Optionally change default input type");
    param.type->descriptions =
        _("point;import area centroids as points;"
          "line;import area boundaries as lines;"
          "boundary;import lines as area boundaries;"
          "centroid;import points as centroids");
    param.type->guisection = _("Selection");

    param.snap = G_define_option();
    param.snap->key = "snap";
    param.snap->type = TYPE_DOUBLE;
    param.snap->required = NO;
    param.snap->answer = "-1";
    param.snap->label = _("Snapping threshold for boundaries");
    param.snap->description = _("'-1' for no snap");

    param.outloc = G_define_option();
    param.outloc->key = "location";
    param.outloc->type = TYPE_STRING;
    param.outloc->required = NO;
    param.outloc->description = _("Name for new location to create");
    param.outloc->key_desc = "name";

    param.cnames = G_define_option();
    param.cnames->key = "cnames";
    param.cnames->type = TYPE_STRING;
    param.cnames->required = NO;
    param.cnames->multiple = YES;
    param.cnames->description =
        _("List of column names to be used instead of original names, "
          "first is used for category column");
    param.cnames->guisection = _("Attributes");

    flag.list = G_define_flag();
    flag.list->key = 'l';
    flag.list->description = _("List available OGR layers in data source and exit");
    flag.list->suppress_required = YES;
    flag.list->guisection = _("Print");

    flag.tlist = G_define_flag();
    flag.tlist->key = 'a';
    flag.tlist->description = _("List available OGR layers including feature types "
                                "in data source and exit");
    flag.tlist->suppress_required = YES;
    flag.tlist->guisection = _("Print");

    flag.formats = G_define_flag();
    flag.formats->key = 'f';
    flag.formats->description = _("List supported formats and exit");
    flag.formats->suppress_required = YES;
    flag.formats->guisection = _("Print");

    /* if using -c, you lose topological information ! */
    flag.no_clean = G_define_flag();
    flag.no_clean->key = 'c';
    flag.no_clean->description = _("Do not clean polygons (not recommended)");
    flag.no_clean->guisection = _("Output");

    flag.z = G_define_flag();
    flag.z->key = 'z';
    flag.z->description = _("Create 3D output");
    flag.z->guisection = _("Output");

    flag.notab = G_define_flag();
    flag.notab->key = 't';
    flag.notab->description = _("Do not create attribute table");
    flag.notab->guisection = _("Attributes");

    flag.over = G_define_flag();
    flag.over->key = 'o';
    flag.over->description =
        _("Override dataset projection (use location's projection)");

    flag.region = G_define_flag();
    flag.region->key = 'r';
    flag.region->guisection = _("Selection");
    flag.region->description = _("Limit import to the current region");

    flag.extend = G_define_flag();
    flag.extend->key = 'e';
    flag.extend->description =
        _("Extend location extents based on new dataset");

    flag.tolower = G_define_flag();
    flag.tolower->key = 'w';
    flag.tolower->description =
        _("Change column names to lowercase characters");
    flag.tolower->guisection = _("Attributes");

    flag.no_import = G_define_flag();
    flag.no_import->key = 'i';
    flag.no_import->description =
        _("Create the location specified by the \"location\" parameter and exit."
          " Do not import the vector data.");

    /* The parser checks if the map already exists in current mapset, this is
     * wrong if location options is used, so we switch out the check and do it
     * in the module after the parser */
    overwrite = G_check_overwrite(argc, argv);

    if (G_parser(argc, argv))
        exit(EXIT_FAILURE);

    G_begin_polygon_area_calculations();	/* Used in geom() */

    OGRRegisterAll();

    /* list supported formats */
    if (flag.formats->answer) {
        int iDriver;

        G_message(_("Available OGR Drivers:"));

        for (iDriver = 0; iDriver < OGRGetDriverCount(); iDriver++) {
            OGRSFDriverH poDriver = OGRGetDriver(iDriver);
            const char *pszRWFlag;

            if (OGR_Dr_TestCapability(poDriver, ODrCCreateDataSource))
                pszRWFlag = "rw";
            else
                pszRWFlag = "ro";

            fprintf(stdout, " %s (%s): %s\n",
                    OGR_Dr_GetName(poDriver),
                    pszRWFlag, OGR_Dr_GetName(poDriver));
        }
        exit(EXIT_SUCCESS);
    }

    if (param.dsn->answer == NULL) {
        G_fatal_error(_("Required parameter <%s> not set"), param.dsn->key);
    }

    min_area = atof(param.min_area->answer);
    snap = atof(param.snap->answer);
    type = Vect_option_to_types(param.type);

    ncnames = 0;
    if (param.cnames->answers) {
        i = 0;
        while (param.cnames->answers[i++]) {
            ncnames++;
        }
    }

    /* Open OGR DSN */
    Ogr_ds = NULL;
    if (strlen(param.dsn->answer) > 0)
        Ogr_ds = OGROpen(param.dsn->answer, FALSE, NULL);

    if (Ogr_ds == NULL)
        G_fatal_error(_("Unable to open data source <%s>"), param.dsn->answer);

    /* Make a list of available layers */
    navailable_layers = OGR_DS_GetLayerCount(Ogr_ds);
    available_layer_names =
        (char **)G_malloc(navailable_layers * sizeof(char *));

    if (flag.list->answer || flag.tlist->answer)
        G_message(_("Data source <%s> (format '%s') contains %d layers:"),
                  param.dsn->answer,
                  OGR_Dr_GetName(OGR_DS_GetDriver(Ogr_ds)), navailable_layers);
    for (i = 0; i < navailable_layers; i++) {
        Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
        Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
        Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);

        available_layer_names[i] =
            G_store((char *)OGR_FD_GetName(Ogr_featuredefn));

        if (flag.tlist->answer)
            fprintf(stdout, "%s (%s)\n", available_layer_names[i],
                    OGRGeometryTypeToName(Ogr_geom_type));
        else if (flag.list->answer)
            fprintf(stdout, "%s\n", available_layer_names[i]);
    }
    if (flag.list->answer || flag.tlist->answer) {
        fflush(stdout);
        exit(EXIT_SUCCESS);
    }

    /* Make a list of layers to be imported */
    if (param.layer->answer) {	/* From option */
        nlayers = 0;
        while (param.layer->answers[nlayers])
            nlayers++;

        layer_names = (char **)G_malloc(nlayers * sizeof(char *));
        layers = (int *)G_malloc(nlayers * sizeof(int));

        for (i = 0; i < nlayers; i++) {
            layer_names[i] = G_store(param.layer->answers[i]);
            /* Find it in the source */
            layers[i] = -1;
            for (j = 0; j < navailable_layers; j++) {
                if (strcmp(available_layer_names[j], layer_names[i]) == 0) {
                    layers[i] = j;
                    break;
                }
            }
            if (layers[i] == -1)
                G_fatal_error(_("Layer <%s> not available"), layer_names[i]);
        }
    }
    else {			/* use list of all layers */
        nlayers = navailable_layers;
        layer_names = available_layer_names;
        layers = (int *)G_malloc(nlayers * sizeof(int));
        for (i = 0; i < nlayers; i++)
            layers[i] = i;
    }

    if (param.out->answer) {
        output = G_store(param.out->answer);
    }
    else {
        if (nlayers < 1)
            G_fatal_error(_("No OGR layers available"));
        output = G_store(layer_names[0]);
        G_message(_("All available OGR layers will be imported into vector map <%s>"), output);
    }

    if (!param.outloc->answer) {	/* Check if the map exists */
        if (G_find_vector2(output, G_mapset()) && !overwrite)
            G_fatal_error(_("Vector map <%s> already exists"),
                          output);
    }

    /* Get first imported layer to use for extents and projection check */
    Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layers[0]);

    if (flag.region->answer) {
        if (param.spat->answer)
            G_fatal_error(_("Select either the current region flag or the spatial option, not both"));

        G_get_window(&cur_wind);
        xmin = cur_wind.west;
        xmax = cur_wind.east;
        ymin = cur_wind.south;
        ymax = cur_wind.north;
    }
    if (param.spat->answer) {
        /* See as reference: gdal/ogr/ogr_capi_test.c */

        /* cut out a piece of the map */
        /* order: xmin,ymin,xmax,ymax */
        arg_s_num = 0;
        i = 0;
        while (param.spat->answers[i]) {
            if (i == 0)
                xmin = atof(param.spat->answers[i]);
            if (i == 1)
                ymin = atof(param.spat->answers[i]);
            if (i == 2)
                xmax = atof(param.spat->answers[i]);
            if (i == 3)
                ymax = atof(param.spat->answers[i]);
            arg_s_num++;
            i++;
        }
        if (arg_s_num != 4)
            G_fatal_error(_("4 parameters required for 'spatial' parameter"));
    }
    if (param.spat->answer || flag.region->answer) {
        G_debug(2, "cut out with boundaries: xmin:%f ymin:%f xmax:%f ymax:%f",
                xmin, ymin, xmax, ymax);

        /* in theory this could be an irregular polygon */
        poSpatialFilter = OGR_G_CreateGeometry(wkbPolygon);
        Ogr_oRing = OGR_G_CreateGeometry(wkbLinearRing);
        OGR_G_AddPoint(Ogr_oRing, xmin, ymin, 0.0);
        OGR_G_AddPoint(Ogr_oRing, xmin, ymax, 0.0);
        OGR_G_AddPoint(Ogr_oRing, xmax, ymax, 0.0);
        OGR_G_AddPoint(Ogr_oRing, xmax, ymin, 0.0);
        OGR_G_AddPoint(Ogr_oRing, xmin, ymin, 0.0);
        OGR_G_AddGeometryDirectly(poSpatialFilter, Ogr_oRing);

        OGR_L_SetSpatialFilter(Ogr_layer, poSpatialFilter);
    }

    if (param.where->answer) {
        /* select by attribute */
        OGR_L_SetAttributeFilter(Ogr_layer, param.where->answer);
    }

    /* fetch boundaries */
    if ((OGR_L_GetExtent(Ogr_layer, &oExt, 1)) == OGRERR_NONE) {
        G_get_window(&cellhd);
        cellhd.north = oExt.MaxY;
        cellhd.south = oExt.MinY;
        cellhd.west = oExt.MinX;
        cellhd.east = oExt.MaxX;
        cellhd.rows = 20;	/* TODO - calculate useful values */
        cellhd.cols = 20;
        cellhd.ns_res = (cellhd.north - cellhd.south) / cellhd.rows;
        cellhd.ew_res = (cellhd.east - cellhd.west) / cellhd.cols;
    }
    else {
        cellhd.north = 1.;
        cellhd.south = 0.;
        cellhd.west = 0.;
        cellhd.east = 1.;
        cellhd.top = 1.;
        cellhd.bottom = 1.;
        cellhd.rows = 1;
        cellhd.rows3 = 1;
        cellhd.cols = 1;
        cellhd.cols3 = 1;
        cellhd.depths = 1;
        cellhd.ns_res = 1.;
        cellhd.ns_res3 = 1.;
        cellhd.ew_res = 1.;
        cellhd.ew_res3 = 1.;
        cellhd.tb_res = 1.;
    }

    /* suppress boundary splitting ? */
    if (flag.no_clean->answer) {
        split_distance = -1.;
    }
    else {
        split_distance = 0.;
        area_size =
            sqrt((cellhd.east - cellhd.west) * (cellhd.north - cellhd.south));
    }

    /* Fetch input map projection in GRASS form. */
    proj_info = NULL;
    proj_units = NULL;
    Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);	/* should not be freed later */

    /* Do we need to create a new location? */
    if (param.outloc->answer != NULL) {
        /* Convert projection information non-interactively as we can't
         * assume the user has a terminal open */
        if (GPJ_osr_to_grass(&cellhd, &proj_info,
                             &proj_units, Ogr_projection, 0) < 0) {
            G_fatal_error(_("Unable to convert input map projection to GRASS "
                            "format; cannot create new location."));
        }
        else {
            G_make_location(param.outloc->answer, &cellhd,
                            proj_info, proj_units, NULL);
            G_message(_("Location <%s> created"), param.outloc->answer);
        }

        /* If the i flag is set, clean up? and exit here */
        if(flag.no_import->answer)
        {
            exit(EXIT_SUCCESS);
        }
    }
    else {
        int err = 0;

        /* Projection only required for checking so convert non-interactively */
        if (GPJ_osr_to_grass(&cellhd, &proj_info,
                             &proj_units, Ogr_projection, 0) < 0)
            G_warning(_("Unable to convert input map projection information to "
                        "GRASS format for checking"));

        /* Does the projection of the current location match the dataset? */
        /* G_get_window seems to be unreliable if the location has been changed */
        G__get_window(&loc_wind, "", "DEFAULT_WIND", "PERMANENT");
        /* fetch LOCATION PROJ info */
        if (loc_wind.proj != PROJECTION_XY) {
            loc_proj_info = G_get_projinfo();
            loc_proj_units = G_get_projunits();
        }

        if (flag.over->answer) {
            cellhd.proj = loc_wind.proj;
            cellhd.zone = loc_wind.zone;
            G_message(_("Over-riding projection check"));
        }
        else if (loc_wind.proj != cellhd.proj
                 || (err =
                         G_compare_projections(loc_proj_info, loc_proj_units,
                                               proj_info, proj_units)) != TRUE) {
            int i_value;

            strcpy(error_msg,
                   _("Projection of dataset does not"
                     " appear to match current location.\n\n"));

            /* TODO: output this info sorted by key: */
            if (loc_wind.proj != cellhd.proj || err != -2) {
                if (loc_proj_info != NULL) {
                    strcat(error_msg, _("GRASS LOCATION PROJ_INFO is:\n"));
                    for (i_value = 0; i_value < loc_proj_info->nitems;
                            i_value++)
                        sprintf(error_msg + strlen(error_msg), "%s: %s\n",
                                loc_proj_info->key[i_value],
                                loc_proj_info->value[i_value]);
                    strcat(error_msg, "\n");
                }

                if (proj_info != NULL) {
                    strcat(error_msg, _("Import dataset PROJ_INFO is:\n"));
                    for (i_value = 0; i_value < proj_info->nitems; i_value++)
                        sprintf(error_msg + strlen(error_msg), "%s: %s\n",
                                proj_info->key[i_value],
                                proj_info->value[i_value]);
                }
                else {
                    strcat(error_msg, _("Import dataset PROJ_INFO is:\n"));
                    if (cellhd.proj == PROJECTION_XY)
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (unreferenced/unknown)\n",
                                cellhd.proj);
                    else if (cellhd.proj == PROJECTION_LL)
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (lat/long)\n",
                                cellhd.proj);
                    else if (cellhd.proj == PROJECTION_UTM)
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (UTM), zone = %d\n",
                                cellhd.proj, cellhd.zone);
                    else if (cellhd.proj == PROJECTION_SP)
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (State Plane), zone = %d\n",
                                cellhd.proj, cellhd.zone);
                    else
                        sprintf(error_msg + strlen(error_msg),
                                "Dataset proj = %d (unknown), zone = %d\n",
                                cellhd.proj, cellhd.zone);
                }
            }
            else {
                if (loc_proj_units != NULL) {
                    strcat(error_msg, "GRASS LOCATION PROJ_UNITS is:\n");
                    for (i_value = 0; i_value < loc_proj_units->nitems;
                            i_value++)
                        sprintf(error_msg + strlen(error_msg), "%s: %s\n",
                                loc_proj_units->key[i_value],
                                loc_proj_units->value[i_value]);
                    strcat(error_msg, "\n");
                }

                if (proj_units != NULL) {
                    strcat(error_msg, "Import dataset PROJ_UNITS is:\n");
                    for (i_value = 0; i_value < proj_units->nitems; i_value++)
                        sprintf(error_msg + strlen(error_msg), "%s: %s\n",
                                proj_units->key[i_value],
                                proj_units->value[i_value]);
                }
            }
            sprintf(error_msg + strlen(error_msg),
                    _("\nYou can use the -o flag to %s to override this projection check.\n"),
                    G_program_name());
            strcat(error_msg,
                   _("Consider generating a new location with 'location' parameter"
                     " from input data set.\n"));
            G_fatal_error(error_msg);
        }
        else {
            G_message(_("Projection of input dataset and current location "
                        "appear to match"));
        }
    }

    db_init_string(&sql);
    db_init_string(&strval);

    /* open output vector */
    /* strip any @mapset from vector output name */
    G_find_vector(output, G_mapset());
    Vect_open_new(&Map, output, flag.z->answer != 0);
    Out = &Map;

    n_polygon_boundaries = 0;
    if (!flag.no_clean->answer) {
        /* check if we need a tmp vector */

        /* estimate distance for boundary splitting --> */
        for (layer = 0; layer < nlayers; layer++) {
            layer_id = layers[layer];

            Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
            Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);

            n_features = feature_count = 0;

            n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);
            OGR_L_ResetReading(Ogr_layer);

            /* count polygons and isles */
            G_message(_("Counting polygons for %d features (OGR layer <%s>)..."),
                      n_features, layer_names[layer]);
            while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
                G_percent(feature_count++, n_features, 1);	/* show something happens */
                /* Geometry */
                Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
                if (Ogr_geometry != NULL) {
                    poly_count(Ogr_geometry, (type & GV_BOUNDARY));
                }
                OGR_F_Destroy(Ogr_feature);
            }
        }

        G_debug(1, "n polygon boundaries: %d", n_polygon_boundaries);
        if (n_polygon_boundaries > 50) {
            split_distance =
                area_size / log(n_polygon_boundaries);
            /* divisor is the handle: increase divisor to decrease split_distance */
            split_distance = split_distance / 5.;
            G_debug(1, "root of area size: %f", area_size);
            G_verbose_message(_("Boundary splitting distance in map units: %G"),
                              split_distance);
        }
        /* <-- estimate distance for boundary splitting */

        use_tmp_vect = n_polygon_boundaries > 0;

        if (use_tmp_vect) {
            /* open temporary vector, do the work in the temporary vector
             * at the end copy alive lines to output vector
             * in case of polygons this reduces the coor file size by a factor of 2 to 5
             * only needed when cleaning polygons */
            sprintf(tempvect, "%s_tmp", output);
            G_verbose_message(_("Using temporary vector <%s>"), tempvect);
            Vect_open_new(&Tmp, tempvect, flag.z->answer != 0);
            Out = &Tmp;
        }
    }

    Vect_hist_command(&Map);

    /* Points and lines are written immediately with categories. Boundaries of polygons are
     * written to the vector then cleaned and centroids are calculated for all areas in cleaan vector.
     * Then second pass through finds all centroids in each polygon feature and adds its category
     * to the centroid. The result is that one centroids may have 0, 1 ore more categories
     * of one ore more (more input layers) fields. */
    with_z = 0;
    for (layer = 0; layer < nlayers; layer++) {
        layer_id = layers[layer];

        Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
        Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);

        /* Add DB link */
        if (!flag.notab->answer) {
            char *cat_col_name = GV_KEY_COLUMN;

            if (nlayers == 1) {	/* one layer only */
                Fi = Vect_default_field_info(&Map, layer + 1, NULL,
                                             GV_1TABLE);
            }
            else {
                Fi = Vect_default_field_info(&Map, layer + 1, NULL,
                                             GV_MTABLE);
            }

            if (ncnames > 0) {
                cat_col_name = param.cnames->answers[0];
            }
            Vect_map_add_dblink(&Map, layer + 1, layer_names[layer], Fi->table,
                                cat_col_name, Fi->database, Fi->driver);

            ncols = OGR_FD_GetFieldCount(Ogr_featuredefn);
            G_debug(2, "%d columns", ncols);

            /* Create table */
            sprintf(buf, "create table %s (%s integer", Fi->table,
                    cat_col_name);
            db_set_string(&sql, buf);
            for (i = 0; i < ncols; i++) {

                Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i);
                Ogr_ftype = OGR_Fld_GetType(Ogr_field);

                G_debug(3, "Ogr_ftype: %i", Ogr_ftype);	/* look up below */

                if (i < ncnames - 1) {
                    Ogr_fieldname = G_store(param.cnames->answers[i + 1]);
                }
                else {
                    /* Change column names to [A-Za-z][A-Za-z0-9_]* */
                    Ogr_fieldname = G_store(OGR_Fld_GetNameRef(Ogr_field));
                    G_debug(3, "Ogr_fieldname: '%s'", Ogr_fieldname);

                    G_str_to_sql(Ogr_fieldname);

                    G_debug(3, "Ogr_fieldname: '%s'", Ogr_fieldname);

                }

                /* avoid that we get the 'cat' column twice */
                if (strcmp(Ogr_fieldname, GV_KEY_COLUMN) == 0) {
                    sprintf(namebuf, "%s_", Ogr_fieldname);
                    Ogr_fieldname = G_store(namebuf);
                }

                /* captial column names are a pain in SQL */
                if (flag.tolower->answer)
                    G_str_to_lower(Ogr_fieldname);

                if (strcmp(OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname) != 0) {
                    G_warning(_("Column name changed: '%s' -> '%s'"),
                              OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname);
                }

                /** Simple 32bit integer                     OFTInteger = 0        **/

                /** List of 32bit integers                   OFTIntegerList = 1    **/

                /** Double Precision floating point          OFTReal = 2           **/

                /** List of doubles                          OFTRealList = 3       **/

                /** String of ASCII chars                    OFTString = 4         **/

                /** Array of strings                         OFTStringList = 5     **/

                /** Double byte string (unsupported)         OFTWideString = 6     **/

                /** List of wide strings (unsupported)       OFTWideStringList = 7 **/

                /** Raw Binary data (unsupported)            OFTBinary = 8         **/

                /**                                          OFTDate = 9           **/

                /**                                          OFTTime = 10          **/

                /**                                          OFTDateTime = 11      **/


                if (Ogr_ftype == OFTInteger) {
                    sprintf(buf, ", %s integer", Ogr_fieldname);
                }
                else if (Ogr_ftype == OFTIntegerList) {
                    /* hack: treat as string */
                    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
                            OFTIntegerListlength);
                    G_warning(_("Writing column <%s> with fixed length %d chars (may be truncated)"),
                              Ogr_fieldname, OFTIntegerListlength);
                }
                else if (Ogr_ftype == OFTReal) {
                    sprintf(buf, ", %s double precision", Ogr_fieldname);
#if GDAL_VERSION_NUM >= 1320
                }
                else if (Ogr_ftype == OFTDate) {
                    sprintf(buf, ", %s date", Ogr_fieldname);
                }
                else if (Ogr_ftype == OFTTime) {
                    sprintf(buf, ", %s time", Ogr_fieldname);
                }
                else if (Ogr_ftype == OFTDateTime) {
                    sprintf(buf, ", %s datetime", Ogr_fieldname);
#endif
                }
                else if (Ogr_ftype == OFTString) {
                    int fwidth;

                    fwidth = OGR_Fld_GetWidth(Ogr_field);
                    /* TODO: read all records first and find the longest string length */
                    if (fwidth == 0) {
                        G_warning(_("Width for column %s set to 255 (was not specified by OGR), "
                                    "some strings may be truncated!"),
                                  Ogr_fieldname);
                        fwidth = 255;
                    }
                    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
                            fwidth);
                }
                else if (Ogr_ftype == OFTStringList) {
                    /* hack: treat as string */
                    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
                            OFTIntegerListlength);
                    G_warning(_("Writing column %s with fixed length %d chars (may be truncated)"),
                              Ogr_fieldname, OFTIntegerListlength);
                }
                else {
                    G_warning(_("Column type not supported (%s)"),
                              Ogr_fieldname);
                    buf[0] = 0;
                }
                db_append_string(&sql, buf);
                G_free(Ogr_fieldname);
            }
            db_append_string(&sql, ")");
            G_debug(3, db_get_string(&sql));

            driver =
                db_start_driver_open_database(Fi->driver,
                                              Vect_subst_var(Fi->database,
                                                      &Map));
            if (driver == NULL) {
                G_fatal_error(_("Unable open database <%s> by driver <%s>"),
                              Vect_subst_var(Fi->database, &Map), Fi->driver);
            }

            if (db_execute_immediate(driver, &sql) != DB_OK) {
                db_close_database(driver);
                db_shutdown_driver(driver);
                G_fatal_error(_("Unable to create table: '%s'"),
                              db_get_string(&sql));
            }

            if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK)
                G_warning(_("Unable to create index for table <%s>, key <%s>"),
                          Fi->table, cat_col_name);

            if (db_grant_on_table
                    (driver, Fi->table, DB_PRIV_SELECT,
                     DB_GROUP | DB_PUBLIC) != DB_OK)
                G_fatal_error(_("Unable to grant privileges on table <%s>"),
                              Fi->table);

            db_begin_transaction(driver);
        }

        /* Import feature */
        cat = 1;
        nogeom = 0;
        OGR_L_ResetReading(Ogr_layer);
        n_features = feature_count = 0;

        n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);

        G_important_message(_("Importing %d features (OGR layer <%s>)..."),
                            n_features, layer_names[layer]);
        while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
            G_percent(feature_count++, n_features, 1);	/* show something happens */
            /* Geometry */
            Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
            if (Ogr_geometry == NULL) {
                nogeom++;
            }
            else {
                dim = OGR_G_GetCoordinateDimension(Ogr_geometry);
                if (dim > 2)
                    with_z = 1;

                geom(Ogr_geometry, Out, layer + 1, cat, min_area, type,
                     flag.no_clean->answer);
            }

            /* Attributes */
            if (!flag.notab->answer) {
                sprintf(buf, "insert into %s values ( %d", Fi->table, cat);
                db_set_string(&sql, buf);
                for (i = 0; i < ncols; i++) {
                    Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i);
                    Ogr_ftype = OGR_Fld_GetType(Ogr_field);
                    if (OGR_F_IsFieldSet(Ogr_feature, i)) {
                        if (Ogr_ftype == OFTInteger || Ogr_ftype == OFTReal) {
                            sprintf(buf, ", %s",
                                    OGR_F_GetFieldAsString(Ogr_feature, i));
#if GDAL_VERSION_NUM >= 1320
                            /* should we use OGR_F_GetFieldAsDateTime() here ? */
                        }
                        else if (Ogr_ftype == OFTDate || Ogr_ftype == OFTTime
                                 || Ogr_ftype == OFTDateTime) {
                            char *newbuf;

                            db_set_string(&strval, (char *)
                                          OGR_F_GetFieldAsString(Ogr_feature,
                                                                 i));
                            db_double_quote_string(&strval);
                            sprintf(buf, ", '%s'", db_get_string(&strval));
                            newbuf = G_str_replace(buf, "/", "-");	/* fix 2001/10/21 to 2001-10-21 */
                            sprintf(buf, "%s", newbuf);
#endif
                        }
                        else if (Ogr_ftype == OFTString ||
                                 Ogr_ftype == OFTIntegerList) {
                            db_set_string(&strval, (char *)
                                          OGR_F_GetFieldAsString(Ogr_feature,
                                                                 i));
                            db_double_quote_string(&strval);
                            sprintf(buf, ", '%s'", db_get_string(&strval));
                        }

                    }
                    else {
                        /* G_warning (_("Column value not set" )); */
                        if (Ogr_ftype == OFTInteger || Ogr_ftype == OFTReal) {
                            sprintf(buf, ", NULL");
#if GDAL_VERSION_NUM >= 1320
                        }
                        else if (Ogr_ftype == OFTString ||
                                 Ogr_ftype == OFTIntegerList ||
                                 Ogr_ftype == OFTDate) {
#else
                        }
                        else if (Ogr_ftype == OFTString ||
                                 Ogr_ftype == OFTIntegerList) {
#endif
                            sprintf(buf, ", ''");
                        }
                    }
                    db_append_string(&sql, buf);
                }
                db_append_string(&sql, " )");
                G_debug(3, db_get_string(&sql));

                if (db_execute_immediate(driver, &sql) != DB_OK) {
                    db_close_database(driver);
                    db_shutdown_driver(driver);
                    G_fatal_error(_("Cannot insert new row: %s"),
                                  db_get_string(&sql));
                }
            }

            OGR_F_Destroy(Ogr_feature);
            cat++;
        }
        G_percent(1, 1, 1);	/* finish it */

        if (!flag.notab->answer) {
            db_commit_transaction(driver);
            db_close_database_shutdown_driver(driver);
        }

        if (nogeom > 0)
            G_warning(_("%d %s without geometry"), nogeom,
                      nogeom == 1 ? "feature" : "features");
    }


    separator = "-----------------------------------------------------";
    G_message("%s", separator);

    if (use_tmp_vect) {
        /* TODO: is it necessary to build here? probably not, consumes time */
        /* GV_BUILD_BASE is sufficient to toggle boundary cleaning */
        Vect_build_partial(&Tmp, GV_BUILD_BASE);
    }

    if (use_tmp_vect && !flag.no_clean->answer &&
            Vect_get_num_primitives(Out, GV_BOUNDARY) > 0) {
        int ret, centr, ncentr, otype, n_overlaps, n_nocat;
        CENTR *Centr;
        struct spatial_index si;
        double x, y, total_area, overlap_area, nocat_area;
        struct bound_box box;
        struct line_pnts *Points;
        int nmodif;

        Points = Vect_new_line_struct();

        G_message("%s", separator);

        G_warning(_("Cleaning polygons, result is not guaranteed!"));

        if (snap >= 0) {
            G_message("%s", separator);
            G_message(_("Snapping boundaries (threshold = %.3e)..."), snap);
            Vect_snap_lines(&Tmp, GV_BOUNDARY, snap, NULL);
        }

        /* It is not to clean to snap centroids, but I have seen data with 2 duplicate polygons
         * (as far as decimal places were printed) and centroids were not identical */
        /* Disabled, because overlapping polygons result in many duplicate centroids anyway */
        /*
           fprintf ( stderr, separator );
           fprintf ( stderr, "Snap centroids (threshold 0.000001):\n" );
           Vect_snap_lines ( &Map, GV_CENTROID, 0.000001, NULL, stderr );
         */

        G_message("%s", separator);
        G_message(_("Breaking polygons..."));
        Vect_break_polygons(&Tmp, GV_BOUNDARY, NULL);

        /* It is important to remove also duplicate centroids in case of duplicate input polygons */
        G_message("%s", separator);
        G_message(_("Removing duplicates..."));
        Vect_remove_duplicates(&Tmp, GV_BOUNDARY | GV_CENTROID, NULL);

        /* in non-pathological cases, the bulk of the cleaning is now done */

        /* Vect_clean_small_angles_at_nodes() can change the geometry so that new intersections
         * are created. We must call Vect_break_lines(), Vect_remove_duplicates()
         * and Vect_clean_small_angles_at_nodes() until no more small angles are found */
        do {
            G_message("%s", separator);
            G_message(_("Breaking boundaries..."));
            Vect_break_lines(&Tmp, GV_BOUNDARY, NULL);

            G_message("%s", separator);
            G_message(_("Removing duplicates..."));
            Vect_remove_duplicates(&Tmp, GV_BOUNDARY, NULL);

            G_message("%s", separator);
            G_message(_("Cleaning boundaries at nodes..."));
            nmodif =
                Vect_clean_small_angles_at_nodes(&Tmp, GV_BOUNDARY, NULL);
        } while (nmodif > 0);

        /* merge boundaries */
        G_message("%s", separator);
        G_message(_("Merging boundaries..."));
        Vect_merge_lines(&Tmp, GV_BOUNDARY, NULL, NULL);

        G_message("%s", separator);
        if (type & GV_BOUNDARY) {	/* that means lines were converted to boundaries */
            G_message(_("Changing boundary dangles to lines..."));
            Vect_chtype_dangles(&Tmp, -1.0, NULL);
        }
        else {
            G_message(_("Removing dangles..."));
            Vect_remove_dangles(&Tmp, GV_BOUNDARY, -1.0, NULL);
        }

        G_message("%s", separator);
        if (type & GV_BOUNDARY) {
            G_message(_("Changing boundary bridges to lines..."));
            Vect_chtype_bridges(&Tmp, NULL);
        }
        else {
            G_message(_("Removing bridges..."));
            Vect_remove_bridges(&Tmp, NULL);
        }

        /* Boundaries are hopefully clean, build areas */
        G_message("%s", separator);
        Vect_build_partial(&Tmp, GV_BUILD_ATTACH_ISLES);

        /* Calculate new centroids for all areas, centroids have the same id as area */
        ncentr = Vect_get_num_areas(&Tmp);
        G_debug(3, "%d centroids/areas", ncentr);

        Centr = (CENTR *) G_calloc(ncentr + 1, sizeof(CENTR));
        Vect_spatial_index_init(&si, 0);
        for (centr = 1; centr <= ncentr; centr++) {
            Centr[centr].valid = 0;
            Centr[centr].cats = Vect_new_cats_struct();
            ret = Vect_get_point_in_area(&Tmp, centr, &x, &y);
            if (ret < 0) {
                G_warning(_("Unable to calculate area centroid"));
                continue;
            }

            Centr[centr].x = x;
            Centr[centr].y = y;
            Centr[centr].valid = 1;
            box.N = box.S = y;
            box.E = box.W = x;
            box.T = box.B = 0;
            Vect_spatial_index_add_item(&si, centr, &box);
        }

        /* Go through all layers and find centroids for each polygon */
        for (layer = 0; layer < nlayers; layer++) {
            G_message("%s", separator);
            G_message(_("Finding centroids for OGR layer <%s>..."), layer_names[layer]);
            layer_id = layers[layer];
            Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
            n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);
            OGR_L_ResetReading(Ogr_layer);

            cat = 0;		/* field = layer + 1 */
            G_percent(cat, n_features, 2);
            while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
                cat++;
                G_percent(cat, n_features, 2);
                /* Geometry */
                Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
                if (Ogr_geometry != NULL) {
                    centroid(Ogr_geometry, Centr, &si, layer + 1, cat,
                             min_area, type);
                }

                OGR_F_Destroy(Ogr_feature);
            }
        }

        /* Write centroids */
        G_message("%s", separator);
        G_message(_("Writing centroids..."));

        n_overlaps = n_nocat = 0;
        total_area = overlap_area = nocat_area = 0.0;
        for (centr = 1; centr <= ncentr; centr++) {
            double area;

            G_percent(centr, ncentr, 2);

            area = Vect_get_area_area(&Tmp, centr);
            total_area += area;

            if (!(Centr[centr].valid)) {
                continue;
            }

            if (Centr[centr].cats->n_cats == 0) {
                nocat_area += area;
                n_nocat++;
                continue;
            }

            if (Centr[centr].cats->n_cats > 1) {
                Vect_cat_set(Centr[centr].cats, nlayers + 1,
                             Centr[centr].cats->n_cats);
                overlap_area += area;
                n_overlaps++;
            }

            Vect_reset_line(Points);
            Vect_append_point(Points, Centr[centr].x, Centr[centr].y, 0.0);
            if (type & GV_POINT)
                otype = GV_POINT;
            else
                otype = GV_CENTROID;
            Vect_write_line(&Tmp, otype, Points, Centr[centr].cats);
        }
        if (Centr)
            G_free(Centr);

        Vect_spatial_index_destroy(&si);

        if (n_overlaps > 0) {
            G_warning(_("%d areas represent more (overlapping) features, because polygons overlap "
                        "in input layer(s). Such areas are linked to more than 1 row in attribute table. "
                        "The number of features for those areas is stored as category in layer %d"),
                      n_overlaps, nlayers + 1);
        }

        G_message("%s", separator);

        Vect_hist_write(&Map, separator);
        Vect_hist_write(&Map, "\n");
        sprintf(buf, _("%d input polygons\n"), n_polygons);
        G_message(_("%d input polygons"), n_polygons);
        Vect_hist_write(&Map, buf);

        sprintf(buf, _("Total area: %G (%d areas)\n"), total_area, ncentr);
        G_message(_("Total area: %G (%d areas)"), total_area, ncentr);
        Vect_hist_write(&Map, buf);

        sprintf(buf, _("Overlapping area: %G (%d areas)\n"), overlap_area,
                n_overlaps);
        G_message(_("Overlapping area: %G (%d areas)"), overlap_area,
                  n_overlaps);
        Vect_hist_write(&Map, buf);

        sprintf(buf, _("Area without category: %G (%d areas)\n"), nocat_area,
                n_nocat);
        G_message(_("Area without category: %G (%d areas)"), nocat_area,
                  n_nocat);
        Vect_hist_write(&Map, buf);
        G_message("%s", separator);
    }

    /* needed?
     * OGR_DS_Destroy( Ogr_ds );
     */

    if (use_tmp_vect) {
        /* Copy temporary vector to output vector */
        Vect_copy_map_lines(&Tmp, &Map);
        /* release memory occupied by topo, we may need that memory for main output */
        Vect_set_release_support(&Tmp);
        Vect_close(&Tmp);
        Vect_delete(tempvect);
    }

    Vect_build(&Map);
    Vect_close(&Map);

    /* -------------------------------------------------------------------- */
    /*      Extend current window based on dataset.                         */
    /* -------------------------------------------------------------------- */
    if (flag.extend->answer) {
        G_get_default_window(&loc_wind);

        loc_wind.north = MAX(loc_wind.north, cellhd.north);
        loc_wind.south = MIN(loc_wind.south, cellhd.south);
        loc_wind.west = MIN(loc_wind.west, cellhd.west);
        loc_wind.east = MAX(loc_wind.east, cellhd.east);

        loc_wind.rows = (int)ceil((loc_wind.north - loc_wind.south)
                                  / loc_wind.ns_res);
        loc_wind.south = loc_wind.north - loc_wind.rows * loc_wind.ns_res;

        loc_wind.cols = (int)ceil((loc_wind.east - loc_wind.west)
                                  / loc_wind.ew_res);
        loc_wind.east = loc_wind.west + loc_wind.cols * loc_wind.ew_res;

        G__put_window(&loc_wind, "../PERMANENT", "DEFAULT_WIND");
    }

    if (with_z && !flag.z->answer)
        G_warning(_("Input data contains 3D features. Created vector is 2D only, "
                    "use -z flag to import 3D vector."));

    exit(EXIT_SUCCESS);
}
int main( int argc, char ** argv )
{
    GDALDriverH     hDriver;
    const char      *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
    int             bFormatExplicitelySet = FALSE;
    char            **papszLayers = NULL;
    const char      *pszBurnAttribute = NULL;
    double          dfIncreaseBurnValue = 0.0;
    double          dfMultiplyBurnValue = 1.0;
    const char      *pszWHERE = NULL, *pszSQL = NULL;
    GDALDataType    eOutputType = GDT_Float64;
    char            **papszCreateOptions = NULL;
    GUInt32         nXSize = 0, nYSize = 0;
    double          dfXMin = 0.0, dfXMax = 0.0, dfYMin = 0.0, dfYMax = 0.0;
    int             bIsXExtentSet = FALSE, bIsYExtentSet = FALSE;
    GDALGridAlgorithm eAlgorithm = GGA_InverseDistanceToAPower;
    void            *pOptions = NULL;
    char            *pszOutputSRS = NULL;
    int             bQuiet = FALSE;
    GDALProgressFunc pfnProgress = GDALTermProgress;
    int             i;
    OGRGeometry     *poSpatialFilter = NULL;
    int             bClipSrc = FALSE;
    OGRGeometry     *poClipSrc = NULL;
    const char      *pszClipSrcDS = NULL;
    const char      *pszClipSrcSQL = NULL;
    const char      *pszClipSrcLayer = NULL;
    const char      *pszClipSrcWhere = NULL;

    /* Check strict compilation and runtime library version as we use C++ API */
    if (! GDAL_CHECK_VERSION(argv[0]))
        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],"--help") )
            Usage();
        else if( EQUAL(argv[i],"-of") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszFormat = argv[++i];
            bFormatExplicitelySet = TRUE;
        }

        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
        {
            bQuiet = TRUE;
            pfnProgress = GDALDummyProgress;
        }

        else if( EQUAL(argv[i],"-ot") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(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 )
            {
                Usage(CPLSPrintf("Unknown output pixel type: %s.",
                                 argv[i + 1] ));
            }
            i++;
        }

        else if( EQUAL(argv[i],"-txe") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
            dfXMin = atof(argv[++i]);
            dfXMax = atof(argv[++i]);
            bIsXExtentSet = TRUE;
        }   

        else if( EQUAL(argv[i],"-tye") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
            dfYMin = atof(argv[++i]);
            dfYMax = atof(argv[++i]);
            bIsYExtentSet = TRUE;
        }   

        else if( EQUAL(argv[i],"-outsize") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
            nXSize = atoi(argv[++i]);
            nYSize = atoi(argv[++i]);
        }   

        else if( EQUAL(argv[i],"-co") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
        }   

        else if( EQUAL(argv[i],"-zfield") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszBurnAttribute = argv[++i];
        }

        else if( EQUAL(argv[i],"-z_increase") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            dfIncreaseBurnValue = atof(argv[++i]);
        }

        else if( EQUAL(argv[i],"-z_multiply") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            dfMultiplyBurnValue = atof(argv[++i]);
        }

        else if( EQUAL(argv[i],"-where") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszWHERE = argv[++i];
        }

        else if( EQUAL(argv[i],"-l") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            papszLayers = CSLAddString( papszLayers, argv[++i] );
        }

        else if( EQUAL(argv[i],"-sql") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszSQL = argv[++i];
        }

        else if( EQUAL(argv[i],"-spat") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
            OGRLinearRing  oRing;

            oRing.addPoint( atof(argv[i+1]), atof(argv[i+2]) );
            oRing.addPoint( atof(argv[i+1]), atof(argv[i+4]) );
            oRing.addPoint( atof(argv[i+3]), atof(argv[i+4]) );
            oRing.addPoint( atof(argv[i+3]), atof(argv[i+2]) );
            oRing.addPoint( atof(argv[i+1]), atof(argv[i+2]) );

            poSpatialFilter = new OGRPolygon();
            ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
            i += 4;
        }

        else if ( EQUAL(argv[i],"-clipsrc") )
        {
            if (i + 1 >= argc)
                Usage(CPLSPrintf("%s option requires 1 or 4 arguments", argv[i]));

            bClipSrc = TRUE;
            errno = 0;
            const double unused = strtod( argv[i + 1], NULL );    // XXX: is it a number or not?
            if ( errno != 0
                 && argv[i + 2] != NULL
                 && argv[i + 3] != NULL
                 && argv[i + 4] != NULL)
            {
                OGRLinearRing  oRing;

                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 2]) );
                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 4]) );
                oRing.addPoint( atof(argv[i + 3]), atof(argv[i + 4]) );
                oRing.addPoint( atof(argv[i + 3]), atof(argv[i + 2]) );
                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 2]) );

                poClipSrc = new OGRPolygon();
                ((OGRPolygon *) poClipSrc)->addRing( &oRing );
                i += 4;

                (void)unused;
            }
            else if (EQUALN(argv[i + 1], "POLYGON", 7)
                     || EQUALN(argv[i + 1], "MULTIPOLYGON", 12))
            {
                OGRGeometryFactory::createFromWkt(&argv[i + 1], NULL, &poClipSrc);
                if ( poClipSrc == NULL )
                {
                    Usage("Invalid geometry. "
                             "Must be a valid POLYGON or MULTIPOLYGON WKT.");
                }
                i++;
            }
            else if (EQUAL(argv[i + 1], "spat_extent") )
            {
                i++;
            }
            else
            {
                pszClipSrcDS = argv[i + 1];
                i++;
            }
        }

        else if ( EQUAL(argv[i], "-clipsrcsql") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszClipSrcSQL = argv[i + 1];
            i++;
        }

        else if ( EQUAL(argv[i], "-clipsrclayer") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszClipSrcLayer = argv[i + 1];
            i++;
        }

        else if ( EQUAL(argv[i], "-clipsrcwhere") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszClipSrcWhere = argv[i + 1];
            i++;
        }

        else if( EQUAL(argv[i],"-a_srs") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            OGRSpatialReference oOutputSRS;

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

            oOutputSRS.exportToWkt( &pszOutputSRS );
            i++;
        }   

        else if( EQUAL(argv[i],"-a") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            if ( ParseAlgorithmAndOptions( argv[++i], &eAlgorithm, &pOptions )
                 != CE_None )
            {
                fprintf( stderr,
                         "Failed to process algorithm name and parameters.\n" );
                exit( 1 );
            }
        }

        else if( argv[i][0] == '-' )
        {
            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
        }

        else if( pszSource == NULL )
        {
            pszSource = argv[i];
        }

        else if( pszDest == NULL )
        {
            pszDest = argv[i];
        }

        else
        {
            Usage("Too many command options.");
        }
    }

    if( pszSource == NULL )
    {
        Usage("Source datasource is not specified.");
    }
    if( pszDest == NULL )
    {
        Usage("Target dataset is not specified.");
    }
    if( pszSQL == NULL && papszLayers == NULL )
    {
        Usage("Neither -sql nor -l are specified.");
    }
    
    if ( bClipSrc && pszClipSrcDS != NULL )
    {
        poClipSrc = LoadGeometry( pszClipSrcDS, pszClipSrcSQL,
                                  pszClipSrcLayer, pszClipSrcWhere );
        if ( poClipSrc == NULL )
        {
            Usage("Cannot load source clip geometry.");
        }
    }
    else if ( bClipSrc && poClipSrc == NULL && !poSpatialFilter )
    {
        Usage("-clipsrc must be used with -spat option or \n"
                 "a bounding box, WKT string or datasource must be "
                 "specified.");
    }

    if ( poSpatialFilter )
    {
        if ( poClipSrc )
        {
            OGRGeometry *poTemp = poSpatialFilter->Intersection( poClipSrc );

            if ( poTemp )
            {
                OGRGeometryFactory::destroyGeometry( poSpatialFilter );
                poSpatialFilter = poTemp;
            }

            OGRGeometryFactory::destroyGeometry( poClipSrc );
            poClipSrc = NULL;
        }
    }
    else
    {
        if ( poClipSrc )
        {
            poSpatialFilter = poClipSrc;
            poClipSrc = NULL;
        }
    }

/* -------------------------------------------------------------------- */
/*      Find the output driver.                                         */
/* -------------------------------------------------------------------- */
    hDriver = GDALGetDriverByName( pszFormat );
    if( hDriver == NULL )
    {
        int	iDr;
        
        fprintf( stderr,
                 "FAILURE: Output driver `%s' not recognised.\n", pszFormat );
        fprintf( stderr,
        "The following format drivers are configured and support output:\n" );
        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
        {
            GDALDriverH hDriver = GDALGetDriver(iDr);

            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
                                        NULL ) != NULL )
            {
                fprintf( stderr, "  %s: %s\n",
                         GDALGetDriverShortName( hDriver  ),
                         GDALGetDriverLongName( hDriver ) );
            }
        }
        printf( "\n" );
        Usage();
    }

/* -------------------------------------------------------------------- */
/*      Open input datasource.                                          */
/* -------------------------------------------------------------------- */
    OGRDataSourceH hSrcDS;

    hSrcDS = OGROpen( pszSource, FALSE, NULL );
    if( hSrcDS == NULL )
    {
        fprintf( stderr, "Unable to open input datasource \"%s\".\n",
                 pszSource );
        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
        exit( 3 );
    }

/* -------------------------------------------------------------------- */
/*      Create target raster file.                                      */
/* -------------------------------------------------------------------- */
    GDALDatasetH    hDstDS;
    int             nLayerCount = CSLCount(papszLayers);
    int             nBands = nLayerCount;

    if ( pszSQL )
        nBands++;

    // FIXME
    if ( nXSize == 0 )
        nXSize = 256;
    if ( nYSize == 0 )
        nYSize = 256;

    if (!bQuiet && !bFormatExplicitelySet)
        CheckExtensionConsistency(pszDest, pszFormat);

    hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands,
                         eOutputType, papszCreateOptions );
    if ( hDstDS == NULL )
    {
        fprintf( stderr, "Unable to create target dataset \"%s\".\n",
                 pszDest );
        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
        exit( 3 );
    }

/* -------------------------------------------------------------------- */
/*      If algorithm was not specified assigh default one.              */
/* -------------------------------------------------------------------- */
    if ( !pOptions )
        ParseAlgorithmAndOptions( szAlgNameInvDist, &eAlgorithm, &pOptions );

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

        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL,
                                    (OGRGeometryH)poSpatialFilter, NULL ); 
        if( hLayer != NULL )
        {
            // Custom layer will be rasterized in the first band.
            ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize, 1,
                          bIsXExtentSet, bIsYExtentSet,
                          dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
                          dfIncreaseBurnValue, dfMultiplyBurnValue, eOutputType, eAlgorithm, pOptions,
                          bQuiet, pfnProgress );
        }
    }

/* -------------------------------------------------------------------- */
/*      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;
        }

        if ( poSpatialFilter != NULL )
            OGR_L_SetSpatialFilter( hLayer, (OGRGeometryH)poSpatialFilter );

        // Fetch the first meaningful SRS definition
        if ( !pszOutputSRS )
        {
            OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( hLayer );
            if ( hSRS )
                OSRExportToWkt( hSRS, &pszOutputSRS );
        }

        ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize,
                      i + 1 + nBands - nLayerCount,
                      bIsXExtentSet, bIsYExtentSet,
                      dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
                      dfIncreaseBurnValue, dfMultiplyBurnValue, eOutputType, eAlgorithm, pOptions,
                      bQuiet, pfnProgress );
    }

/* -------------------------------------------------------------------- */
/*      Apply geotransformation matrix.                                 */
/* -------------------------------------------------------------------- */
    double  adfGeoTransform[6];
    adfGeoTransform[0] = dfXMin;
    adfGeoTransform[1] = (dfXMax - dfXMin) / nXSize;
    adfGeoTransform[2] = 0.0;
    adfGeoTransform[3] = dfYMin;
    adfGeoTransform[4] = 0.0;
    adfGeoTransform[5] = (dfYMax - dfYMin) / nYSize;
    GDALSetGeoTransform( hDstDS, adfGeoTransform );

/* -------------------------------------------------------------------- */
/*      Apply SRS definition if set.                                    */
/* -------------------------------------------------------------------- */
    if ( pszOutputSRS )
    {
        GDALSetProjection( hDstDS, pszOutputSRS );
        CPLFree( pszOutputSRS );
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    OGR_DS_Destroy( hSrcDS );
    GDALClose( hDstDS );
    OGRGeometryFactory::destroyGeometry( poSpatialFilter );

    CPLFree( pOptions );
    CSLDestroy( papszCreateOptions );
    CSLDestroy( argv );
    CSLDestroy( papszLayers );

    OGRCleanupAll();

    GDALDestroyDriverManager();
 
    return 0;
}