[GRASS-SVN] r71558 - in grass/trunk: raster/r.external raster/r.in.gdal vector/v.external vector/v.in.ogr

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Oct 15 09:43:51 PDT 2017


Author: mmetz
Date: 2017-10-15 09:43:51 -0700 (Sun, 15 Oct 2017)
New Revision: 71558

Added:
   grass/trunk/raster/r.in.gdal/proj.c
   grass/trunk/vector/v.in.ogr/proj.c
Modified:
   grass/trunk/raster/r.external/main.c
   grass/trunk/raster/r.external/proj.c
   grass/trunk/raster/r.external/proto.h
   grass/trunk/raster/r.in.gdal/main.c
   grass/trunk/vector/v.external/args.c
   grass/trunk/vector/v.external/dsn.c
   grass/trunk/vector/v.external/local_proto.h
   grass/trunk/vector/v.external/main.c
   grass/trunk/vector/v.external/proj.c
   grass/trunk/vector/v.in.ogr/global.h
   grass/trunk/vector/v.in.ogr/main.c
Log:
sync projection check between r.in.gdal, r.external, v.in.ogr, v.external

Modified: grass/trunk/raster/r.external/main.c
===================================================================
--- grass/trunk/raster/r.external/main.c	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/raster/r.external/main.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -44,7 +44,7 @@
 	struct Option *input, *source, *output, *band, *title;
     } parm;
     struct {
-	struct Flag *o, *f, *e, *h, *v, *t, *a;
+	struct Flag *o, *j, *f, *e, *h, *v, *t, *a;
     } flag;
     int min_band, max_band, band;
     struct band_info info;
@@ -103,6 +103,12 @@
     flag.o->description =
 	_("Assume that the dataset has same projection as the current location");
 
+    flag.j = G_define_flag();
+    flag.j->key = 'j';
+    flag.j->description =
+	_("Perform projection check only and exit");
+    flag.j->suppress_required = YES;
+
     flag.e = G_define_flag();
     flag.e->key = 'e';
     flag.e->label = _("Extend region extents based on new dataset");
@@ -191,7 +197,7 @@
         exit(EXIT_SUCCESS);
     }
 
