Beispiel #1
0
/* returns 0 on success, 1 on failure */
int G__write_fp_format(int fd)
{
    struct fileinfo *fcb = &G__.fileinfo[fd];
    struct Key_Value *format_kv;
    char path[GPATH_MAX];
    int stat;

    if (fcb->map_type == CELL_TYPE) {
	G_warning(_("unable to write f_format file for CELL maps"));
	return 0;
    }
    format_kv = G_create_key_value();
    if (fcb->map_type == FCELL_TYPE)
	G_set_key_value("type", "float", format_kv);
    else
	G_set_key_value("type", "double", format_kv);

    G_set_key_value("byte_order", "xdr", format_kv);

    if (fcb->open_mode == OPEN_NEW_COMPRESSED)
	G_set_key_value("lzw_compression_bits", "-1", format_kv);

    G__make_mapset_element_misc("cell_misc", fcb->name);
    G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, fcb->mapset);
    G_write_key_value_file(path, format_kv, &stat);

    G_free_key_value(format_kv);

    return stat;
}
Beispiel #2
0
int set_datum(char *datum)
{
    struct gpj_datum dstruct;
    struct Key_Value *temp_projinfo;
    int i;

    if (cellhd.proj == PROJECTION_XY)
	return 0;

    if (!datum || GPJ_get_datum_by_name(datum, &dstruct) < 0)
    {
	G_fatal_error(_("Invalid datum code <%s>"), datum);
	return 0;
    }

    temp_projinfo = G_create_key_value();

    /* Copy old PROJ_INFO, skipping out any keys related
     * to datum or ellipsoid parameters */
    for (i = 0; i < projinfo->nitems; i++) {
        if (strcmp(projinfo->key[i], "datum") == 0
	    || strcmp(projinfo->key[i], "dx") == 0
	    || strcmp(projinfo->key[i], "dy") == 0
	    || strcmp(projinfo->key[i], "dz") == 0
	    || strcmp(projinfo->key[i], "datumparams") == 0
	    || strcmp(projinfo->key[i], "nadgrids") == 0
	    || strcmp(projinfo->key[i], "towgs84") == 0
	    || strcmp(projinfo->key[i], "ellps") == 0
	    || strcmp(projinfo->key[i], "a") == 0
	    || strcmp(projinfo->key[i], "b") == 0
	    || strcmp(projinfo->key[i], "es") == 0
	    || strcmp(projinfo->key[i], "f") == 0
	    || strcmp(projinfo->key[i], "rf") == 0)
	    continue;

	G_set_key_value(projinfo->key[i], projinfo->value[i],
			temp_projinfo);
    }

    /* Finally add datum and ellipsoid names */
    G_set_key_value("datum", dstruct.name, temp_projinfo);
    G_message(_("Datum set to <%s>"), dstruct.name);
    G_set_key_value("ellps", dstruct.ellps, temp_projinfo);
    G_message(_("Ellipsoid set to <%s>"), dstruct.ellps);

    /* Destroy original key/value structure and replace with new one */
    G_free_key_value(projinfo);
    projinfo = temp_projinfo;

    return 1;
}
Beispiel #3
0
int main(int argc, char *argv[])
{
    int i, type, stat;
    int day, yr, Out_proj;
    int out_zone = 0;
    int overwrite;		/* overwrite output map */
    const char *mapset;
    const char *omap_name, *map_name, *iset_name, *iloc_name;
    struct pj_info info_in;
    struct pj_info info_out;
    const char *gbase;
    char date[40], mon[4];
    struct GModule *module;
    struct Option *omapopt, *mapopt, *isetopt, *ilocopt, *ibaseopt, *smax;
    struct Key_Value *in_proj_keys, *in_unit_keys;
    struct Key_Value *out_proj_keys, *out_unit_keys;
    struct line_pnts *Points, *Points2;
    struct line_cats *Cats;
    struct Map_info Map;
    struct Map_info Out_Map;
    struct bound_box src_box, tgt_box;
    int nowrap = 0, recommend_nowrap = 0;
    double lmax;
    struct
    {
	struct Flag *list;	/* list files in source location */
	struct Flag *transformz;	/* treat z as ellipsoidal height */
	struct Flag *wrap;		/* latlon output: wrap to 0,360 */
	struct Flag *no_topol;		/* do not build topology */
    } flag;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("projection"));
    G_add_keyword(_("transformation"));
    G_add_keyword(_("import"));
    module->description = _("Re-projects a vector map from one location to the current location.");

    /* set up the options and flags for the command line parser */

    ilocopt = G_define_standard_option(G_OPT_M_LOCATION);
    ilocopt->required = YES;
    ilocopt->label = _("Location containing input vector map");
    ilocopt->guisection = _("Source");
    
    isetopt = G_define_standard_option(G_OPT_M_MAPSET);
    isetopt->label = _("Mapset containing input vector map");
    isetopt->description = _("Default: name of current mapset");
    isetopt->guisection = _("Source");

    mapopt = G_define_standard_option(G_OPT_V_INPUT);
    mapopt->required = NO;
    mapopt->label = _("Name of input vector map to re-project");
    mapopt->description = NULL;
    mapopt->guisection = _("Source");
    
    ibaseopt = G_define_standard_option(G_OPT_M_DBASE);
    ibaseopt->label = _("Path to GRASS database of input location");
    
    smax = G_define_option();
    smax->key = "smax";
    smax->type = TYPE_DOUBLE;
    smax->required = NO;
    smax->answer = "10000";
    smax->label = _("Maximum segment length in meters in output vector map");
    smax->description = _("Increases accuracy of reprojected shapes, disable with smax=0");
    smax->guisection = _("Target");

    omapopt = G_define_standard_option(G_OPT_V_OUTPUT);
    omapopt->required = NO;
    omapopt->description = _("Name for output vector map (default: input)");
    omapopt->guisection = _("Target");

    flag.list = G_define_flag();
    flag.list->key = 'l';
    flag.list->description = _("List vector maps in input mapset and exit");

    flag.transformz = G_define_flag();
    flag.transformz->key = 'z';
    flag.transformz->description = _("3D vector maps only");
    flag.transformz->label =
	_("Assume z coordinate is ellipsoidal height and "
	  "transform if possible");
    flag.transformz->guisection = _("Target");

    flag.wrap = G_define_flag();
    flag.wrap->key = 'w';
    flag.wrap->description = _("Latlon output only, default is -180,180");
    flag.wrap->label =
	_("Disable wrapping to -180,180 for latlon output");
    flag.transformz->guisection = _("Target");

    flag.no_topol = G_define_flag();
    flag.no_topol->key = 'b';
    flag.no_topol->label = _("Do not build vector topology");
    flag.no_topol->description = _("Recommended for massive point projection");

    /* The parser checks if the map already exists in current mapset,
       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);

    /* start checking options and flags */
    /* set input vector map name and mapset */
    map_name = mapopt->answer;
    if (omapopt->answer)
	omap_name = omapopt->answer;
    else
	omap_name = map_name;
    if (omap_name && !flag.list->answer && !overwrite &&
	G_find_vector2(omap_name, G_mapset()))
	G_fatal_error(_("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"), omapopt->key,
		      omap_name);
    if (isetopt->answer)
	iset_name = isetopt->answer;
    else
	iset_name = G_store(G_mapset());

    iloc_name = ilocopt->answer;

    if (ibaseopt->answer)
	gbase = ibaseopt->answer;
    else
	gbase = G_store(G_gisdbase());

    if (!ibaseopt->answer && strcmp(iloc_name, G_location()) == 0)
	G_fatal_error(_("Input and output locations can not be the same"));

    lmax = atof(smax->answer);
    if (lmax < 0)
	lmax = 0;

    Out_proj = G_projection();
    if (Out_proj == PROJECTION_LL && flag.wrap->answer)
	nowrap = 1;
    
    G_begin_distance_calculations();

    /* Change the location here and then come back */

    select_target_env();
    G_setenv_nogisrc("GISDBASE", gbase);
    G_setenv_nogisrc("LOCATION_NAME", iloc_name);
    stat = G_mapset_permissions(iset_name);
    
    if (stat >= 0) {		/* yes, we can access the mapset */
	/* if requested, list the vector maps in source location - MN 5/2001 */
	if (flag.list->answer) {
	    int i;
	    char **list;
	    G_verbose_message(_("Checking location <%s> mapset <%s>"),
			      iloc_name, iset_name);
	    list = G_list(G_ELEMENT_VECTOR, G_getenv_nofatal("GISDBASE"),
			  G_getenv_nofatal("LOCATION_NAME"), iset_name);
	    if (list[0]) {
		for (i = 0; list[i]; i++) {
		    fprintf(stdout, "%s\n", list[i]);
		}
		fflush(stdout);
	    }
	    else {
		G_important_message(_("No vector maps found"));
	    }
	    exit(EXIT_SUCCESS);	/* leave v.proj after listing */
	}

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

	G_setenv_nogisrc("MAPSET", iset_name);
	/* Make sure map is available */
	mapset = G_find_vector2(map_name, iset_name);
	if (mapset == NULL)
	    G_fatal_error(_("Vector map <%s> in location <%s> mapset <%s> not found"),
			  map_name, iloc_name, iset_name);

	 /*** Get projection info for input mapset ***/
	in_proj_keys = G_get_projinfo();
	if (in_proj_keys == NULL)
	    exit(EXIT_FAILURE);

	/* apparently the +over switch must be set in the input projection,
	 * not the output latlon projection */
	if (Out_proj == PROJECTION_LL && nowrap == 1)
	    G_set_key_value("+over", "defined", in_proj_keys);

	in_unit_keys = G_get_projunits();
	if (in_unit_keys == NULL)
	    exit(EXIT_FAILURE);

	if (pj_get_kv(&info_in, in_proj_keys, in_unit_keys) < 0)
	    exit(EXIT_FAILURE);

	Vect_set_open_level(1);
	G_debug(1, "Open old: location: %s mapset : %s", G_location_path(),
		G_mapset());
	if (Vect_open_old(&Map, map_name, mapset) < 0)
	    G_fatal_error(_("Unable to open vector map <%s>"), map_name);
    }
    else if (stat < 0)
    {				/* allow 0 (i.e. denied permission) */
	/* need to be able to read from others */
	if (stat == 0)
	    G_fatal_error(_("Mapset <%s> in input location <%s> - permission denied"),
			  iset_name, iloc_name);
	else
	    G_fatal_error(_("Mapset <%s> in input location <%s> not found"),
			  iset_name, iloc_name);
    }

    select_current_env();

    /****** get the output projection parameters ******/
    out_proj_keys = G_get_projinfo();
    if (out_proj_keys == NULL)
	exit(EXIT_FAILURE);

    out_unit_keys = G_get_projunits();
    if (out_unit_keys == NULL)
	exit(EXIT_FAILURE);

    if (pj_get_kv(&info_out, out_proj_keys, out_unit_keys) < 0)
	exit(EXIT_FAILURE);

    G_free_key_value(in_proj_keys);
    G_free_key_value(in_unit_keys);
    G_free_key_value(out_proj_keys);
    G_free_key_value(out_unit_keys);

    if (G_verbose() == G_verbose_max()) {
	pj_print_proj_params(&info_in, &info_out);
    }

    /* Initialize the Point / Cat structure */
    Points = Vect_new_line_struct();
    Points2 = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    /* test if latlon wrapping to -180,180 should be disabled */
    if (Out_proj == PROJECTION_LL && nowrap == 0) {
	int first = 1, counter = 0;
	double x, y;
	
	/* Cycle through all lines */
	Vect_rewind(&Map);
	while (1) {
	    type = Vect_read_next_line(&Map, Points, Cats);	/* read line */
	    if (type == 0)
		continue;		/* Dead */

	    if (type == -1)
		G_fatal_error(_("Reading input vector map"));
	    if (type == -2)
		break;
		
	    if (first && Points->n_points > 0) {
		first = 0;
		src_box.E = src_box.W = Points->x[0];
		src_box.N = src_box.S = Points->y[0];
		src_box.T = src_box.B = Points->z[0];
	    }
	    for (i = 0; i < Points->n_points; i++) {
		if (src_box.E < Points->x[i])
		    src_box.E = Points->x[i];
		if (src_box.W > Points->x[i])
		    src_box.W = Points->x[i];
		if (src_box.N < Points->y[i])
		    src_box.N = Points->y[i];
		if (src_box.S > Points->y[i])
		    src_box.S = Points->y[i];
	    }
	    counter++;
	}
	if (counter == 0) {
	    G_warning(_("Input vector map <%s> is empty"), omap_name);
	    exit(EXIT_SUCCESS);
	}
	/* NW corner */
	x = src_box.W;
	y = src_box.N;
	if (pj_do_transform(1, &x, &y, NULL,
			    &info_in, &info_out) < 0) {
	    G_fatal_error(_("Error in pj_do_transform"));
	}
	tgt_box.E = x;
	tgt_box.W = x;
	tgt_box.N = y;
	tgt_box.S = y;
	/* SW corner */
	x = src_box.W;
	y = src_box.S;
	if (pj_do_transform(1, &x, &y, NULL,
			    &info_in, &info_out) < 0) {
	    G_fatal_error(_("Error in pj_do_transform"));
	}
	if (tgt_box.W > x)
	    tgt_box.W = x;
	if (tgt_box.E < x)
	    tgt_box.E = x;
	if (tgt_box.N < y)
	    tgt_box.N = y;
	if (tgt_box.S > y)
	    tgt_box.S = y;
	/* NE corner */
	x = src_box.E;
	y = src_box.N;
	if (pj_do_transform(1, &x, &y, NULL,
			    &info_in, &info_out) < 0) {
	    G_fatal_error(_("Error in pj_do_transform"));
	}
	if (tgt_box.W > x) {
	    tgt_box.E = x + 360;
	    recommend_nowrap = 1;
	}
	if (tgt_box.N < y)
	    tgt_box.N = y;
	if (tgt_box.S > y)
	    tgt_box.S = y;
	/* SE corner */
	x = src_box.E;
	y = src_box.S;
	if (pj_do_transform(1, &x, &y, NULL,
			    &info_in, &info_out) < 0) {
	    G_fatal_error(_("Error in pj_do_transform"));
	}
	if (tgt_box.W > x) {
	    if (tgt_box.E < x + 360)
		tgt_box.E = x + 360;
	    recommend_nowrap = 1;
	}
	if (tgt_box.N < y)
	    tgt_box.N = y;
	if (tgt_box.S > y)
	    tgt_box.S = y;
    }

    G_debug(1, "Open new: location: %s mapset : %s", G_location_path(),
	    G_mapset());

    if (Vect_open_new(&Out_Map, omap_name, Vect_is_3d(&Map)) < 0)
	G_fatal_error(_("Unable to create vector map <%s>"), omap_name);

    Vect_set_error_handler_io(NULL, &Out_Map); /* register standard i/o error handler */
    
    Vect_copy_head_data(&Map, &Out_Map);
    Vect_hist_copy(&Map, &Out_Map);
    Vect_hist_command(&Out_Map);

    out_zone = info_out.zone;
    Vect_set_zone(&Out_Map, out_zone);

    /* Read and write header info */
    sprintf(date, "%s", G_date());
    sscanf(date, "%*s%s%d%*s%d", mon, &day, &yr);
    if (yr < 2000)
	yr = yr - 1900;
    else
	yr = yr - 2000;
    sprintf(date, "%s %d %d", mon, day, yr);
    Vect_set_date(&Out_Map, date);

    /* line densification works only with vector topology */
    if (Map.format != GV_FORMAT_NATIVE)
	lmax = 0;

    /* Cycle through all lines */
    Vect_rewind(&Map);
    i = 0;
    G_message(_("Reprojecting primitives ..."));
    while (TRUE) {
	++i;
	G_progress(i, 1e3);
	type = Vect_read_next_line(&Map, Points, Cats);	/* read line */
	if (type == 0)
	    continue;		/* Dead */

	if (type == -1)
	    G_fatal_error(_("Reading input vector map"));
	if (type == -2)
	    break;

	Vect_line_prune(Points);
	if (lmax > 0 && (type & GV_LINES) && Points->n_points > 1) {
	    double x1, y1, z1, x2, y2, z2;
	    double dx, dy, dz;
	    double l;
	    int i, n;

	    Vect_reset_line(Points2);
	    for (i = 0; i < Points->n_points - 1; i++) {
		x1 = Points->x[i];
		y1 = Points->y[i];
		z1 = Points->z[i];
		n = i + 1;
		x2 = Points->x[n];
		y2 = Points->y[n];
		z2 = Points->z[n];

		dx = x2 - x1;
		dy = y2 - y1;
		dz = z2 - z1;

		if (pj_do_transform(1, &x1, &y1,
				    flag.transformz->answer ? &z1 : NULL,
				    &info_in, &info_out) < 0) {
		  G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"),
				Vect_get_full_name(&Map), ilocopt->answer);
		}

		if (pj_do_transform(1, &x2, &y2,
				    flag.transformz->answer ? &z2 : NULL,
				    &info_in, &info_out) < 0) {
		  G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"),
				Vect_get_full_name(&Map), ilocopt->answer);
		}

		Vect_append_point(Points2, x1, y1, z1);

		l = G_distance(x1, y1, x2, y2);

		if (l > lmax) {
		    int j;
		    double x, y, z;

		    x1 = Points->x[i];
		    y1 = Points->y[i];
		    z1 = Points->z[i];

		    n = ceil(l / lmax);

		    for (j = 1; j < n; j++) {
			x = x1 + dx * j / n;
			y = y1 + dy * j / n;
			z = z1 + dz * j / n;

			if (pj_do_transform(1, &x, &y,
					    flag.transformz->answer ? &z : NULL,
					    &info_in, &info_out) < 0) {
			  G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"),
					Vect_get_full_name(&Map), ilocopt->answer);
			}
			Vect_append_point(Points2, x, y, z);
		    }
		}
	    }
	    Vect_append_point(Points2, x2, y2, z2);
	    Vect_write_line(&Out_Map, type, Points2, Cats);	/* write line */
	}
	else {
	    if (pj_do_transform(Points->n_points, Points->x, Points->y,
				flag.transformz->answer ? Points->z : NULL,
				&info_in, &info_out) < 0) {
	      G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"),
			    Vect_get_full_name(&Map), ilocopt->answer);
	    }

	    Vect_write_line(&Out_Map, type, Points, Cats);	/* write line */
	}
    }				/* end lines section */
    G_progress(1, 1);

    /* Copy tables */
    if (Vect_copy_tables(&Map, &Out_Map, 0))
        G_warning(_("Failed to copy attribute table to output map"));

    Vect_close(&Map);

    if (!flag.no_topol->answer)
        Vect_build(&Out_Map);
    Vect_close(&Out_Map);

    if (recommend_nowrap)
	G_important_message(_("Try to disable wrapping to -180,180 "
			      "if topological errors occurred"));

    exit(EXIT_SUCCESS);
}
Beispiel #4
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    int Out_proj;
    int out_stat;
    int old_zone, old_proj;
    int i;
    int stat;
    char cmnd2[500];
    char proj_out[20], proj_name[50], set_name[20];
    char path[1024], buffa[1024], buffb[1024], answer[200], answer1[200];
    char answer2[200], buff[1024];
    char tmp_buff[20], *buf;

    struct Key_Value *old_proj_keys, *out_proj_keys, *in_unit_keys;
    double aa, e2;
    double f;
    FILE *FPROJ;
    int exist = 0;
    char spheroid[100];
    int j, k, sph_check;
    struct Cell_head cellhd;
    char datum[100], dat_ellps[100], dat_params[100];
    struct proj_parm *proj_parms;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("general"));
    G_add_keyword(_("projection"));
    module->description =
	_("Interactively reset the location's projection settings.");

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


    if (strcmp(G_mapset(), "PERMANENT") != 0)
	G_fatal_error(_("You must be in the PERMANENT mapset to run g.setproj"));

	/***
         * no longer necessary, table is a static struct 
	 * init_unit_table();
        ***/
    sprintf(set_name, "PERMANENT");
    G_file_name(path, "", PROJECTION_FILE, set_name);

    /* get the output projection parameters, if existing */
    /* Check for ownership here */
    stat = G__mapset_permissions(set_name);
    if (stat == 0) {
	G_fatal_error(_("PERMANENT: permission denied"));
    }
    G_get_default_window(&cellhd);
    if (-1 == G_set_window(&cellhd))
	G_fatal_error(_("Current region cannot be set"));

    if (G_get_set_window(&cellhd) == -1)
	G_fatal_error(_("Retrieving and setting region failed"));

    Out_proj = cellhd.proj;
    old_zone = cellhd.zone;
    old_proj = cellhd.proj;

    if (access(path, 0) == 0) {
	exist = 1;
	FPROJ = fopen(path, "r");
	old_proj_keys = G_fread_key_value(FPROJ);
	fclose(FPROJ);
	buf = G_find_key_value("name", old_proj_keys);
	fprintf(stderr,
		"\nWARNING: A projection file already exists for this location\n(Filename '%s')\n",
		path);
	fprintf(stderr,
		"\nThis file contains all the parameters for the location's projection:\n  %s\n",
		buf);
	fprintf(stderr,
		"\n    Overriding this information implies that the old projection parameters\n"
		"    were incorrect.  If you change the parameters, all existing data will\n"
		"    be interpreted differently by the projection software.\n%c%c%c",
		7, 7, 7);
	fprintf(stderr,
		"    GRASS will not re-project your data automatically.\n\n");

	if (!G_yes
	    (_("Would you still like to change some of the parameters?"),
	     0)) {
	    G_message(_("The projection information will not be updated"));
	    leave(SP_NOCHANGE);
	}
    }
    out_proj_keys = G_create_key_value();

    if (exist) {
	buf = G_find_key_value("zone", old_proj_keys);
	if (buf != NULL)
	    sscanf(buf, "%d", &zone);
	if (zone != old_zone) {
	    G_warning(_("Zone in default geographic region definition: %d\n"
			" is different from zone in PROJ_INFO file: %d"),
		      old_zone, zone);
	    old_zone = zone;
	}
    }
    switch (Out_proj) {
    case 0:			/* No projection/units */
	if (!exist) {
	    /* leap frog over code, and just make sure we remove the file */
	    G_warning(_("XY-location cannot be projected"));
	    goto write_file;
	    break;
	}
    case PROJECTION_UTM:
	if (!exist) {
	    sprintf(proj_name, "%s", G__projection_name(PROJECTION_UTM));
	    sprintf(proj_out, "utm");
	    break;
	}
    case PROJECTION_SP:
	if (!exist) {
	    sprintf(proj_name, "%s", G__projection_name(PROJECTION_SP));
	    sprintf(proj_out, "stp");
	    break;
	}
    case PROJECTION_LL:
	if (!exist) {
	    sprintf(proj_name, "%s", G__projection_name(PROJECTION_LL));
	    sprintf(proj_out, "ll");
	    break;
	}
    case PROJECTION_OTHER:
	if (G_ask_proj_name(proj_out, proj_name) < 0)
	    leave(SP_NOCHANGE);

	if (G_strcasecmp(proj_out, "LL") == 0)
	    Out_proj = PROJECTION_LL;
	else if (G_strcasecmp(proj_out, "UTM") == 0)
	    Out_proj = PROJECTION_UTM;
	else if (G_strcasecmp(proj_out, "STP") == 0)
	    Out_proj = PROJECTION_SP;
	break;
    default:
	G_fatal_error(_("Unknown projection"));
    }
    cellhd.proj = Out_proj;

    proj_parms = get_proj_parms(proj_out);
    if (!proj_parms)
	G_fatal_error(_("Projection %s is not specified in the file 'proj-parms.table'"),
		      proj_out);

    G_set_key_value("name", proj_name, out_proj_keys);

    sph_check = 0;
    if (G_yes
	(_("Do you wish to specify a geodetic datum for this location?"),
	 1)) {
	char lbuf[100], lbufa[100];

	if (exist &&
	    (G_get_datumparams_from_projinfo(old_proj_keys, lbuf, lbufa) ==
	     2)) {
	    G_strip(lbuf);
	    if ((i = G_get_datum_by_name(lbuf)) > 0) {
		G_message(_("The current datum is %s (%s)"),
			  G_datum_name(i), G_datum_description(i));
		if (G_yes
		    (_("Do you wish to change the datum (or datum transformation parameters)?"),
		     0))
		    sph_check = ask_datum(datum, dat_ellps, dat_params);
		else {
		    sprintf(datum, lbuf);
		    sprintf(dat_params, lbufa);
		    sprintf(dat_ellps, G_datum_ellipsoid(i));
		    sph_check = 1;
		    G_message(_("The datum information has not been changed"));
		}
	    }
	    else
		sph_check = ask_datum(datum, dat_ellps, dat_params);

	}
	else
	    sph_check = ask_datum(datum, dat_ellps, dat_params);
    }

    if (sph_check > 0) {
	char *paramkey, *paramvalue;

	/* write out key/value pairs to out_proj_keys */
	if (G_strcasecmp(datum, "custom") != 0)
	    G_set_key_value("datum", datum, out_proj_keys);
	/*        G_set_key_value("datumparams", dat_params, out_proj_keys); */
	paramkey = strtok(dat_params, "=");
	paramvalue = dat_params + strlen(paramkey) + 1;
	G_set_key_value(paramkey, paramvalue, out_proj_keys);
	sprintf(spheroid, "%s", dat_ellps);
    }
    else {

/*****************   GET spheroid  **************************/

	if (Out_proj != PROJECTION_SP) {	/* some projections have 
						 * fixed spheroids */
	    if (G_strcasecmp(proj_out, "ALSK") == 0 ||
		G_strcasecmp(proj_out, "GS48") == 0 ||
		G_strcasecmp(proj_out, "GS50") == 0) {
		sprintf(spheroid, "%s", "clark66");
		G_set_key_value("ellps", spheroid, out_proj_keys);
		sph_check = 1;
	    }
	    else if (G_strcasecmp(proj_out, "LABRD") == 0 ||
		     G_strcasecmp(proj_out, "NZMG") == 0) {
		sprintf(spheroid, "%s", "international");
		G_set_key_value("ellps", spheroid, out_proj_keys);
		sph_check = 1;
	    }
	    else if (G_strcasecmp(proj_out, "SOMERC") == 0) {
		sprintf(spheroid, "%s", "bessel");
		G_set_key_value("ellps", spheroid, out_proj_keys);
		sph_check = 1;
	    }
	    else if (G_strcasecmp(proj_out, "OB_TRAN") == 0) {
		/* Hard coded to use "Equidistant Cylincrical"
		 * until g.setproj has been changed to run
		 * recurively, to allow input of options for
		 * a second projection, MHu991010 */
		G_set_key_value("o_proj", "eqc", out_proj_keys);
		sph_check = 2;
	    }
	    else {
		if (exist &&
		    (buf =
		     G_find_key_value("ellps", old_proj_keys)) != NULL) {
		    strcpy(spheroid, buf);
		    G_strip(spheroid);
		    if (G_get_spheroid_by_name(spheroid, &aa, &e2, &f)) {
			/* if legal ellips. exist, ask wether or not to change it */
			G_message(_("The current ellipsoid is %s"), spheroid);
			if (G_yes
			    (_("Do you want to change ellipsoid parameter?"),
			     0))
			    sph_check = G_ask_ellipse_name(spheroid);
			else {
			    G_message(_("The ellipse information has not been changed"));
			    sph_check = 1;
			}
		    }		/* the val is legal */
		    else
			sph_check = G_ask_ellipse_name(spheroid);
		}
		else
		    sph_check = G_ask_ellipse_name(spheroid);
	    }
	}

	if (sph_check > 0) {
	    if (sph_check == 2) {	/* ask radius */
		if (exist) {
		    buf = G_find_key_value("a", old_proj_keys);
		    if ((buf != NULL) && (sscanf(buf, "%lf", &radius) == 1)) {
			G_message(_("The radius is currently %f"), radius);
			if (G_yes(_("Do you want to change the radius?"), 0))
			    radius =
				prompt_num_double(_("Enter radius for the sphere in meters"),
						  RADIUS_DEF, 1);
		    }
		}
		else
		    radius =
			prompt_num_double(_("Enter radius for the sphere in meters"),
					  RADIUS_DEF, 1);
	    }			/* end ask radius */
	}
    }