-    check_projection(&cellhd, hDS, flag.o->answer);
+    check_projection(&cellhd, hDS, NULL, 0, flag.o->answer, flag.j->answer);
 
     if (flag.a->answer && cellhd.proj == PROJECTION_LL) {
 	G_adjust_Cell_head(&cellhd, 1, 1);

Modified: grass/trunk/raster/r.external/proj.c
===================================================================
--- grass/trunk/raster/r.external/proj.c	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/raster/r.external/proj.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -3,26 +3,113 @@
 #include <grass/glocale.h>
 
 #include <gdal.h>
+#include <ogr_srs_api.h>
 
-void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, int override)
+/* keep in sync with r.in.gdal, v.in.ogr, v.external */
+void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS,
+                      char *outloc, int create_only, int override,
+		      int check_only)
 {
     struct Cell_head loc_wind;
     struct Key_Value *proj_info = NULL, *proj_units = NULL;
     struct Key_Value *loc_proj_info = NULL, *loc_proj_units = NULL;
-    int projcomp_error = 0;
+    const char *wkt;
     char error_msg[8096];
+    int proj_trouble;
 
+    /* -------------------------------------------------------------------- */
+    /*      Fetch the projection in GRASS form.                             */
+    /* -------------------------------------------------------------------- */
+    proj_info = NULL;
+    proj_units = NULL;
+    wkt = GDALGetProjectionRef(hDS);
+    /* proj_trouble:
+     * 0: valid srs
+     * 1: no srs, default to xy
+     * 2: unreadable srs, default to xy
+     */
+
     /* Projection only required for checking so convert non-interactively */
-    if (GPJ_wkt_to_grass(cellhd, &proj_info,
-			 &proj_units, GDALGetProjectionRef(hDS), 0) < 0)
-	G_warning(_("Unable to convert input raster map projection information to "
-		    "GRASS format for checking"));
+    proj_trouble = 0;
+    if (wkt && *wkt) {
+	OGRSpatialReferenceH hSRS;
+
+	hSRS = OSRNewSpatialReference(wkt);
+	GPJ_osr_to_grass(cellhd, &proj_info, &proj_units, hSRS, 0);
+
+	if (!OSRIsProjected(hSRS) && !OSRIsGeographic(hSRS)) {
+	    G_important_message(_("Input contains an invalid SRS. " 
+	                          "WKT definition:\n%s"), wkt);
+
+	    proj_trouble = 2;
+	}
+	if (hSRS)
+	    OSRDestroySpatialReference(hSRS);
+    }
     else {
+	G_important_message(_("No projection information available"));
+	cellhd->proj = PROJECTION_XY;
+	cellhd->zone = 0;
+	proj_trouble = 1;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Do we need to create a new location?                            */
+    /* -------------------------------------------------------------------- */
+    if (outloc != NULL) {
+	/* do not create a xy location if an existing SRS was unreadable */ 
+	if (proj_trouble == 2) {
+	    G_fatal_error(_("Unable to convert input map projection to GRASS "
+			    "format; cannot create new location."));
+	}
+	else {
+            if (0 != G_make_location(outloc, cellhd,
+                                     proj_info, proj_units)) {
+                G_fatal_error(_("Unable to create new location <%s>"),
+                              outloc);
+            }
+	    G_message(_("Location <%s> created"), outloc);
+
+	    G_unset_window();	/* new location, projection, and window */
+	    G_get_window(cellhd);
+	}
+
+        /* If create only, clean up and exit here */
+        if (create_only) {
+	    GDALClose(hDS);
+            exit(EXIT_SUCCESS);
+        }
+    }
+    else {
+	int err = 0;
+        void (*msg_fn)(const char *, ...);
+
+	if (check_only && override) {
+	    /* can't check when over-riding check */
+	    override = 0;
+	}
+
+	if (proj_trouble == 2) {
+	    strcpy(error_msg, _("Unable to convert input map projection information "
+		                "to GRASS format."));
+            if (override) {
+                msg_fn = G_warning;
+	    }
+            else {
+                msg_fn = G_fatal_error;
+	    }
+            msg_fn(error_msg);
+            if (!override) {
+                exit(EXIT_FAILURE);
+	    }
+	}
+
 	/* -------------------------------------------------------------------- */
 	/*      Does the projection of the current location match the           */
 	/*      dataset?                                                        */
 	/* -------------------------------------------------------------------- */
 	G_get_default_window(&loc_wind);
+	/* fetch LOCATION PROJ info */
 	if (loc_wind.proj != PROJECTION_XY) {
 	    loc_proj_info = G_get_projinfo();
 	    loc_proj_units = G_get_projunits();
@@ -31,11 +118,12 @@
 	if (override) {
 	    cellhd->proj = loc_wind.proj;
 	    cellhd->zone = loc_wind.zone;
-	    G_warning(_("Over-riding projection check"));
+	    G_message(_("Over-riding projection check"));
 	}
-	else if (loc_wind.proj != cellhd->proj ||
-		 (projcomp_error = G_compare_projections(
-		      loc_proj_info, loc_proj_units, proj_info, proj_units)) < 0) {
+	else if (loc_wind.proj != cellhd->proj
+		 || (err =
+		     G_compare_projections(loc_proj_info, loc_proj_units,
+					   proj_info, proj_units)) != 1) {
 	    int i_value;
 
 	    strcpy(error_msg,
@@ -43,65 +131,100 @@
 		     " appear to match current location.\n\n"));
 
 	    /* TODO: output this info sorted by key: */
-	    if (loc_proj_info != NULL) {
-		strcat(error_msg, _("Location PROJ_INFO is:\n"));
-		for (i_value = 0;
-		     loc_proj_info != NULL &&
-			 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 (loc_wind.proj != cellhd->proj || err != -2) {
+		/* error in proj_info */
+		if (loc_proj_info != NULL) {
+		    strcat(error_msg, _("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, _("Dataset PROJ_INFO is:\n"));
-		for (i_value = 0;
-		     proj_info != NULL && 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]);
-		strcat(error_msg, "\nERROR: ");
-		switch (projcomp_error) {
-		case -1:
-		    strcat(error_msg, "proj\n");
-		    break;
-		case -2:
-		    strcat(error_msg, "units\n");
-		    break;
-		case -3:
-		    strcat(error_msg, "datum\n");
-		    break;
-		case -4:
-		    strcat(error_msg, "ellps\n");
-		    break;
-		case -5:
-		    strcat(error_msg, "zone\n");
-		    break;
+		if (proj_info != NULL) {
+		    strcat(error_msg, _("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]);
+		    strcat(error_msg, "\nERROR: ");
+		    switch (err) {
+		    case -1:
+			strcat(error_msg, "proj\n");
+			break;
+		    case -2:
+			strcat(error_msg, "units\n");
+			break;
+		    case -3:
+			strcat(error_msg, "datum\n");
+			break;
+		    case -4:
+			strcat(error_msg, "ellps, a, es\n");
+			break;
+		    case -5:
+			strcat(error_msg, "zone\n");
+			break;
+		    case -6:
+			strcat(error_msg, "south\n");
+			break;
+		    case -7:
+			strcat(error_msg, "x_0\n");
+			break;
+		    case -8:
+			strcat(error_msg, "y_0\n");
+			break;
+		    case -9:
+			strcat(error_msg, "lon_0\n");
+			break;
+		    case -10:
+			strcat(error_msg, "lat_0\n");
+			break;
+		    case -11:
+			strcat(error_msg, "lat_1, lat2\n");
+			break;
+		    }
 		}
+		else {
+		    strcat(error_msg, _("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
+			sprintf(error_msg + strlen(error_msg),
+				"Dataset proj = %d (unknown), zone = %d\n",
+				cellhd->proj, cellhd->zone);
+		}
 	    }
 	    else {
-		strcat(error_msg, _("Import dataset PROJ_INFO is:\n"));
-		if (cellhd->proj == PROJECTION_XY)
-		    sprintf(error_msg + strlen(error_msg),
-			    "cellhd.proj = %d (unreferenced/unknown)\n",
-			    cellhd->proj);
-		else if (cellhd->proj == PROJECTION_LL)
-		    sprintf(error_msg + strlen(error_msg),
-			    "cellhd.proj = %d (lat/long)\n", cellhd->proj);
-		else if (cellhd->proj == PROJECTION_UTM)
-		    sprintf(error_msg + strlen(error_msg),
-			    "cellhd.proj = %d (UTM), zone = %d\n",
-			    cellhd->proj, cellhd->zone);
-		else if (cellhd->proj == PROJECTION_SP)
-		    sprintf(error_msg + strlen(error_msg),
-			    "cellhd.proj = %d (State Plane), zone = %d\n",
-			    cellhd->proj, cellhd->zone);
-		else
-		    sprintf(error_msg + strlen(error_msg),
-			    "cellhd.proj = %d (unknown), zone = %d\n",
-			    cellhd->proj, cellhd->zone);
+		/* error in proj_units */
+		if (loc_proj_units != NULL) {
+		    strcat(error_msg, "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, "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]);
+		}
 	    }
 	    strcat(error_msg,
 		   _("\nIn case of no significant differences in the projection definitions,"
@@ -109,12 +232,28 @@
 		     " current location definition.\n"));
 	    strcat(error_msg,
 		   _("Consider generating a new location from the input dataset using "
-		     "the 'location' parameter.\n"));
-	    G_fatal_error("%s", error_msg);
+		    "the 'location' parameter.\n"));
+
+	    if (check_only)
+		msg_fn = G_message;
+	    else
+		msg_fn = G_fatal_error;
+	    msg_fn(error_msg);
+	    if (check_only) {
+		exit(EXIT_FAILURE);
+	    }
 	}
 	else {
-	    G_message(_("Projection of input dataset and current location "
-			"appear to match"));
+	    if (check_only)
+		msg_fn = G_message;
+	    else
+		msg_fn = G_verbose_message;            
+	    msg_fn(_("Projection of input dataset and current location "
+		     "appear to match"));
+	    if (check_only) {
+		GDALClose(hDS);
+		exit(EXIT_SUCCESS);
+	    }
 	}
     }
 }

Modified: grass/trunk/raster/r.external/proto.h
===================================================================
--- grass/trunk/raster/r.external/proto.h	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/raster/r.external/proto.h	2017-10-15 16:43:51 UTC (rev 71558)
@@ -38,7 +38,7 @@
 void list_bands(struct Cell_head *, GDALDatasetH);
 
 /* proj.c */
-void check_projection(struct Cell_head *, GDALDatasetH, int);
+void check_projection(struct Cell_head *, GDALDatasetH, char *, int, int, int);
 
 /* window.c */
 void setup_window(struct Cell_head *, GDALDatasetH, int *);

Modified: grass/trunk/raster/r.in.gdal/main.c
===================================================================
--- grass/trunk/raster/r.in.gdal/main.c	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/raster/r.in.gdal/main.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -29,14 +29,16 @@
 #include <grass/gprojects.h>
 #include <grass/glocale.h>
 
-#include "gdal.h"
-#include "ogr_srs_api.h"
+#include <gdal.h>
 
 #undef MIN
 #undef MAX
 #define MIN(a,b)      ((a) < (b) ? (a) : (b))
 #define MAX(a,b)      ((a) > (b) ? (a) : (b))
 
+void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS,
+                      char *outloc, int create_only, int override,
+		      int check_only);
 static void ImportBand(GDALRasterBandH hBand, const char *output,
 		       struct Ref *group_ref, int *rowmap, int *colmap,
 		       int col_offset);
@@ -56,17 +58,14 @@
     char *input;
     char *output;
     char *title;
-    struct Cell_head cellhd, loc_wind, cur_wind;
+    struct Cell_head cellhd, cur_wind;
     struct Key_Value *proj_info = NULL, *proj_units = NULL;
-    struct Key_Value *loc_proj_info = NULL, *loc_proj_units = NULL;
     GDALDatasetH hDS;
     GDALDriverH hDriver;
     GDALRasterBandH hBand;
     double adfGeoTransform[6];
     int n_bands;
     int force_imagery = FALSE;
-    char error_msg[8096];
-    int projcomp_error = 0;
     int overwrite;
     int offset = 0;
     char *suffix;
@@ -115,7 +114,9 @@
     parm.memory->key = "memory";
     parm.memory->type = TYPE_INTEGER;
     parm.memory->required = NO;
+#if GDAL_VERSION_NUM < 1800
     parm.memory->options = "0-2047";
+#endif
     parm.memory->answer = "300";
     parm.memory->label = _("Maximum memory to be used (in MB)");
     parm.memory->description = _("Cache size for raster rows");
@@ -239,7 +240,13 @@
     flag_p->guisection = _("Print");
     flag_p->suppress_required = YES;
     G_option_requires(flag_p, parm.input, NULL);
-    
+
+    /* 1. list supported formats */
+    /* 2. print input bands */
+    /* 3. open input */
+    /* 4. check projection / create location */ 
+    /* 5. open output */
+
     /* 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 */
@@ -248,6 +255,46 @@
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
+    /* -------------------------------------------------------------------- */
+    /*      Fire up the engines.                                            */
+    /* -------------------------------------------------------------------- */
+    GDALAllRegister();
+
+    /* -------------------------------------------------------------------- */
+    /*      List supported formats and exit.                                */
+    /*         code from GDAL 1.2.5  gcore/gdal_misc.cpp                    */
+    /*         Copyright (c) 1999, Frank Warmerdam                          */
+    /* -------------------------------------------------------------------- */
+    if (flag_f->answer) {
+	int iDr;
+
+	G_message(_("Supported formats:"));
+	for (iDr = 0; iDr < GDALGetDriverCount(); iDr++) {
+	    const char *pszRWFlag;
+
+	    hDriver = GDALGetDriver(iDr);
+
+#ifdef GDAL_DCAP_RASTER
+            /* Starting with GDAL 2.0, vector drivers can also be returned */
+            /* Only keep raster drivers */
+            if (!GDALGetMetadataItem(hDriver, GDAL_DCAP_RASTER, NULL))
+                continue;
+#endif
+
+	    if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL))
+		pszRWFlag = "rw+";
+	    else if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, NULL))
+		pszRWFlag = "rw";
+	    else
+		pszRWFlag = "ro";
+
+	    fprintf(stdout, " %s (%s): %s\n",
+		    GDALGetDriverShortName(hDriver),
+		    pszRWFlag, GDALGetDriverLongName(hDriver));
+	}
+	exit(EXIT_SUCCESS);
+    }
+
     input = parm.input->answer;
 
     output = parm.output->answer;
@@ -274,13 +321,14 @@
     if (flag_l->answer && G_projection() != PROJECTION_LL)
 	G_fatal_error(_("The '-l' flag only works in Lat/Lon locations"));
 
-    if(num_digits < 0)
+    if (num_digits < 0)
         G_fatal_error(_("The number of digits for band numbering must be equal or greater than 0"));
 
     /* Allocate the suffix string */
-    if(num_digits > 0) {
+    if (num_digits > 0) {
         suffix = G_calloc( num_digits + 1, sizeof(char));
-    } else {
+    }
+    else {
         /* Band number length should not exceed 64 digits */
         suffix = G_calloc(65, sizeof(char));
     }
@@ -291,49 +339,15 @@
 	croptoregion = 0; 
     }
 
-    /* -------------------------------------------------------------------- */
-    /*      Fire up the engines.                                            */
-    /* -------------------------------------------------------------------- */
-    GDALAllRegister();
     /* default GDAL memory cache size appears to be only 40 MiB, slowing down r.in.gdal */
     if (parm.memory->answer && *parm.memory->answer) {
-	   /* TODO: GDALGetCacheMax() overflows at 2GiB, implement use of GDALSetCacheMax64() */
+#if GDAL_VERSION_NUM >= 1800
+           GDALSetCacheMax64((GIntBig)atol(parm.memory->answer) * 1024 * 1024);
+           G_verbose_message(_("Using memory cache size: %.1f MiB"), GDALGetCacheMax64()/1024.0/1024.0);
+#else
            GDALSetCacheMax(atol(parm.memory->answer) * 1024 * 1024);
            G_verbose_message(_("Using memory cache size: %.1f MiB"), GDALGetCacheMax()/1024.0/1024.0);
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      List supported formats and exit.                                */
-    /*         code from GDAL 1.2.5  gcore/gdal_misc.cpp                    */
-    /*         Copyright (c) 1999, Frank Warmerdam                          */
-    /* -------------------------------------------------------------------- */
-    if (flag_f->answer) {
-	int iDr;
-
-	G_message(_("Supported formats:"));
-	for (iDr = 0; iDr < GDALGetDriverCount(); iDr++) {
-	    GDALDriverH hDriver = GDALGetDriver(iDr);
-	    const char *pszRWFlag;
-
-#ifdef GDAL_DCAP_RASTER
-            /* Starting with GDAL 2.0, vector drivers can also be returned */
-            /* Only keep raster drivers */
-            if (!GDALGetMetadataItem(hDriver, GDAL_DCAP_RASTER, NULL))
-                continue;
 #endif
-
-	    if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL))
-		pszRWFlag = "rw+";
-	    else if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, NULL))
-		pszRWFlag = "rw";
-	    else
-		pszRWFlag = "ro";
-
-	    fprintf(stdout, " %s (%s): %s\n",
-		    GDALGetDriverShortName(hDriver),
-		    pszRWFlag, GDALGetDriverLongName(hDriver));
-	}
-	exit(EXIT_SUCCESS);
     }
 
     /* -------------------------------------------------------------------- */
@@ -444,170 +458,13 @@
 	    "with r.region before going any further."));
     }
 
-    /* -------------------------------------------------------------------- */
-    /*      Fetch the projection in GRASS form.                             */
-    /* -------------------------------------------------------------------- */
-    proj_info = NULL;
-    proj_units = NULL;
+    check_projection(&cellhd, hDS, parm.outloc->answer, flag_c->answer,
+                     flag_o->answer, flag_j->answer);
 
-    /* -------------------------------------------------------------------- */
-    /*      Do we need to create a new location?                            */
-    /* -------------------------------------------------------------------- */
-    if (parm.outloc->answer != NULL) {
-	/* Convert projection information non-interactively as we can't
-	 * assume the user has a terminal open */
-	if (GPJ_wkt_to_grass(&cellhd, &proj_info,
-			     &proj_units, GDALGetProjectionRef(hDS), 0) < 0) {
-	    G_fatal_error(_("Unable to convert input map projection to GRASS "
-			    "format; cannot create new location."));
-	}
-	else {
-	    if (0 != G_make_location(parm.outloc->answer, &cellhd,
-				     proj_info, proj_units)) {
-		G_fatal_error(_("Unable to create new location <%s>"),
-			      parm.outloc->answer);
-	    }
-	    G_message(_("Location <%s> created"), parm.outloc->answer);
-	}
-
-        /* If the c flag is set, clean up? and exit here */
-        if (flag_c->answer) {
-            exit(EXIT_SUCCESS);
-        }
-    }
-    else {
-	/* Projection only required for checking so convert non-interactively */
-	if (GPJ_wkt_to_grass(&cellhd, &proj_info,
-			     &proj_units, GDALGetProjectionRef(hDS), 0) < 0)
-	    G_warning(_("Unable to convert input raster map projection information to "
-		       "GRASS format for checking"));
-	else {
-            void (*msg_fn)(const char *, ...);
-
-	    /* -------------------------------------------------------------------- */
-	    /*      Does the projection of the current location match the           */
-	    /*      dataset?                                                        */
-	    /* -------------------------------------------------------------------- */
-	    G_get_default_window(&loc_wind);
-	    if (loc_wind.proj != PROJECTION_XY) {
-		loc_proj_info = G_get_projinfo();
-		loc_proj_units = G_get_projunits();
-	    }
-
-	    if (flag_o->answer) {
-		cellhd.proj = loc_wind.proj;
-		cellhd.zone = loc_wind.zone;
-		G_warning(_("Over-riding projection check"));
-	    }
-	    else if (loc_wind.proj != cellhd.proj
-		     || (projcomp_error = G_compare_projections(loc_proj_info,
-								loc_proj_units,
-								proj_info,
-								proj_units)) < 0) {
-		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_proj_info != NULL) {
-		    strcat(error_msg, _("Location PROJ_INFO is:\n"));
-		    for (i_value = 0;
-			 loc_proj_info != NULL &&
-			 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, _("Dataset PROJ_INFO is:\n"));
-		    for (i_value = 0;
-			 proj_info != NULL && 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]);
-		    strcat(error_msg, "\nERROR: ");
-		    switch (projcomp_error) {
-		    case -1:
-			strcat(error_msg, "proj\n");
-			break;
-		    case -2:
-			strcat(error_msg, "units\n");
-			break;
-		    case -3:
-			strcat(error_msg, "datum\n");
-			break;
-		    case -4:
-			strcat(error_msg, "ellps\n");
-			break;
-		    case -5:
-			strcat(error_msg, "zone\n");
-			break;
-		    case -6:
-			strcat(error_msg, "south\n");
-			break;
-		    case -7:
-			strcat(error_msg, "x_0\n");
-			break;
-		    case -8:
-			strcat(error_msg, "y_0\n");
-			break;
-		    }
-		}
-		else {
-		    strcat(error_msg, _("Import dataset PROJ_INFO is:\n"));
-		    if (cellhd.proj == PROJECTION_XY)
-			sprintf(error_msg + strlen(error_msg),
-				"cellhd.proj = %d (unreferenced/unknown)\n",
-				cellhd.proj);
-		    else if (cellhd.proj == PROJECTION_LL)
-			sprintf(error_msg + strlen(error_msg),
-				"cellhd.proj = %d (lat/long)\n", cellhd.proj);
-		    else if (cellhd.proj == PROJECTION_UTM)
-			sprintf(error_msg + strlen(error_msg),
-				"cellhd.proj = %d (UTM), zone = %d\n",
-				cellhd.proj, cellhd.zone);
-		    else
-			sprintf(error_msg + strlen(error_msg),
-				"cellhd.proj = %d (unknown), zone = %d\n",
-				cellhd.proj, cellhd.zone);
-		}
-		strcat(error_msg,
-		       _("\nIn case of no significant differences in the projection definitions,"
-			 " use the -o flag to ignore them and use"
-			 " current location definition.\n"));
-		strcat(error_msg,
-		       _("Consider generating a new location from the input dataset using "
-			"the 'location' parameter.\n"));
-
-                if (flag_j->answer)
-                    msg_fn = G_message;
-                else
-                    msg_fn = G_fatal_error;
-                msg_fn(error_msg);
-                if (flag_j->answer)
-                    exit(EXIT_FAILURE);
-	    }
-	    else {
-                if (flag_j->answer)
-                    msg_fn = G_message;
-                else
-                    msg_fn = G_verbose_message;            
-                msg_fn(_("Projection of input dataset and current location "
-                         "appear to match"));
-                if (flag_j->answer)
-                    exit(EXIT_SUCCESS);
-	    }
-	}
-    }
-
-    if (GDALGetRasterCount(hDS) > 1)
+    if (GDALGetRasterCount(hDS) > 1) {
 	G_message(_("Importing %d raster bands..."),
 		  GDALGetRasterCount(hDS));
+    }
 
     /* -------------------------------------------------------------------- */
     /*      Set the active window to match the available data.              */

Copied: grass/trunk/raster/r.in.gdal/proj.c (from rev 71498, grass/trunk/raster/r.external/proj.c)
===================================================================
--- grass/trunk/raster/r.in.gdal/proj.c	                        (rev 0)
+++ grass/trunk/raster/r.in.gdal/proj.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -0,0 +1,259 @@
+#include <grass/gis.h>
+#include <grass/gprojects.h>
+#include <grass/glocale.h>
+
+#include <gdal.h>
+#include <ogr_srs_api.h>
+
+/* keep in sync with r.external, v.in.ogr, v.external */
+void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS,
+                      char *outloc, int create_only, int override,
+		      int check_only)
+{
+    struct Cell_head loc_wind;
+    struct Key_Value *proj_info = NULL, *proj_units = NULL;
+    struct Key_Value *loc_proj_info = NULL, *loc_proj_units = NULL;
+    const char *wkt;
+    char error_msg[8096];
+    int proj_trouble;
+
+    /* -------------------------------------------------------------------- */
+    /*      Fetch the projection in GRASS form.                             */
+    /* -------------------------------------------------------------------- */
+    proj_info = NULL;
+    proj_units = NULL;
+    wkt = GDALGetProjectionRef(hDS);
+    /* proj_trouble:
+     * 0: valid srs
+     * 1: no srs, default to xy
+     * 2: unreadable srs, default to xy
+     */
+
+    /* Projection only required for checking so convert non-interactively */
+    proj_trouble = 0;
+    if (wkt && *wkt) {
+	OGRSpatialReferenceH hSRS;
+
+	hSRS = OSRNewSpatialReference(wkt);
+	GPJ_osr_to_grass(cellhd, &proj_info, &proj_units, hSRS, 0);
+
+	if (!OSRIsProjected(hSRS) && !OSRIsGeographic(hSRS)) {
+	    G_important_message(_("Input contains an invalid SRS. " 
+	                          "WKT definition:\n%s"), wkt);
+
+	    proj_trouble = 2;
+	}
+	if (hSRS)
+	    OSRDestroySpatialReference(hSRS);
+    }
+    else {
+	G_important_message(_("No projection information available"));
+	cellhd->proj = PROJECTION_XY;
+	cellhd->zone = 0;
+	proj_trouble = 1;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Do we need to create a new location?                            */
+    /* -------------------------------------------------------------------- */
+    if (outloc != NULL) {
+	/* do not create a xy location if an existing SRS was unreadable */ 
+	if (proj_trouble == 2) {
+	    G_fatal_error(_("Unable to convert input map projection to GRASS "
+			    "format; cannot create new location."));
+	}
+	else {
+            if (0 != G_make_location(outloc, cellhd,
+                                     proj_info, proj_units)) {
+                G_fatal_error(_("Unable to create new location <%s>"),
+                              outloc);
+            }
+	    G_message(_("Location <%s> created"), outloc);
+
+	    G_unset_window();	/* new location, projection, and window */
+	    G_get_window(cellhd);
+	}
+
+        /* If create only, clean up and exit here */
+        if (create_only) {
+	    GDALClose(hDS);
+            exit(EXIT_SUCCESS);
+        }
+    }
+    else {
+	int err = 0;
+        void (*msg_fn)(const char *, ...);
+
+	if (check_only && override) {
+	    /* can't check when over-riding check */
+	    override = 0;
+	}
+
+	if (proj_trouble == 2) {
+	    strcpy(error_msg, _("Unable to convert input map projection information "
+		                "to GRASS format."));
+            if (override) {
+                msg_fn = G_warning;
+	    }
+            else {
+                msg_fn = G_fatal_error;
+	    }
+            msg_fn(error_msg);
+            if (!override) {
+                exit(EXIT_FAILURE);
+	    }
+	}
+
+	/* -------------------------------------------------------------------- */
+	/*      Does the projection of the current location match the           */
+	/*      dataset?                                                        */
+	/* -------------------------------------------------------------------- */
+	G_get_default_window(&loc_wind);
+	/* fetch LOCATION PROJ info */
+	if (loc_wind.proj != PROJECTION_XY) {
+	    loc_proj_info = G_get_projinfo();
+	    loc_proj_units = G_get_projunits();
+	}
+
+	if (override) {
+	    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)) != 1) {
+	    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) {
+		/* error in proj_info */
+		if (loc_proj_info != NULL) {
+		    strcat(error_msg, _("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, _("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]);
+		    strcat(error_msg, "\nERROR: ");
+		    switch (err) {
+		    case -1:
+			strcat(error_msg, "proj\n");
+			break;
+		    case -2:
+			strcat(error_msg, "units\n");
+			break;
+		    case -3:
+			strcat(error_msg, "datum\n");
+			break;
+		    case -4:
+			strcat(error_msg, "ellps, a, es\n");
+			break;
+		    case -5:
+			strcat(error_msg, "zone\n");
+			break;
+		    case -6:
+			strcat(error_msg, "south\n");
+			break;
+		    case -7:
+			strcat(error_msg, "x_0\n");
+			break;
+		    case -8:
+			strcat(error_msg, "y_0\n");
+			break;
+		    case -9:
+			strcat(error_msg, "lon_0\n");
+			break;
+		    case -10:
+			strcat(error_msg, "lat_0\n");
+			break;
+		    case -11:
+			strcat(error_msg, "lat_1, lat2\n");
+			break;
+		    }
+		}
+		else {
+		    strcat(error_msg, _("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
+			sprintf(error_msg + strlen(error_msg),
+				"Dataset proj = %d (unknown), zone = %d\n",
+				cellhd->proj, cellhd->zone);
+		}
+	    }
+	    else {
+		/* error in proj_units */
+		if (loc_proj_units != NULL) {
+		    strcat(error_msg, "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, "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]);
+		}
+	    }
+	    strcat(error_msg,
+		   _("\nIn case of no significant differences in the projection definitions,"
+		     " use the -o flag to ignore them and use"
+		     " current location definition.\n"));
+	    strcat(error_msg,
+		   _("Consider generating a new location from the input dataset using "
+		    "the 'location' parameter.\n"));
+
+	    if (check_only)
+		msg_fn = G_message;
+	    else
+		msg_fn = G_fatal_error;
+	    msg_fn(error_msg);
+	    if (check_only) {
+		exit(EXIT_FAILURE);
+	    }
+	}
+	else {
+	    if (check_only)
+		msg_fn = G_message;
+	    else
+		msg_fn = G_verbose_message;            
+	    msg_fn(_("Projection of input dataset and current location "
+		     "appear to match"));
+	    if (check_only) {
+		GDALClose(hDS);
+		exit(EXIT_SUCCESS);
+	    }
+	}
+    }
+}