/*** END get spheroid  ***/


    /* create the PROJ_INFO & PROJ_UNITS files, if required */
    if (G_strcasecmp(proj_out, "LL") == 0) ;
    else if (G_strcasecmp(proj_out, "STP") == 0)
	get_stp_proj(buffb);
    else if (sph_check != 2) {
	G_strip(spheroid);
	if (G_get_spheroid_by_name(spheroid, &aa, &e2, &f) == 0)
	    G_fatal_error(_("Invalid input ellipsoid"));
    }

  write_file:
    /*
     **  NOTE   the program will (hopefully) never exit abnormally
     **  after this point.  Thus we know the file will be completely
     **  written out once it is opened for write 
     */
    if (exist) {
	sprintf(buff, "%s~", path);
	G_rename_file(path, buff);
    }
    if (Out_proj == 0)
	goto write_units;

    /*
     **   Include MISC parameters for PROJ_INFO
     */
    if (G_strcasecmp(proj_out, "STP") == 0) {
	for (i = 0; i < strlen(buffb); i++)
	    if (buffb[i] == ' ')
		buffb[i] = '\t';
	sprintf(cmnd2, "%s\t\n", buffb);
	for (i = 0; i < strlen(cmnd2); i++) {
	    j = k = 0;
	    if (cmnd2[i] == '+') {
		while (cmnd2[++i] != '=')
		    buffa[j++] = cmnd2[i];
		buffa[j] = 0;
		while (cmnd2[++i] != '\t' && cmnd2[i] != '\n' &&
		       cmnd2[i] != 0)
		    buffb[k++] = cmnd2[i];
		buffb[k] = 0;
		G_set_key_value(buffa, buffb, out_proj_keys);
	    }
	}
    }
    else if (G_strcasecmp(proj_out, "LL") == 0) {
	G_set_key_value("proj", "ll", out_proj_keys);
	G_set_key_value("ellps", spheroid, out_proj_keys);
    }
    else {
	if (sph_check != 2) {
	    G_set_key_value("proj", proj_out, out_proj_keys);
	    G_set_key_value("ellps", spheroid, out_proj_keys);
	    sprintf(tmp_buff, "%.10f", aa);
	    G_set_key_value("a", tmp_buff, out_proj_keys);
	    sprintf(tmp_buff, "%.10f", e2);
	    G_set_key_value("es", tmp_buff, out_proj_keys);
	    sprintf(tmp_buff, "%.10f", f);
	    G_set_key_value("f", tmp_buff, out_proj_keys);
	}
	else {
	    G_set_key_value("proj", proj_out, out_proj_keys);
	    /* G_set_key_value ("ellps", "sphere", out_proj_keys); */
	    sprintf(tmp_buff, "%.10f", radius);
	    G_set_key_value("a", tmp_buff, out_proj_keys);
	    G_set_key_value("es", "0.0", out_proj_keys);
	    G_set_key_value("f", "0.0", out_proj_keys);
	}

	for (i = 0;; i++) {
	    struct proj_parm *parm = &proj_parms[i];
	    struct proj_desc *desc;

	    if (!parm->name)
		break;

	    desc = get_proj_desc(parm->name);
	    if (!desc)
		break;

	    if (parm->ask) {
		if (G_strcasecmp(desc->type, "bool") == 0) {
		    if (G_yes((char *)desc->desc, 0)) {
			G_set_key_value(desc->key, "defined", out_proj_keys);
			if (G_strcasecmp(parm->name, "SOUTH") == 0)
			    cellhd.zone = -abs(cellhd.zone);
		    }
		}
		else if (G_strcasecmp(desc->type, "lat") == 0) {
		    double val;

		    while (!get_LL_stuff(parm, desc, 1, &val)) ;
		    sprintf(tmp_buff, "%.10f", val);
		    G_set_key_value(desc->key, tmp_buff, out_proj_keys);
		}
		else if (G_strcasecmp(desc->type, "lon") == 0) {
		    double val;

		    while (!get_LL_stuff(parm, desc, 0, &val)) ;
		    sprintf(tmp_buff, "%.10f", val);
		    G_set_key_value(desc->key, tmp_buff, out_proj_keys);
		}
		else if (G_strcasecmp(desc->type, "float") == 0) {
		    double val;

		    while (!get_double(parm, desc, &val)) ;
		    sprintf(tmp_buff, "%.10f", val);
		    G_set_key_value(desc->key, tmp_buff, out_proj_keys);
		}
		else if (G_strcasecmp(desc->type, "int") == 0) {
		    int val;

		    while (!get_int(parm, desc, &val)) ;
		    sprintf(tmp_buff, "%d", val);
		    G_set_key_value(desc->key, tmp_buff, out_proj_keys);
		}
		else if (G_strcasecmp(desc->type, "zone") == 0) {
		    if ((Out_proj == PROJECTION_UTM) && (old_zone != 0)) {
			G_message(_("The UTM zone is now set to %d"),
				  old_zone);
			if (!G_yes
			    (_("Do you want to change the UTM zone?"), 0)) {
			    G_message(_("UTM zone information has not been updated"));
			    zone = old_zone;
			    break;
			}
			else {
			    G_message(_("But if you change zone, all the existing "
				       "data will be interpreted by projection software. "
				       "GRASS will not automatically re-project or even "
				       "change the headers for existing maps."));
			    if (!G_yes
				(_("Would you still like to change the UTM zone?"),
				 0)) {
				zone = old_zone;
				break;
			    }
			}
		    }		/* UTM */

		    while (!get_zone()) ;

		    sprintf(tmp_buff, "%d", zone);
		    G_set_key_value("zone", tmp_buff, out_proj_keys);
		    cellhd.zone = zone;
		}
	    }
	    else if (parm->def_exists) {
		/* don't ask, use the default */

		if (G_strcasecmp(desc->type, "float") == 0 ||
		    G_strcasecmp(desc->type, "lat") == 0 ||
		    G_strcasecmp(desc->type, "lon") == 0) {
		    sprintf(tmp_buff, "%.10f", parm->deflt);
		    G_set_key_value(desc->key, tmp_buff, out_proj_keys);
		}
		else if (G_strcasecmp(desc->type, "int") == 0) {
		    sprintf(tmp_buff, "%d", (int)parm->deflt);
		    G_set_key_value(desc->key, tmp_buff, out_proj_keys);
		}
	    }
	}			/* for OPTIONS */
    }

    /* create the PROJ_INFO & PROJ_UNITS files, if required */

    G_write_key_value_file(path, out_proj_keys, &out_stat);
    if (out_stat != 0) {
	G_fatal_error(_("Error writing PROJ_INFO file <%s>"), path);
    }

    G_free_key_value(out_proj_keys);
    if (exist)
	G_free_key_value(old_proj_keys);

  write_units:
    G_file_name(path, "", UNIT_FILE, set_name);

    /* if we got this far, the user
     ** already affirmed to write over old info
     ** so if units file is here, remove it.
     */
    if (access(path, 0) == 0) {
	sprintf(buff, "%s~", path);
	G_rename_file(path, buff);
    }
    if (Out_proj == 0)
	leave(0);

    {
	in_unit_keys = G_create_key_value();

	switch (Out_proj) {
	case PROJECTION_UTM:
	    G_set_key_value("unit", "meter", in_unit_keys);
	    G_set_key_value("units", "meters", in_unit_keys);
	    G_set_key_value("meters", "1.0", in_unit_keys);
	    break;
	case PROJECTION_SP:
	    for (;;) {

		do {
		    fprintf(stderr, "\nSpecify the correct units to use:\n");
		    fprintf(stderr, "Enter the corresponding number\n");
		    fprintf(stderr,
			    "1.\tUS Survey Foot (Default for State Plane 1927)\n");
		    fprintf(stderr, "2.\tInternational Foot\n");
		    fprintf(stderr, "3.\tMeter\n");
		    fprintf(stderr, ">");
		} while (!G_gets(answer));

		G_strip(answer);
		if (strcmp(answer, "1") == 0) {
		    G_set_key_value("unit", "USfoot", in_unit_keys);
		    G_set_key_value("units", "USfeet", in_unit_keys);
		    G_set_key_value("meters", "0.30480060960121920243",
				    in_unit_keys);
		    break;
		}
		else if (strcmp(answer, "2") == 0) {
		    G_set_key_value("unit", "foot", in_unit_keys);
		    G_set_key_value("units", "feet", in_unit_keys);
		    G_set_key_value("meters", "0.3048", in_unit_keys);
		    break;
		}
		else if (strcmp(answer, "3") == 0) {
		    G_set_key_value("unit", "meter", in_unit_keys);
		    G_set_key_value("units", "meters", in_unit_keys);
		    G_set_key_value("meters", "1.0", in_unit_keys);
		    break;
		}
		else
		    fprintf(stderr, "\nInvalid Entry (number 1 - 3)\n");
	    }
	    break;
	case PROJECTION_LL:
	    G_set_key_value("unit", "degree", in_unit_keys);
	    G_set_key_value("units", "degrees", in_unit_keys);
	    G_set_key_value("meters", "1.0", in_unit_keys);
	    break;
	default:
	    if (G_strcasecmp(proj_out, "LL") != 0) {
		fprintf(stderr, _("Enter plural form of units [meters]: "));
		G_gets(answer);
		if (strlen(answer) == 0) {
		    G_set_key_value("unit", "meter", in_unit_keys);
		    G_set_key_value("units", "meters", in_unit_keys);
		    G_set_key_value("meters", "1.0", in_unit_keys);
		}
		else {
		    const struct proj_unit *unit;

		    G_strip(answer);
		    unit = get_proj_unit(answer);
		    if (unit) {
#ifdef FOO
			if (G_strcasecmp(proj_out, "STP") == 0 &&
			    !strcmp(answer, "feet")) {
			    fprintf(stderr,
				    "%cPROJECTION 99 State Plane cannot be in FEET.\n",
				    7);
			    remove(path);	/* remove file */
			    leave(SP_FATAL);
			}
#endif
			G_set_key_value("unit", unit->unit, in_unit_keys);
			G_set_key_value("units", unit->units, in_unit_keys);
			sprintf(buffb, "%.10f", unit->fact);
			G_set_key_value("meters", buffb, in_unit_keys);
		    }
		    else {
			double unit_fact;

			while (1) {
			    fprintf(stderr, _("Enter singular for unit: "));
			    G_gets(answer1);
			    G_strip(answer1);
			    if (strlen(answer1) > 0)
				break;
			}
			while (1) {
			    fprintf(stderr,
				    _("Enter conversion factor from %s to meters: "),
				    answer);
			    G_gets(answer2);
			    G_strip(answer2);
			    if (!
				(strlen(answer2) == 0 ||
				 (1 != sscanf(answer2, "%lf", &unit_fact))))
				break;
			}
			G_set_key_value("unit", answer1, in_unit_keys);
			G_set_key_value("units", answer, in_unit_keys);
			sprintf(buffb, "%.10f", unit_fact);
			G_set_key_value("meters", buffb, in_unit_keys);
		    }
		}
	    }
	    else {
		G_set_key_value("unit", "degree", in_unit_keys);
		G_set_key_value("units", "degrees", in_unit_keys);
		G_set_key_value("meters", "1.0", in_unit_keys);
	    }
	}			/* switch */

	G_write_key_value_file(path, in_unit_keys, &out_stat);
	if (out_stat != 0)
	    G_fatal_error(_("Error writing into UNITS output file <%s>"),
			  path);

	G_free_key_value(in_unit_keys);
    }				/* if */

    if (G__put_window(&cellhd, "", "DEFAULT_WIND") < 0)
	G_fatal_error(_("Unable to write to DEFAULT_WIND region file"));
    fprintf(stderr,
	    _("\nProjection information has been recorded for this location\n\n"));
    if ((old_zone != zone) | (old_proj != cellhd.proj)) {
	G_message(_("The geographic region information in WIND is now obsolete"));
	G_message(_("Run g.region -d to update it"));
    }
    leave(0);
}
Beispiel #5
0
int set_datumtrans(int datumtrans, int force)
{
    char *params, *datum = NULL;
    int paramsets, status;

    if (cellhd.proj == PROJECTION_XY)
	return 0;

    status = GPJ__get_datum_params(projinfo, &datum, &params);
    G_debug(3, "set_datumtrans(): GPJ__get_datum_params() status=%d", status);
    G_free(params);

    if (datum) {
	/* A datum name is specified; need to determine if
	 * there are parameters to choose from for this datum */
	struct gpj_datum dstruct;

	if (GPJ_get_datum_by_name(datum, &dstruct) > 0) {
	    char *defparams;

	    paramsets =
		GPJ_get_default_datum_params_by_name(dstruct.name,
						     &defparams);
	    G_free(defparams);
	    GPJ_free_datum(&dstruct);

	    G_debug(3, "set_datumtrans(): datum transform terms found "
		    "with %d options", paramsets);

	    if (status == 1 && paramsets > 1)
		/* Parameters are missing and there is a choice to be made */
		force = 1;

	}
	else {
	    /* Datum name not found in table; can't do anything. */
	    G_debug(3, "set_datumtrans(): Datum name not found in table.");
	    force = 0;
	}
    }
    else {
	/* No datum name; can't do anything. */
	G_debug(3, "set_datumtrans(): Datum name either invalid or not supplied.");
	force = 0;
    }

    if (force) {
	char *chosenparams = NULL;
	char *paramkey, *paramvalue;
	struct Key_Value *temp_projinfo;
	int i;

	/* First of all obtain the new parameters 
	 * through the supplied transform number index */
	{
	    struct gpj_datum_transform_list *list;

	    if (datumtrans > paramsets)
		G_fatal_error
		    ("Invalid transformation number %d; valid range is 1 to %d",
		     datumtrans, paramsets);

	    G_debug(3, "set_datumtrans(): looking up available datum "
		    "transforms for <%s>", datum);

	    list = GPJ_get_datum_transform_by_name(datum);

	    if (list != NULL) {
		if (datumtrans == -1) {
		    do {
			struct gpj_datum_transform_list *old = list;
			fprintf(stdout, "---\n%d\nUsed in %s\n%s\n%s\n",
				list->count, list->where_used,
				list->params, list->comment);
			list = list->next;
		        GPJ_free_datum_transform(old);
		    } while (list != NULL);

		    exit(EXIT_SUCCESS);
		}
		else {
		    do {
			struct gpj_datum_transform_list *old = list;
			if (list->count == datumtrans)
			    chosenparams = G_store(list->params);
			list = list->next;
		        GPJ_free_datum_transform(old);
		    } while (list != NULL);
		}
	    }

	}

	temp_projinfo = G_create_key_value();

	/* Copy old PROJ_INFO, skipping out any keys related
	 * to datum parameters */
	for (i = 0; i < projinfo->nitems; i++) {
	    if (strcmp(projinfo->key[i], "dx") == 0
		|| strcmp(projinfo->key[i], "dy") == 0
		|| strcmp(projinfo->key[i], "dz") == 0
		|| strcmp(projinfo->key[i], "datumparams") == 0
		|| strcmp(projinfo->key[i], "nadgrids") == 0
		|| strcmp(projinfo->key[i], "towgs84") == 0)
		continue;

	    G_set_key_value(projinfo->key[i], projinfo->value[i],
			    temp_projinfo);
	}

	/* Finally add new parameters (if we have them) */
	if (chosenparams != NULL) {
	    /* Now split 'chosenparams' into key/value format */
	    paramkey = strtok(chosenparams, "=");
	    paramvalue = chosenparams + strlen(paramkey) + 1;
	    G_set_key_value(paramkey, paramvalue, temp_projinfo);
	    G_free(chosenparams);
	}

	/* Destroy original key/value structure and replace with new one */
	G_free_key_value(projinfo);
	projinfo = temp_projinfo;

    }
    G_free(datum);

    return force;
}
Beispiel #6
0
void make_link(const char *dsn_opt,
	       const char *format,
	       char *option_str, char **options)
{
    int use_ogr;
    char *filename, *dsn;
    FILE *fp;
    
    struct Key_Value *key_val;
    
    key_val = G_create_key_value();

    /* check for weird options */
    if (G_strncasecmp(dsn_opt, "PG:", 3) == 0 &&
        strcmp(format, "PostgreSQL") != 0)
        G_warning(_("Data source starts with \"PG:\" prefix, expecting \"PostgreSQL\" "
                    "format (\"%s\" given)"), format);
    
    /* use OGR ? */
    use_ogr = is_ogr(format);
    if (use_ogr) {
        filename = "OGR";
        G_remove("", "PG");
    }
    else {
        filename = "PG";
        G_remove("", "OGR");
    }
    
    /* be friendly, ignored 'PG:' prefix for GRASS-PostGIS data driver */
    if (!use_ogr && strcmp(format, "PostgreSQL") == 0 &&
	G_strncasecmp(dsn_opt, "PG:", 3) == 0) {
	int i, length;
	
	length = strlen(dsn_opt);
	dsn = (char *) G_malloc(length - 3);
	for (i = 3; i < length; i++)
	    dsn[i-3] = dsn_opt[i];
	dsn[length-3] = '\0';
    }
    else {
	dsn = G_store(dsn_opt);
    }
        
    /* parse options for PG data format */
    if (options && *options && !use_ogr) {
        int i;
        char *key, *value;
        
        i = 0;
        while (options[i]) {
            if (parse_option_pg(options[i++], &key, &value) != 0)
                continue;
            G_set_key_value(key, value, key_val);
        }
    }

    /* datasource section */
    if (dsn) {
	if (use_ogr)
	    G_set_key_value("dsn", dsn, key_val);
	else
	    G_set_key_value("conninfo", dsn, key_val);
    }
    
    if (use_ogr) { /* OGR */
        if (format)
            G_set_key_value("format", format, key_val);
        if (option_str)
            G_set_key_value("options", option_str, key_val);
    }
    else {        /* PG */
        G_set_key_value("format", "PostgreSQL", key_val);
    }
    /* save file - OGR or PG */
    fp = G_fopen_new("", filename);
    if (!fp)
	G_fatal_error(_("Unable to create settings file"));

    if (G_fwrite_key_value(fp, key_val) < 0)
	G_fatal_error(_("Error writing settings file"));

    fclose(fp);

    if (use_ogr)
        G_verbose_message(_("Switched to OGR format (%s)"),
                          G_find_key_value("format", key_val));
    else
        G_verbose_message(_("Switched to PostGIS format"));

    G_free_key_value(key_val);
}
Beispiel #7
0
int GPJ_osr_to_grass(struct Cell_head *cellhd, struct Key_Value **projinfo,
		     struct Key_Value **projunits, OGRSpatialReferenceH hSRS,
		     int datumtrans)
{
    struct Key_Value *temp_projinfo;
    char *pszProj4 = NULL, *pszRemaining;
    char *pszProj = NULL;
    char *datum = NULL;
    struct gpj_datum dstruct;

    if (hSRS == NULL)
	goto default_to_xy;

    /* Set finder function for locating OGR csv co-ordinate system tables */
    SetCSVFilenameHook(GPJ_set_csv_loc);

    /* Hopefully this doesn't do any harm if it wasn't in ESRI format
     * to start with... */
    OSRMorphFromESRI(hSRS);

    /* -------------------------------------------------------------------- */
    /*      Set cellhd for well known coordinate systems.                   */
    /* -------------------------------------------------------------------- */
    if (!OSRIsGeographic(hSRS) && !OSRIsProjected(hSRS))
	goto default_to_xy;

    if (cellhd) {
	int bNorth;

	if (OSRIsGeographic(hSRS)) {
	    cellhd->proj = PROJECTION_LL;
	    cellhd->zone = 0;
	}
	else if (OSRGetUTMZone(hSRS, &bNorth) != 0) {
	    cellhd->proj = PROJECTION_UTM;
	    cellhd->zone = OSRGetUTMZone(hSRS, &bNorth);
	    if (!bNorth)
		cellhd->zone *= -1;
	}
	else {
	    cellhd->proj = PROJECTION_OTHER;
	    cellhd->zone = 0;
	}
    }

    /* -------------------------------------------------------------------- */
    /*      Get the coordinate system definition in PROJ.4 format.          */
    /* -------------------------------------------------------------------- */
    if (OSRExportToProj4(hSRS, &pszProj4) != OGRERR_NONE)
	goto default_to_xy;

    /* -------------------------------------------------------------------- */
    /*      Parse the PROJ.4 string into key/value pairs.  Do a bit of      */
    /*      extra work to "GRASSify" the result.                            */
    /* -------------------------------------------------------------------- */
    temp_projinfo = G_create_key_value();

    /* Create "local" copy of proj4 string so we can modify and free it
     * using GRASS functions */
    pszRemaining = G_store(pszProj4);
    CPLFree(pszProj4);
    pszProj4 = pszRemaining;
    while ((pszRemaining = strstr(pszRemaining, "+")) != NULL) {
	char *pszToken, *pszValue;

	pszRemaining++;

	/* Advance pszRemaining to end of this token[=value] pair */
	pszToken = pszRemaining;
	while (*pszRemaining != ' ' && *pszRemaining != '\0')
	    pszRemaining++;

	if (*pszRemaining == ' ') {
	    *pszRemaining = '\0';
	    pszRemaining++;
	}

	/* parse token, and value */
	if (strstr(pszToken, "=") != NULL) {
	    pszValue = strstr(pszToken, "=");
	    *pszValue = '\0';
	    pszValue++;
	}
	else
	    pszValue = "defined";


	if (G_strcasecmp(pszToken, "proj") == 0) {
	    /* The ll projection is known as longlat in PROJ.4 */
	    if (G_strcasecmp(pszValue, "longlat") == 0)
		pszValue = "ll";

	    pszProj = pszValue;
	    continue;
	}

	/* Ellipsoid and datum handled separately below */
	if (G_strcasecmp(pszToken, "ellps") == 0
	    || G_strcasecmp(pszToken, "a") == 0
	    || G_strcasecmp(pszToken, "b") == 0
	    || G_strcasecmp(pszToken, "es") == 0
	    || G_strcasecmp(pszToken, "rf") == 0
	    || G_strcasecmp(pszToken, "datum") == 0)
	    continue;

	/* We will handle units separately */
	if (G_strcasecmp(pszToken, "to_meter") == 0
	    || G_strcasecmp(pszToken, "units") == 0)
	    continue;

	G_set_key_value(pszToken, pszValue, temp_projinfo);
    }

    *projinfo = G_create_key_value();

    /* -------------------------------------------------------------------- */
    /*      Derive the user name for the projection.                        */
    /* -------------------------------------------------------------------- */
    if (pszProj) {
	char path[4095];
	char name[80];

	sprintf(path, "%s/etc/projections", G_gisbase());
	if (G_lookup_key_value_from_file(path, pszProj, name, sizeof(name)) >
	    0)
	    G_set_key_value("name", name, *projinfo);
	else
	    G_set_key_value("name", pszProj, *projinfo);

	G_set_key_value("proj", pszProj, *projinfo);
    }
    else
	G_warning(_("No projection name! Projection parameters likely to be meaningless."));


    /* -------------------------------------------------------------------- */
    /*      Find the GRASS datum name and choose parameters either          */
    /*      interactively or not.                                           */
    /* -------------------------------------------------------------------- */

    {
	const char *pszDatumNameConst = OSRGetAttrValue(hSRS, "DATUM", 0);
	struct datum_list *list, *listhead;
	char *dum1, *dum2, *pszDatumName;
	int paramspresent =
	    GPJ__get_datum_params(temp_projinfo, &dum1, &dum2);

	if (pszDatumNameConst) {
	    /* Need to make a new copy of the string so we don't mess
	     * around with the memory inside the OGRSpatialReferenceH? */

	    pszDatumName = G_store(pszDatumNameConst);
	    DatumNameMassage(&pszDatumName);

	    list = listhead = read_datum_table();

	    while (list != NULL) {
		if (G_strcasecmp(pszDatumName, list->longname) == 0) {
		    datum = G_store(list->name);
		    break;
		}
		list = list->next;
	    }
	    free_datum_list(listhead);

	    if (datum == NULL) {
		if (paramspresent < 2)
		    /* Only give warning if no parameters present */
		    G_warning(_("Datum <%s> not recognised by GRASS and no parameters found"),
			      pszDatumName);
	    }
	    else {
		G_set_key_value("datum", datum, *projinfo);

		if (paramspresent < 2) {
		    /* If no datum parameters were imported from the OSR
		     * object then we should use the set specified by datumtrans */
		    char *params, *chosenparams = NULL;
		    int paramsets;

		    paramsets =
			GPJ_get_default_datum_params_by_name(datum, &params);

		    if (paramsets < 0)
			G_warning(_("Datum <%s> apparently recognised by GRASS but no parameters found. "
				   "You may want to look into this."), datum);
		    else if (datumtrans > paramsets) {

			G_warning(_("Invalid transformation number %d; valid range is 1 to %d. "
				   "Leaving datum transform parameters unspecified."),
				  datumtrans, paramsets);
			datumtrans = 0;
		    }

		    if (paramsets > 0) {
			struct gpj_datum_transform_list *list, *old;

			list = GPJ_get_datum_transform_by_name(datum);

			if (list != NULL) {
			    do {
				if (list->count == datumtrans)
				    chosenparams = G_store(list->params);
				old = list;
				list = list->next;
				GPJ_free_datum_transform(old);
			    } while (list != NULL);
			}
		    }

		    if (chosenparams != NULL) {
			char *paramkey, *paramvalue;

			paramkey = strtok(chosenparams, "=");
			paramvalue = chosenparams + strlen(paramkey) + 1;
			G_set_key_value(paramkey, paramvalue, *projinfo);
			G_free(chosenparams);
		    }

		    if (paramsets > 0)
			G_free(params);
		}

	    }
	    G_free(pszDatumName);
	}
    }

    /* -------------------------------------------------------------------- */
    /*   Determine an appropriate GRASS ellipsoid name if possible, or      */
    /*   else just put a and es values into PROJ_INFO                       */
    /* -------------------------------------------------------------------- */

    if ((datum != NULL) && (GPJ_get_datum_by_name(datum, &dstruct) > 0)) {
	/* Use ellps name associated with datum */
	G_set_key_value("ellps", dstruct.ellps, *projinfo);
	GPJ_free_datum(&dstruct);
	G_free(datum);
    }
    else {
	/* If we can't determine the ellipsoid from the datum, derive it
	 * directly from "SPHEROID" parameters in WKT */
	const char *pszSemiMajor = OSRGetAttrValue(hSRS, "SPHEROID", 1);
	const char *pszInvFlat = OSRGetAttrValue(hSRS, "SPHEROID", 2);

	if (pszSemiMajor != NULL && pszInvFlat != NULL) {
	    char *ellps = NULL;
	    struct ellps_list *list, *listhead;
	    double a = atof(pszSemiMajor), invflat = atof(pszInvFlat), flat;
	    double es;

	    /* Allow for incorrect WKT describing a sphere where InvFlat 
	     * is given as 0 rather than inf */
	    if (invflat > 0)
		flat = 1 / invflat;
	    else
		flat = 0;

	    es = flat * (2.0 - flat);

	    list = listhead = read_ellipsoid_table(0);

	    while (list != NULL) {
		/* Try and match a and es against GRASS defined ellipsoids;
		 * accept first one that matches. These numbers were found
		 * by trial and error and could be fine-tuned, or possibly
		 * a direct comparison of IEEE floating point values used. */
		if ((a == list->a || fabs(a - list->a) < 0.1 || fabs(1 - a / list->a) < 0.0000001) && ((es == 0 && list->es == 0) ||	/* Special case for sphere */
												       (invflat == list->rf || fabs(invflat - list->rf) < 0.0000001))) {
		    ellps = G_store(list->name);
		    break;
		}
		list = list->next;
	    }
	    if (listhead != NULL)
		free_ellps_list(listhead);

	    if (ellps == NULL) {
		/* If we weren't able to find a matching ellps name, set
		 * a and es values directly from WKT-derived data */
		char es_str[100];

		G_set_key_value("a", (char *)pszSemiMajor, *projinfo);

		sprintf(es_str, "%.16g", es);
		G_set_key_value("es", es_str, *projinfo);
	    }
	    else {
		/* else specify the GRASS ellps name for readability */
		G_set_key_value("ellps", ellps, *projinfo);
		G_free(ellps);
	    }

	}

    }

    /* -------------------------------------------------------------------- */
    /*      Finally append the detailed projection parameters to the end    */
    /* -------------------------------------------------------------------- */

    {
	int i;

	for (i = 0; i < temp_projinfo->nitems; i++)
	    G_set_key_value(temp_projinfo->key[i],
			    temp_projinfo->value[i], *projinfo);

	G_free_key_value(temp_projinfo);
    }

    G_free(pszProj4);

    /* -------------------------------------------------------------------- */
    /*      Set the linear units.                                           */
    /* -------------------------------------------------------------------- */
    *projunits = G_create_key_value();

    if (OSRIsGeographic(hSRS)) {
	/* We assume degrees ... someday we will be wrong! */
	G_set_key_value("unit", "degree", *projunits);
	G_set_key_value("units", "degrees", *projunits);
	G_set_key_value("meters", "1.0", *projunits);
    }
    else {
	char szFormatBuf[256];
	char *pszUnitsName = NULL;
	double dfToMeters;
	char *pszUnitsPlural, *pszStringEnd;

	dfToMeters = OSRGetLinearUnits(hSRS, &pszUnitsName);

	/* Workaround for the most obvious case when unit name is unknown */
	if ((G_strcasecmp(pszUnitsName, "unknown") == 0) &&
	    (dfToMeters == 1.))
	    G_asprintf(&pszUnitsName, "meter");

	G_set_key_value("unit", pszUnitsName, *projunits);

	/* Attempt at plural formation (WKT format doesn't store plural
	 * form of unit name) */
	pszUnitsPlural = G_malloc(strlen(pszUnitsName) + 3);
	strcpy(pszUnitsPlural, pszUnitsName);
	pszStringEnd = pszUnitsPlural + strlen(pszUnitsPlural) - 4;
	if (G_strcasecmp(pszStringEnd, "foot") == 0) {
	    /* Special case for foot - change two o's to e's */
	    pszStringEnd[1] = 'e';
	    pszStringEnd[2] = 'e';
	}
	else if (G_strcasecmp(pszStringEnd, "inch") == 0) {
	    /* Special case for inch - add es */
	    pszStringEnd[4] = 'e';
	    pszStringEnd[5] = 's';
	    pszStringEnd[6] = '\0';
	}
	else {
	    /* For anything else add an s at the end */
	    pszStringEnd[4] = 's';
	    pszStringEnd[5] = '\0';
	}

	G_set_key_value("units", pszUnitsPlural, *projunits);
	G_free(pszUnitsPlural);

	sprintf(szFormatBuf, "%.16g", dfToMeters);
	G_set_key_value("meters", szFormatBuf, *projunits);

    }

    return 2;

    /* -------------------------------------------------------------------- */
    /*      Fallback to returning an ungeoreferenced definition.            */
    /* -------------------------------------------------------------------- */
  default_to_xy:
    if (cellhd != NULL) {
	cellhd->proj = PROJECTION_XY;
	cellhd->zone = 0;
    }

    *projinfo = NULL;
    *projunits = NULL;

    return 1;
}
Beispiel #8
0
/*!
  \brief Create GDAL settings for given raster map

  \param name map name
  \param map_type map type (CELL, FCELL, DCELL)

  \return pointer to allocated GDAL_link structure
  \return NULL on error
*/
struct GDAL_link *Rast_create_gdal_link(const char *name,
					RASTER_MAP_TYPE map_type)
{
#ifdef GDAL_LINK
    char path[GPATH_MAX];
    GDALDriverH driver;
    double transform[6];
    struct GDAL_link *gdal;
    FILE *fp;
    struct Key_Value *key_val;
    char buf[32];

    Rast__init_window();

    Rast_init_gdal();

    if (!G_is_initialized(&st->initialized)) {
	read_gdal_options();
	st->projinfo = G_get_projinfo();
	st->projunits = G_get_projunits();
#if 0
	/* We cannot use GPJ_grass_to_wkt() here because that would create a
	   circular dependency between libgis and libgproj */
	if (st->projinfo && st->projunits)
	    st->srswkt = GPJ_grass_to_wkt(st->projinfo, st->projunits);
#endif
	G_initialize_done(&st->initialized);
    }

    gdal = G_calloc(1, sizeof(struct GDAL_link));

    sprintf(path, "%s/%s%s", st->opts.dir, name, st->opts.ext);
    gdal->filename = G_store(path);
    gdal->band_num = 1;
    gdal->hflip = 0;
    gdal->vflip = 0;

    switch (map_type) {
    case CELL_TYPE:
	switch (R__.nbytes) {
	case 1:
	    gdal->type = GDT_Byte;
	    gdal->null_val = (DCELL) 0xFF;
	    break;
	case 2:
	    gdal->type = GDT_UInt16;
	    gdal->null_val = (DCELL) 0xFFFF;
	    break;
	case 3:
	case 4:
	    gdal->type = GDT_Int32;
	    gdal->null_val = (DCELL) 0x80000000U;
	    break;
	}
	break;
    case FCELL_TYPE:
	gdal->type = GDT_Float32;
	Rast_set_d_null_value(&gdal->null_val, 1);
	break;
    case DCELL_TYPE:
	gdal->type = GDT_Float64;
	Rast_set_d_null_value(&gdal->null_val, 1);
	break;
    default:
	G_fatal_error(_("Invalid map type <%d>"), map_type);
	break;
    }

    driver = (*pGDALGetDriverByName) (st->opts.format);
    if (!driver)
	G_fatal_error(_("Unable to get <%s> driver"), st->opts.format);

    /* Does driver support GDALCreate ? */
    if ((*pGDALGetMetadataItem) (driver, GDAL_DCAP_CREATE, NULL)) {
	gdal->data =
	    (*pGDALCreate)(driver, gdal->filename,
			   R__.wr_window.cols, R__.wr_window.rows,
			   1, gdal->type, st->opts.options);
	if (!gdal->data)
	    G_fatal_error(_("Unable to create <%s> dataset using <%s> driver"),
			  name, st->opts.format);
    }
    /* If not - create MEM driver for intermediate dataset. 
     * Check if raster can be created at all (with GDALCreateCopy) */
    else if ((*pGDALGetMetadataItem) (driver, GDAL_DCAP_CREATECOPY, NULL)) {
	GDALDriverH mem_driver;

	G_message(_("Driver <%s> does not support direct writing. "
		    "Using MEM driver for intermediate dataset."),
		  st->opts.format);

	mem_driver = (*pGDALGetDriverByName) ("MEM");
	if (!mem_driver)
	    G_fatal_error(_("Unable to get in-memory raster driver"));

	gdal->data =
	    (*pGDALCreate)(mem_driver, "",
			   R__.wr_window.cols, R__.wr_window.rows,
			   1, gdal->type, st->opts.options);
	if (!gdal->data)
	    G_fatal_error(_("Unable to create <%s> dataset using memory driver"),
			  name);
    }
    else
	G_fatal_error(_("Driver <%s> does not support creating rasters"),
		      st->opts.format);

    gdal->band = (*pGDALGetRasterBand) (gdal->data, gdal->band_num);

    (*pGDALSetRasterNoDataValue) (gdal->band, gdal->null_val);

    /* Set Geo Transform  */
    transform[0] = R__.wr_window.west;
    transform[1] = R__.wr_window.ew_res;
    transform[2] = 0.0;
    transform[3] = R__.wr_window.north;
    transform[4] = 0.0;
    transform[5] = -R__.wr_window.ns_res;

    if ((*pGDALSetGeoTransform) (gdal->data, transform) >= CE_Failure)
	G_warning(_("Unable to set geo transform"));

    if (st->srswkt)
	if ((*pGDALSetProjection) (gdal->data, st->srswkt) == CE_Failure)
	    G_warning(_("Unable to set projection"));

    fp = G_fopen_new_misc("cell_misc", "gdal", name);
    if (!fp)
	G_fatal_error(_("Unable to create cell_misc/%s/gdal file"), name);

    key_val = G_create_key_value();

    G_set_key_value("file", gdal->filename, key_val);

    sprintf(buf, "%d", gdal->band_num);
    G_set_key_value("band", buf, key_val);

    sprintf(buf, "%.22g", gdal->null_val);
    G_set_key_value("null", buf, key_val);

    sprintf(buf, "%d", gdal->type);
    G_set_key_value("type", buf, key_val);

    if (G_fwrite_key_value(fp, key_val) < 0)
	G_fatal_error(_("Error writing cell_misc/%s/gdal file"), name);

    G_free_key_value(key_val);

    fclose(fp);

    return gdal;
#else
    return NULL;
#endif
}