Modified: grass/trunk/vector/v.external/args.c
===================================================================
--- grass/trunk/vector/v.external/args.c	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/vector/v.external/args.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -46,6 +46,11 @@
     flags->override->description =
 	_("Assume that the dataset has the same projection as the current location");
 
+    flags->proj = G_define_flag();
+    flags->proj->key = 'j';
+    flags->proj->description =
+	_("Perform projection check only and exit");
+
     flags->format = G_define_flag();
     flags->format->key = 'f';
     flags->format->description = _("List supported formats and exit");

Modified: grass/trunk/vector/v.external/dsn.c
===================================================================
--- grass/trunk/vector/v.external/dsn.c	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/vector/v.external/dsn.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -7,7 +7,7 @@
 char *get_datasource_name(const char *opt_dsn, int use_ogr)
 {
     char *dsn;
-    
+
     if (G_strncasecmp(opt_dsn, "PG:", 3) == 0) {
         /* PostgreSQL/PostGIS */
         size_t i;

Modified: grass/trunk/vector/v.external/local_proto.h
===================================================================
--- grass/trunk/vector/v.external/local_proto.h	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/vector/v.external/local_proto.h	2017-10-15 16:43:51 UTC (rev 71558)
@@ -6,7 +6,7 @@
 };
 
 struct _flags {
-    struct Flag *format, *layer, *tlist, *topo, *list, *override;
+    struct Flag *format, *layer, *tlist, *topo, *list, *override, *proj;
 };
 
 /* args.c */
@@ -22,5 +22,6 @@
 void get_table_name(const char *, char **, char **);
 
 /* proj.c */
-void check_projection(const char *, int);
+void check_projection(struct Cell_head *, const char *, int, char *,
+                      char *, int, int, int);
 #endif

Modified: grass/trunk/vector/v.external/main.c
===================================================================
--- grass/trunk/vector/v.external/main.c	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/vector/v.external/main.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -43,6 +43,7 @@
     int ilayer, use_ogr;
     char buf[GPATH_MAX], *dsn, *layer;
     const char *output;
+    struct Cell_head cellhd;
     
     G_gisinit(argv[0]);
     
@@ -62,7 +63,7 @@
     use_ogr = TRUE;
     G_debug(1, "GRASS_VECTOR_OGR defined? %s",
             getenv("GRASS_VECTOR_OGR") ? "yes" : "no");
-    if(options.dsn->answer &&
+    if (options.dsn->answer &&
        G_strncasecmp(options.dsn->answer, "PG:", 3) == 0) {
         /* -> PostgreSQL */
 #if defined HAVE_OGR && defined HAVE_POSTGRES
@@ -137,21 +138,9 @@
     }
 
     /* check projection match */
-    if (!flags.override->answer) {
-        /* here must be used original dsn since check_projection() is
-         * using GDAL library */
-        char dsn_ogr[DB_SQL_MAX];
-
-        if (!use_ogr && G_strncasecmp(options.dsn->answer, "PG:", 3) == 0) {
-            /* make dsn OGR-compatible */
-            strcpy(dsn_ogr, "PG:");
-            strcat(dsn_ogr, dsn);
-        }
-        else {
-            sprintf(dsn_ogr, "%s", dsn);
-        }
-        check_projection(dsn_ogr, ilayer);
-    }
+    G_get_window(&cellhd);
+    check_projection(&cellhd, options.dsn->answer, ilayer, NULL, NULL, 0,
+                     flags.override->answer, flags.proj->answer);
     
     /* create new vector map */
     putenv("GRASS_VECTOR_EXTERNAL_IGNORE=1");

Modified: grass/trunk/vector/v.external/proj.c
===================================================================
--- grass/trunk/vector/v.external/proj.c	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/vector/v.external/proj.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -2,125 +2,380 @@
 #include <grass/gprojects.h>
 #include <grass/glocale.h>
 
-#ifdef HAVE_OGR
+#include <gdal.h>
+#include <gdal_version.h>
 #include "ogr_api.h"
+
+/* define type of input datasource
+ * as of GDAL 2.2, all functions having as argument a GDAL/OGR dataset 
+ * must use the GDAL version, not the OGR version */
+#if GDAL_VERSION_NUM >= 2020000
+typedef GDALDatasetH ds_t;
+#define ds_getlayerbyindex(ds, i)	GDALDatasetGetLayer((ds), (i))
+#define ds_close(ds)			GDALClose(ds)
+#else
+typedef OGRDataSourceH ds_t;
+#define ds_getlayerbyindex(ds, i)	OGR_DS_GetLayer((ds), (i))
+#define ds_close(ds)			OGR_DS_Destroy(ds)
 #endif
 
-void check_projection(const char *dsn, int ilayer)
+/* get projection info of OGR layer in GRASS format
+ * return 0 on success (some non-xy SRS)
+ * return 1 if no SRS available
+ * return 2 if SRS available but unreadable */
+int get_layer_proj(OGRLayerH Ogr_layer, struct Cell_head *cellhd,
+		   struct Key_Value **proj_info, struct Key_Value **proj_units,
+		   char *geom_col, int verbose)
 {
-#ifdef HAVE_OGR
-    int err = 0;
-    char error_msg[8192];
-    
-    struct Cell_head cellhd, loc_wind;
-    struct Key_Value *loc_proj_info, *loc_proj_units;
-    struct Key_Value *proj_info, *proj_units;
-    
-    OGRDataSourceH Ogr_ds;
-    OGRLayerH Ogr_layer;
     OGRSpatialReferenceH Ogr_projection;
-    
-    proj_info = proj_units = NULL;
-    loc_proj_info = G_get_projinfo();
-    loc_proj_units = G_get_projunits();
-    
-    G_get_default_window(&loc_wind);
-    G_get_window(&cellhd);
-    
-    Ogr_ds = OGROpen(dsn, FALSE, NULL);
-    if (!Ogr_ds) {
-	G_fatal_error(_("Unable to open data source '%s'"), dsn);
+    char *pszProj4 = NULL;
+
+    Ogr_projection = NULL;
+    *proj_info = NULL;
+    *proj_units = NULL;
+    G_get_window(cellhd);
+
+    /* Fetch input layer projection in GRASS form. */
+#if GDAL_VERSION_NUM >= 1110000
+    if (geom_col) {
+	int igeom;
+        OGRGeomFieldDefnH Ogr_geomdefn;
+	OGRFeatureDefnH Ogr_featuredefn;
+        
+        Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
+        igeom = OGR_FD_GetGeomFieldIndex(Ogr_featuredefn, geom_col);
+        if (igeom < 0)
+            G_fatal_error(_("Geometry column <%s> not found in input layer <%s>"),
+                          geom_col, OGR_L_GetName(Ogr_layer));
+        Ogr_geomdefn = OGR_FD_GetGeomFieldDefn(Ogr_featuredefn, igeom);
+        Ogr_projection = OGR_GFld_GetSpatialRef(Ogr_geomdefn);
     }
-    if (ilayer > OGR_DS_GetLayerCount(Ogr_ds))
-        return;
-    Ogr_layer = OGR_DS_GetLayer(Ogr_ds, ilayer);
-    Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);
-    
-    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"));
-    OGR_DS_Destroy(Ogr_ds);
-    
-    if ((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");
+    else {
+        Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);
+    }
+#else
+    Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);	/* should not be freed later */
+#endif
+
+    /* verbose is used only when comparing input SRS to GRASS projection,
+     * not when comparing SRS's of several input layers */
+    if (GPJ_osr_to_grass(cellhd, proj_info,
+			 proj_units, Ogr_projection, 0) < 0) {
+	/* TODO: GPJ_osr_to_grass() does not return anything < 0
+	 * check with GRASS 6 and GRASS 5 */
+	G_warning(_("Unable to convert input layer projection information to "
+		   "GRASS format for checking"));
+	if (verbose && Ogr_projection != NULL) {
+	    char *wkt = NULL;
+
+	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
+		G_warning(_("Can't get WKT parameter string"));
+	    }
+	    else if (wkt) {
+		G_important_message(_("WKT definition:\n%s"), wkt);
+	    }
+	}
+
+	return 2;
+    }
+    /* custom checks because if in doubt GPJ_osr_to_grass() returns a 
+     * xy CRS */
+    if (Ogr_projection == NULL) {
+	if (verbose) {
+	    G_important_message(_("No OGR projection available for layer <%s>"),
+				OGR_L_GetName(Ogr_layer));
+	}
+
+	return 1;
+    }
+
+    if (!OSRIsProjected(Ogr_projection) && !OSRIsGeographic(Ogr_projection)) {
+	G_important_message(_("OGR projection for layer <%s> does not contain a valid SRS"),
+			    OGR_L_GetName(Ogr_layer));
+
+	if (verbose) {
+	    char *wkt = NULL;
+
+	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
+		G_important_message(_("Can't get WKT parameter string"));
+	    }
+	    else if (wkt) {
+		G_important_message(_("WKT definition:\n%s"), wkt);
+	    }
+	}
+
+	return 2;
+    }
+
+    if (OSRExportToProj4(Ogr_projection, &pszProj4) != OGRERR_NONE) {
+	G_important_message(_("OGR projection for layer <%s> can not be converted to proj4"),
+			    OGR_L_GetName(Ogr_layer));
+
+	if (verbose) {
+	    char *wkt = NULL;
+
+	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
+		G_important_message(_("Can't get WKT-style parameter string"));
+	    }
+	    else if (wkt) {
+		G_important_message(_("WKT-style definition:\n%s"), wkt);
+	    }
+	}
+
+	return 2;
+    }
+
+    return 0;
+}
+
+/* keep in sync with r.in.gdal, r.external, v.in.ogr */
+void check_projection(struct Cell_head *cellhd, char *dsn, int layer, char *geom_col,
+                      char *outloc, int create_only, int override,
+		      int check_only)
+{
+    struct Cell_head loc_wind;
+    struct Key_Value *proj_info = NULL, *proj_units = NULL;
+    struct Key_Value *loc_proj_info = NULL, *loc_proj_units = NULL;
+    char error_msg[8096];
+    int proj_trouble;
+    ds_t hDS;
+    OGRLayerH Ogr_layer;
+
+    /* open OGR DSN (v.external does not open the datasource itself */
+    hDS = NULL;
+    if (strlen(dsn) > 0) {
+#if GDAL_VERSION_NUM >= 2020000
+	hDS = GDALOpenEx(dsn, GDAL_OF_VECTOR, NULL, NULL, NULL);
+#else
+	hDS = OGROpen(dsn, FALSE, NULL);
+#endif
+    }
+    if (hDS == NULL)
+	G_fatal_error(_("Unable to open data source <%s>"), dsn);
+
+    /* Get first layer to be imported to use for projection check */
+    Ogr_layer = ds_getlayerbyindex(hDS, layer);
+
+    /* -------------------------------------------------------------------- */
+    /*      Fetch the projection in GRASS form.                             */
+    /* -------------------------------------------------------------------- */
+    proj_info = NULL;
+    proj_units = NULL;
+
+    /* proj_trouble:
+     * 0: valid srs
+     * 1: no srs, default to xy
+     * 2: unreadable srs, default to xy
+     */
+
+    /* Projection only required for checking so convert non-interactively */
+    proj_trouble = get_layer_proj(Ogr_layer, cellhd, &proj_info, &proj_units,
+		   geom_col, 1);
+
+    /* -------------------------------------------------------------------- */
+    /*      Do we need to create a new location?                            */
+    /* -------------------------------------------------------------------- */
+    if (outloc != NULL) {
+	/* do not create a xy location because this can mean that the
+	 * real SRS has not been recognized or is missing */ 
+	if (proj_trouble) {
+	    G_fatal_error(_("Unable to convert input map projection to GRASS "
+			    "format; cannot create new location."));
+	}
+	else {
+            if (0 != G_make_location(outloc, cellhd,
+                                     proj_info, proj_units)) {
+                G_fatal_error(_("Unable to create new location <%s>"),
+                              outloc);
             }
-            
-            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
-                    sprintf(error_msg + strlen(error_msg),
-                            "Dataset proj = %d (unknown), zone = %d\n",
-                            cellhd.proj, cellhd.zone);
-            }
+	    G_message(_("Location <%s> created"), outloc);
+
+	    G_unset_window();	/* new location, projection, and window */
+	    G_get_window(cellhd);
+	}
+
+        /* If create only, clean up and exit here */
+        if (create_only) {
+	    ds_close(hDS);
+            exit(EXIT_SUCCESS);
         }
-        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),
-                _("\nIn case of no significant differences in the projection definitions,"
-                  " use the -o flag to ignore them and use"
-                  " current location definition.\n"));
-        strcat(error_msg,
-               _("Consider generating a new location with 'location' parameter"
-                 " from input data set.\n"));
-        G_fatal_error("%s", error_msg);
     }
     else {
-        G_verbose_message(_("Projection of input dataset and current location "
-                            "appear to match"));
+	int err = 0;
+        void (*msg_fn)(const char *, ...);
+
+	if (check_only && override) {
+	    /* can't check when over-riding check */
+	    override = 0;
+	}
+
+	if (proj_trouble == 2) {
+	    strcpy(error_msg, _("Unable to convert input map projection information "
+		                "to GRASS format."));
+            if (override) {
+                msg_fn = G_warning;
+	    }
+            else {
+                msg_fn = G_fatal_error;
+		ds_close(hDS);
+	    }
+            msg_fn(error_msg);
+            if (!override) {
+                exit(EXIT_FAILURE);
+	    }
+	}
+
+	/* -------------------------------------------------------------------- */
+	/*      Does the projection of the current location match the           */
+	/*      dataset?                                                        */
+	/* -------------------------------------------------------------------- */
+	G_get_default_window(&loc_wind);
+	/* fetch LOCATION PROJ info */
+	if (loc_wind.proj != PROJECTION_XY) {
+	    loc_proj_info = G_get_projinfo();
+	    loc_proj_units = G_get_projunits();
+	}
+
+	if (override) {
+	    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)) != 1) {
+	    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) {
+		/* error in proj_info */
+		if (loc_proj_info != NULL) {
+		    strcat(error_msg, _("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, _("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]);
+		    strcat(error_msg, "\nERROR: ");
+		    switch (err) {
+		    case -1:
+			strcat(error_msg, "proj\n");
+			break;
+		    case -2:
+			strcat(error_msg, "units\n");
+			break;
+		    case -3:
+			strcat(error_msg, "datum\n");
+			break;
+		    case -4:
+			strcat(error_msg, "ellps, a, es\n");
+			break;
+		    case -5:
+			strcat(error_msg, "zone\n");
+			break;
+		    case -6:
+			strcat(error_msg, "south\n");
+			break;
+		    case -7:
+			strcat(error_msg, "x_0\n");
+			break;
+		    case -8:
+			strcat(error_msg, "y_0\n");
+			break;
+		    case -9:
+			strcat(error_msg, "lon_0\n");
+			break;
+		    case -10:
+			strcat(error_msg, "lat_0\n");
+			break;
+		    case -11:
+			strcat(error_msg, "lat_1, lat2\n");
+			break;
+		    }
+		}
+		else {
+		    strcat(error_msg, _("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
+			sprintf(error_msg + strlen(error_msg),
+				"Dataset proj = %d (unknown), zone = %d\n",
+				cellhd->proj, cellhd->zone);
+		}
+	    }
+	    else {
+		/* error in proj_units */
+		if (loc_proj_units != NULL) {
+		    strcat(error_msg, "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, "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]);
+		}
+	    }
+	    strcat(error_msg,
+		   _("\nIn case of no significant differences in the projection definitions,"
+		     " use the -o flag to ignore them and use"
+		     " current location definition.\n"));
+	    strcat(error_msg,
+		   _("Consider generating a new location from the input dataset using "
+		    "the 'location' parameter.\n"));
+
+	    if (check_only)
+		msg_fn = G_message;
+	    else
+		msg_fn = G_fatal_error;
+	    msg_fn(error_msg);
+	    if (check_only) {
+		exit(EXIT_FAILURE);
+	    }
+	}
+	else {
+	    if (check_only)
+		msg_fn = G_message;
+	    else
+		msg_fn = G_verbose_message;            
+	    msg_fn(_("Projection of input dataset and current location "
+		     "appear to match"));
+	    if (check_only) {
+		ds_close(hDS);
+		exit(EXIT_SUCCESS);
+	    }
+	}
     }
-#endif
+    ds_close(hDS);
 }

Modified: grass/trunk/vector/v.in.ogr/global.h
===================================================================
--- grass/trunk/vector/v.in.ogr/global.h	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/vector/v.in.ogr/global.h	2017-10-15 16:43:51 UTC (rev 71558)
@@ -23,7 +23,23 @@
 #ifndef __GLOBAL_H__
 #define __GLOBAL_H__
 
+#include <gdal.h>
+#include <gdal_version.h>
+#include <ogr_api.h>
 
+/* define type of input datasource
+ * as of GDAL 2.2, all functions having as argument a GDAL/OGR dataset 
+ * must use the GDAL version, not the OGR version */
+#if GDAL_VERSION_NUM >= 2020000
+typedef GDALDatasetH ds_t;
+#define ds_getlayerbyindex(ds, i)	GDALDatasetGetLayer((ds), (i))
+#define ds_close(ds)			GDALClose(ds)
+#else
+typedef OGRDataSourceH ds_t;
+#define ds_getlayerbyindex(ds, i)	OGR_DS_GetLayer((ds), (i))
+#define ds_close(ds)			OGR_DS_Destroy(ds)
+#endif
+
 extern int n_polygons;
 extern int n_polygon_boundaries;
 extern double split_distance;

Modified: grass/trunk/vector/v.in.ogr/main.c
===================================================================
--- grass/trunk/vector/v.in.ogr/main.c	2017-10-15 14:21:28 UTC (rev 71557)
+++ grass/trunk/vector/v.in.ogr/main.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -29,9 +29,7 @@
 #include <grass/gprojects.h>
 #include <grass/glocale.h>
 #include <gdal_version.h>	/* needed for OFTDate */
-#include "gdal.h"
-#include "ogr_api.h"
-#include "cpl_conv.h"
+#include <cpl_conv.h>
 #include "global.h"
 
 #ifndef MAX
@@ -39,19 +37,6 @@
 #  define MAX(a,b)      ((a>b) ? a : b)
 #endif
 
-/* define type of input datasource
- * as of GDAL 2.2, all functions having as argument a GDAL/OGR dataset 
- * must use the GDAL version, not the OGR version */
-#if GDAL_VERSION_NUM >= 2020000
-typedef GDALDatasetH ds_t;
-#define ds_getlayerbyindex(ds, i)	GDALDatasetGetLayer((ds), (i))
-#define ds_close(ds)			GDALClose(ds)
-#else
-typedef OGRDataSourceH ds_t;
-#define ds_getlayerbyindex(ds, i)	OGR_DS_GetLayer((ds), (i))
-#define ds_close(ds)			OGR_DS_Destroy(ds)
-#endif
-
 int n_polygons;
 int n_polygon_boundaries;
 double split_distance;
@@ -65,9 +50,10 @@
 char *get_datasource_name(const char *, int);
 
 int cmp_layer_srs(ds_t, int, int *, char **, char *);
-int get_layer_proj(OGRLayerH, struct Cell_head *,
-		   struct Key_Value **, struct Key_Value **,
-		   char *, int);
+void check_projection(struct Cell_head *cellhd, ds_t hDS, int layer, char *geom_col,
+                      char *outloc, int create_only, int override,
+		      int check_only);
+
 int create_spatial_filter(ds_t Ogr_ds, OGRGeometryH *,
                           int , int *, char **,
                           double *, double *,
@@ -118,12 +104,9 @@
     double min_area, snap;
     char buf[DB_SQL_MAX], namebuf[1024];
     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];
 
+    struct Cell_head cellhd, cur_wind;
+
     /* Vector */
     struct Map_info Map, Tmp, *Out;
     int cat;
@@ -150,7 +133,6 @@
     OGRGeometryH Ogr_geometry, *poSpatialFilter;
     const char *attr_filter;
     struct OGR_iterator OGR_iter;
-    int proj_trouble;
 
     int OFTIntegerListlength;
 
@@ -174,7 +156,6 @@
 
     xmin = ymin = 1.0;
     xmax = ymax = 0.0;
-    loc_proj_info = loc_proj_units = NULL;
     Ogr_ds = NULL;
     poSpatialFilter = NULL;
     OFTIntegerListlength = 255;	/* hack due to limitation in OGR */
@@ -617,17 +598,8 @@
 	                "Input layers must be imported separately."));
     }
 
-    /* Get first imported layer to use for projection check */
-    Ogr_layer = ds_getlayerbyindex(Ogr_ds, layers[0]);
-
-    /* Fetch input projection in GRASS form. */
-    proj_info = NULL;
-    proj_units = NULL;
     G_get_window(&cellhd);
 
-    proj_trouble = get_layer_proj(Ogr_layer, &cellhd, &proj_info, &proj_units,
-		   param.geom->answer, 1);
-
     cellhd.north = 1.;
     cellhd.south = 0.;
     cellhd.west = 0.;
@@ -645,169 +617,11 @@
     cellhd.ew_res3 = 1.;
     cellhd.tb_res = 1.;
 
-    /* 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 */
+    check_projection(&cellhd, Ogr_ds, layers[0], param.geom->answer,
+		     param.outloc->answer,
+                     flag.no_import->answer, flag.over->answer,
+		     flag.proj->answer);
 
-	/* do not create a xy location because this can mean that the
-	 * real SRS has not been recognized */ 
-	if (proj_trouble) {
-	    G_fatal_error(_("Unable to convert input map projection to GRASS "
-			    "format; cannot create new location."));
-	}
-	else {
-            if (0 != G_make_location(param.outloc->answer, &cellhd,
-                                     proj_info, proj_units)) {
-                G_fatal_error(_("Unable to create new location <%s>"),
-                              param.outloc->answer);
-            }
-	    G_message(_("Location <%s> created"), param.outloc->answer);
-
-	    G_unset_window();	/* new location, projection, and window */
-	    G_get_window(&cellhd);
-	}
-
-        /* If the i flag is set, clean up and exit here */
-        if (flag.no_import->answer) {
-	    ds_close(Ogr_ds);
-            exit(EXIT_SUCCESS);
-        }
-    }
-    else {
-	int err = 0;
-        void (*msg_fn)(const char *, ...);
-            
-	/* Projection only required for checking so convert non-interactively */
-	if (proj_trouble) {
-	    strcpy(error_msg, _("Unable to convert input map projection information "
-		                "to GRASS format."));
-            if (flag.over->answer) {
-                msg_fn = G_warning;
-	    }
-            else {
-                msg_fn = G_fatal_error;
-		ds_close(Ogr_ds);
-	    }
-            msg_fn(error_msg);
-            if (!flag.over->answer) {
-                exit(EXIT_FAILURE);
-	    }
-	}
-
-	/* 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_default_window(&loc_wind);
-	/* 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
-			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),
-		    _("\nIn case of no significant differences in the projection definitions,"
-		      " use the -o flag to ignore them and use"
-		      " current location definition.\n"));
-	    strcat(error_msg,
-		   _("Consider generating a new location with 'location' parameter"
-		    " from input data set.\n"));
-            if (flag.proj->answer)
-                msg_fn = G_message;
-            else {
-                msg_fn = G_fatal_error;
-		ds_close(Ogr_ds);
-	    }
-            msg_fn(error_msg);
-            if (flag.proj->answer)
-                exit(EXIT_FAILURE);
-	}
-	else {
-	    if (flag.proj->answer)
-		msg_fn = G_message;
-	    else
-		msg_fn = G_verbose_message;            
-	    msg_fn(_("Projection of input dataset and current location "
-		     "appear to match"));
-	    if (flag.proj->answer) {
-		ds_close(Ogr_ds);
-		exit(EXIT_SUCCESS);
-	    }
-	}
-    }
-
     /* get output name */
     if (param.out->answer) {
 	output = G_store(param.out->answer);
@@ -2062,212 +1876,6 @@
     return NULL;
 }
 
-/* get projection info of OGR layer in GRASS format
- * return 0 on success (some non-xy SRS)
- * return 1 if no SRS available
- * return 2 if SRS available but unreadable */
-int get_layer_proj(OGRLayerH Ogr_layer, struct Cell_head *cellhd,
-		   struct Key_Value **proj_info, struct Key_Value **proj_units,
-		   char *geom_col, int verbose)
-{
-    OGRSpatialReferenceH Ogr_projection;
-
-    Ogr_projection = NULL;
-    *proj_info = NULL;
-    *proj_units = NULL;
-    G_get_window(cellhd);
-
-    /* Fetch input layer projection in GRASS form. */
-#if GDAL_VERSION_NUM >= 1110000
-    if (geom_col) {
-	int igeom;
-        OGRGeomFieldDefnH Ogr_geomdefn;
-	OGRFeatureDefnH Ogr_featuredefn;
-        
-        Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
-        igeom = OGR_FD_GetGeomFieldIndex(Ogr_featuredefn, geom_col);
-        if (igeom < 0)
-            G_fatal_error(_("Geometry column <%s> not found in input layer <%s>"),
-                          geom_col, OGR_L_GetName(Ogr_layer));
-        Ogr_geomdefn = OGR_FD_GetGeomFieldDefn(Ogr_featuredefn, igeom);
-        Ogr_projection = OGR_GFld_GetSpatialRef(Ogr_geomdefn);
-    }
-    else {
-        Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);
-    }
-#else
-    Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);	/* should not be freed later */
-#endif
-
-    /* verbose is used only when comparing input SRS to GRASS projection,
-     * not when comparing SRS's of several input layers */
-    if (GPJ_osr_to_grass(cellhd, proj_info,
-			 proj_units, Ogr_projection, 0) < 0) {
-	/* TODO: GPJ_osr_to_grass() does not return anything < 0
-	 * check with GRASS 6 and GRASS 5 */
-	G_warning(_("Unable to convert input layer projection information to "
-		   "GRASS format for checking"));
-	if (verbose && Ogr_projection != NULL) {
-	    char *wkt = NULL;
-
-	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
-		G_warning(_("Can't get WKT-style parameter string"));
-	    }
-	    else if (wkt) {
-		G_important_message(_("WKT-style definition:\n%s"), wkt);
-	    }
-	}
-
-	return 2;
-    }
-    /* custom checks because if in doubt GPJ_osr_to_grass() returns a 
-     * xy CRS */
-    if (Ogr_projection == NULL) {
-	if (verbose) {
-	    G_important_message(_("No OGR projection available for layer <%s>"),
-				OGR_L_GetName(Ogr_layer));
-	}
-
-	return 1;
-    }
-
-    if (!OSRIsProjected(Ogr_projection) && !OSRIsGeographic(Ogr_projection)) {
-	G_important_message(_("OGR projection for layer <%s> does not contain a valid SRS"),
-			    OGR_L_GetName(Ogr_layer));
-
-	if (verbose) {
-	    char *wkt = NULL;
-
-	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
-		G_important_message(_("Can't get WKT-style parameter string"));
-	    }
-	    else if (wkt) {
-		G_important_message(_("WKT-style definition:\n%s"), wkt);
-	    }
-	}
-
-	return 2;
-    }
-
-    char *pszProj4 = NULL;
-
-    if (OSRExportToProj4(Ogr_projection, &pszProj4) != OGRERR_NONE) {
-	G_important_message(_("OGR projection for layer <%s> can not be converted to proj4"),
-			    OGR_L_GetName(Ogr_layer));
-
-	if (verbose) {
-	    char *wkt = NULL;
-
-	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
-		G_important_message(_("Can't get WKT-style parameter string"));
-	    }
-	    else if (wkt) {
-		G_important_message(_("WKT-style definition:\n%s"), wkt);
-	    }
-	}
-
-	return 2;
-    }
-
-    return 0;
-}
-
-/* compare projections of all OGR layers
- * return 0 if all layers have the same projection
- * return 1 if layer projections differ */
-int cmp_layer_srs(ds_t Ogr_ds, int nlayers, int *layers,
-		  char **layer_names, char *geom_col)
-{
-    int layer;
-    struct Key_Value *proj_info1, *proj_units1;
-    struct Key_Value *proj_info2, *proj_units2;
-    struct Cell_head cellhd1, cellhd2;
-    OGRLayerH Ogr_layer;
-
-    if (nlayers == 1)
-	return 0;
-
-    proj_info1 = proj_units1 = NULL;
-    proj_info2 = proj_units2 = NULL;
-
-    layer = 0;
-    do {
-	/* Get first SRS */
-	Ogr_layer = ds_getlayerbyindex(Ogr_ds, layers[layer]);
-
-	if (get_layer_proj(Ogr_layer, &cellhd1, &proj_info1, &proj_units1,
-			   geom_col, 0) == 0) {
-	    break;
-	}
-	layer++;
-    } while (layer < nlayers);
-
-    if (layer == nlayers) {
-	/* could not get layer proj in GRASS format for any of the layers
-	 * -> projections of all layers are the same, i.e. unreadable by GRASS */
-	G_warning(_("Layer projections are unreadable"));
-	if (proj_info1)
-	    G_free_key_value(proj_info1);
-	if (proj_units1)
-	    G_free_key_value(proj_units1);
-
-	return 0;
-    }
-    if (layer > 0) {
-	/* could not get layer proj in GRASS format for at least one of the layers
-	 * -> mix of unreadable and readable projections  */
-	G_warning(_("Projection for layer <%s> is unreadable"),
-	          layer_names[layer]);
-	if (proj_info1)
-	    G_free_key_value(proj_info1);
-	if (proj_units1)
-	    G_free_key_value(proj_units1);
-
-	return 1;
-    }
-
-    for (layer = 1; layer < nlayers; layer++) {
-	/* Get SRS of other layer(s) */
-	Ogr_layer = ds_getlayerbyindex(Ogr_ds, layers[layer]);
-	if (get_layer_proj(Ogr_layer, &cellhd2, &proj_info2, &proj_units2,
-			   geom_col, 0) != 0) {
-	    G_free_key_value(proj_info1);
-	    G_free_key_value(proj_units1);
-
-	    return 1;
-	}
-
-	if (cellhd1.proj != cellhd2.proj
-	    || G_compare_projections(proj_info1, proj_units1,
-				     proj_info2, proj_units2) != TRUE) {
-	    if (proj_info1)
-		G_free_key_value(proj_info1);
-	    if (proj_units1)
-		G_free_key_value(proj_units1);
-	    if (proj_info2)
-		G_free_key_value(proj_info2);
-	    if (proj_units2)
-		G_free_key_value(proj_units2);
-	    
-	    G_warning(_("Projection of layer <%s> is different from "
-			"projection of layer <%s>"),
-			layer_names[layer], layer_names[layer - 1]);
-
-	    return 1;
-	 }
-	if (proj_info2)
-	    G_free_key_value(proj_info2);
-	if (proj_units2)
-	    G_free_key_value(proj_units2);
-    }
-    if (proj_info1)
-	G_free_key_value(proj_info1);
-    if (proj_units1)
-	G_free_key_value(proj_units1);
-
-    return 0;
-}
-
 int create_spatial_filter(ds_t Ogr_ds, OGRGeometryH *poSpatialFilter,
                           int nlayers, int *layers, char **layer_names,
                           double *xmin, double *ymin,

Copied: grass/trunk/vector/v.in.ogr/proj.c (from rev 71498, grass/trunk/raster/r.external/proj.c)
===================================================================
--- grass/trunk/vector/v.in.ogr/proj.c	                        (rev 0)
+++ grass/trunk/vector/v.in.ogr/proj.c	2017-10-15 16:43:51 UTC (rev 71558)
@@ -0,0 +1,450 @@
+#include <grass/gis.h>
+#include <grass/gprojects.h>
+#include <grass/glocale.h>
+
+#include <ogr_srs_api.h>
+#include "global.h"
+
+/* get projection info of OGR layer in GRASS format
+ * return 0 on success (some non-xy SRS)
+ * return 1 if no SRS available
+ * return 2 if SRS available but unreadable */
+int get_layer_proj(OGRLayerH Ogr_layer, struct Cell_head *cellhd,
+		   struct Key_Value **proj_info, struct Key_Value **proj_units,
+		   char *geom_col, int verbose)
+{
+    OGRSpatialReferenceH Ogr_projection;
+    char *pszProj4 = NULL;
+
+    Ogr_projection = NULL;
+    *proj_info = NULL;
+    *proj_units = NULL;
+    G_get_window(cellhd);
+
+    /* Fetch input layer projection in GRASS form. */
+#if GDAL_VERSION_NUM >= 1110000
+    if (geom_col) {
+	int igeom;
+        OGRGeomFieldDefnH Ogr_geomdefn;
+	OGRFeatureDefnH Ogr_featuredefn;
+        
+        Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
+        igeom = OGR_FD_GetGeomFieldIndex(Ogr_featuredefn, geom_col);
+        if (igeom < 0)
+            G_fatal_error(_("Geometry column <%s> not found in input layer <%s>"),
+                          geom_col, OGR_L_GetName(Ogr_layer));
+        Ogr_geomdefn = OGR_FD_GetGeomFieldDefn(Ogr_featuredefn, igeom);
+        Ogr_projection = OGR_GFld_GetSpatialRef(Ogr_geomdefn);
+    }
+    else {
+        Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);
+    }
+#else
+    Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);	/* should not be freed later */
+#endif
+
+    /* verbose is used only when comparing input SRS to GRASS projection,
+     * not when comparing SRS's of several input layers */
+    if (GPJ_osr_to_grass(cellhd, proj_info,
+			 proj_units, Ogr_projection, 0) < 0) {
+	/* TODO: GPJ_osr_to_grass() does not return anything < 0
+	 * check with GRASS 6 and GRASS 5 */
+	G_warning(_("Unable to convert input layer projection information to "
+		   "GRASS format for checking"));
+	if (verbose && Ogr_projection != NULL) {
+	    char *wkt = NULL;
+
+	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
+		G_warning(_("Can't get WKT parameter string"));
+	    }
+	    else if (wkt) {
+		G_important_message(_("WKT definition:\n%s"), wkt);
+	    }
+	}
+
+	return 2;
+    }
+    /* custom checks because if in doubt GPJ_osr_to_grass() returns a 
+     * xy CRS */
+    if (Ogr_projection == NULL) {
+	if (verbose) {
+	    G_important_message(_("No OGR projection available for layer <%s>"),
+				OGR_L_GetName(Ogr_layer));
+	}
+
+	return 1;
+    }
+
+    if (!OSRIsProjected(Ogr_projection) && !OSRIsGeographic(Ogr_projection)) {
+	G_important_message(_("OGR projection for layer <%s> does not contain a valid SRS"),
+			    OGR_L_GetName(Ogr_layer));
+
+	if (verbose) {
+	    char *wkt = NULL;
+
+	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
+		G_important_message(_("Can't get WKT parameter string"));
+	    }
+	    else if (wkt) {
+		G_important_message(_("WKT definition:\n%s"), wkt);
+	    }
+	}
+
+	return 2;
+    }
+
+    if (OSRExportToProj4(Ogr_projection, &pszProj4) != OGRERR_NONE) {
+	G_important_message(_("OGR projection for layer <%s> can not be converted to proj4"),
+			    OGR_L_GetName(Ogr_layer));
+
+	if (verbose) {
+	    char *wkt = NULL;
+
+	    if (OSRExportToPrettyWkt(Ogr_projection, &wkt, FALSE) != OGRERR_NONE) {
+		G_important_message(_("Can't get WKT-style parameter string"));
+	    }
+	    else if (wkt) {
+		G_important_message(_("WKT-style definition:\n%s"), wkt);
+	    }
+	}
+
+	return 2;
+    }
+
+    return 0;
+}
+
+
+/* compare projections of all OGR layers
+ * return 0 if all layers have the same projection
+ * return 1 if layer projections differ */
+int cmp_layer_srs(ds_t Ogr_ds, int nlayers, int *layers,
+		  char **layer_names, char *geom_col)
+{
+    int layer;
+    struct Key_Value *proj_info1, *proj_units1;
+    struct Key_Value *proj_info2, *proj_units2;
+    struct Cell_head cellhd1, cellhd2;
+    OGRLayerH Ogr_layer;
+
+    if (nlayers == 1)
+	return 0;
+
+    proj_info1 = proj_units1 = NULL;
+    proj_info2 = proj_units2 = NULL;
+
+    layer = 0;
+    do {
+	/* Get first SRS */
+	Ogr_layer = ds_getlayerbyindex(Ogr_ds, layers[layer]);
+
+	if (get_layer_proj(Ogr_layer, &cellhd1, &proj_info1, &proj_units1,
+			   geom_col, 0) == 0) {
+	    break;
+	}
+	layer++;
+    } while (layer < nlayers);
+
+    if (layer == nlayers) {
+	/* could not get layer proj in GRASS format for any of the layers
+	 * -> projections of all layers are the same, i.e. unreadable by GRASS */
+	G_warning(_("Layer projections are unreadable"));
+	if (proj_info1)
+	    G_free_key_value(proj_info1);
+	if (proj_units1)
+	    G_free_key_value(proj_units1);
+
+	return 0;
+    }
+    if (layer > 0) {
+	/* could not get layer proj in GRASS format for at least one of the layers
+	 * -> mix of unreadable and readable projections  */
+	G_warning(_("Projection for layer <%s> is unreadable"),
+	          layer_names[layer]);
+	if (proj_info1)
+	    G_free_key_value(proj_info1);
+	if (proj_units1)
+	    G_free_key_value(proj_units1);
+
+	return 1;
+    }
+
+    for (layer = 1; layer < nlayers; layer++) {
+	/* Get SRS of other layer(s) */
+	Ogr_layer = ds_getlayerbyindex(Ogr_ds, layers[layer]);
+	if (get_layer_proj(Ogr_layer, &cellhd2, &proj_info2, &proj_units2,
+			   geom_col, 0) != 0) {
+	    G_free_key_value(proj_info1);
+	    G_free_key_value(proj_units1);
+
+	    return 1;
+	}
+
+	if (cellhd1.proj != cellhd2.proj
+	    || G_compare_projections(proj_info1, proj_units1,
+				     proj_info2, proj_units2) < 0) {
+	    if (proj_info1)
+		G_free_key_value(proj_info1);
+	    if (proj_units1)
+		G_free_key_value(proj_units1);
+	    if (proj_info2)
+		G_free_key_value(proj_info2);
+	    if (proj_units2)
+		G_free_key_value(proj_units2);
+	    
+	    G_warning(_("Projection of layer <%s> is different from "
+			"projection of layer <%s>"),
+			layer_names[layer], layer_names[layer - 1]);
+
+	    return 1;
+	 }
+	if (proj_info2)
+	    G_free_key_value(proj_info2);
+	if (proj_units2)
+	    G_free_key_value(proj_units2);
+    }
+    if (proj_info1)
+	G_free_key_value(proj_info1);
+    if (proj_units1)
+	G_free_key_value(proj_units1);
+
+    return 0;
+}
+
+/* keep in sync with r.in.gdal, r.external, v.external */
+void check_projection(struct Cell_head *cellhd, ds_t hDS, int layer, char *geom_col,
+                      char *outloc, int create_only, int override,
+		      int check_only)
+{
+    struct Cell_head loc_wind;
+    struct Key_Value *proj_info = NULL, *proj_units = NULL;
+    struct Key_Value *loc_proj_info = NULL, *loc_proj_units = NULL;
+    char error_msg[8096];
+    int proj_trouble;
+    OGRLayerH Ogr_layer;
+
+    /* Get first layer to be imported to use for projection check */
+    Ogr_layer = ds_getlayerbyindex(hDS, layer);
+
+    /* -------------------------------------------------------------------- */
+    /*      Fetch the projection in GRASS form.                             */
+    /* -------------------------------------------------------------------- */
+    proj_info = NULL;
+    proj_units = NULL;
+
+    /* proj_trouble:
+     * 0: valid srs
+     * 1: no srs, default to xy
+     * 2: unreadable srs, default to xy
+     */
+
+    /* Projection only required for checking so convert non-interactively */
+    proj_trouble = get_layer_proj(Ogr_layer, cellhd, &proj_info, &proj_units,
+		   geom_col, 1);
+
+    /* -------------------------------------------------------------------- */
+    /*      Do we need to create a new location?                            */
+    /* -------------------------------------------------------------------- */
+    if (outloc != NULL) {
+	/* do not create a xy location because this can mean that the
+	 * real SRS has not been recognized or is missing */ 
+	if (proj_trouble) {
+	    G_fatal_error(_("Unable to convert input map projection to GRASS "
+			    "format; cannot create new location."));
+	}
+	else {
+            if (0 != G_make_location(outloc, cellhd,
+                                     proj_info, proj_units)) {
+                G_fatal_error(_("Unable to create new location <%s>"),
+                              outloc);
+            }
+	    G_message(_("Location <%s> created"), outloc);
+
+	    G_unset_window();	/* new location, projection, and window */
+	    G_get_window(cellhd);
+	}
+
+        /* If create only, clean up and exit here */
+        if (create_only) {
+	    ds_close(hDS);
+            exit(EXIT_SUCCESS);
+        }
+    }
+    else {
+	int err = 0;
+        void (*msg_fn)(const char *, ...);
+
+	if (check_only && override) {
+	    /* can't check when over-riding check */
+	    override = 0;
+	}
+
+	if (proj_trouble == 2) {
+	    strcpy(error_msg, _("Unable to convert input map projection information "
+		                "to GRASS format."));
+            if (override) {
+                msg_fn = G_warning;
+	    }
+            else {
+                msg_fn = G_fatal_error;
+		ds_close(hDS);
+	    }
+            msg_fn(error_msg);
+            if (!override) {
+                exit(EXIT_FAILURE);
+	    }
+	}
+
+	/* -------------------------------------------------------------------- */
+	/*      Does the projection of the current location match the           */
+	/*      dataset?                                                        */
+	/* -------------------------------------------------------------------- */
+	G_get_default_window(&loc_wind);
+	/* fetch LOCATION PROJ info */
+	if (loc_wind.proj != PROJECTION_XY) {
+	    loc_proj_info = G_get_projinfo();
+	    loc_proj_units = G_get_projunits();
+	}
+
+	if (override) {
+	    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)) != 1) {
+	    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) {
+		/* error in proj_info */
+		if (loc_proj_info != NULL) {
+		    strcat(error_msg, _("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, _("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]);
+		    strcat(error_msg, "\nERROR: ");
+		    switch (err) {
+		    case -1:
+			strcat(error_msg, "proj\n");
+			break;
+		    case -2:
+			strcat(error_msg, "units\n");
+			break;
+		    case -3:
+			strcat(error_msg, "datum\n");
+			break;
+		    case -4:
+			strcat(error_msg, "ellps, a, es\n");
+			break;
+		    case -5:
+			strcat(error_msg, "zone\n");
+			break;
+		    case -6:
+			strcat(error_msg, "south\n");
+			break;
+		    case -7:
+			strcat(error_msg, "x_0\n");
+			break;
+		    case -8:
+			strcat(error_msg, "y_0\n");
+			break;
+		    case -9:
+			strcat(error_msg, "lon_0\n");
+			break;
+		    case -10:
+			strcat(error_msg, "lat_0\n");
+			break;
+		    case -11:
+			strcat(error_msg, "lat_1, lat2\n");
+			break;
+		    }
+		}
+		else {
+		    strcat(error_msg, _("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
+			sprintf(error_msg + strlen(error_msg),
+				"Dataset proj = %d (unknown), zone = %d\n",
+				cellhd->proj, cellhd->zone);
+		}
+	    }
+	    else {
+		/* error in proj_units */
+		if (loc_proj_units != NULL) {
+		    strcat(error_msg, "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, "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]);
+		}
+	    }
+	    strcat(error_msg,
+		   _("\nIn case of no significant differences in the projection definitions,"
+		     " use the -o flag to ignore them and use"
+		     " current location definition.\n"));
+	    strcat(error_msg,
+		   _("Consider generating a new location from the input dataset using "
+		    "the 'location' parameter.\n"));
+
+	    if (check_only)
+		msg_fn = G_message;
+	    else
+		msg_fn = G_fatal_error;
+	    msg_fn(error_msg);
+	    if (check_only) {
+		exit(EXIT_FAILURE);
+	    }
+	}
+	else {
+	    if (check_only)
+		msg_fn = G_message;
+	    else
+		msg_fn = G_verbose_message;            
+	    msg_fn(_("Projection of input dataset and current location "
+		     "appear to match"));
+	    if (check_only) {
+		ds_close(hDS);
+		exit(EXIT_SUCCESS);
+	    }
+	}
+    }
+}



More information about the grass-commit mailing list