/* **************************************************************************** * * MODULE: g.proj * AUTHOR(S): Paul Kelly - paul-grass@stjohnspoint.co.uk * PURPOSE: Provides a means of reporting the contents of GRASS * projection information files and creating * new projection information files. * COPYRIGHT: (C) 2007 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ #include #include #include #include #include #include #include "local_proto.h" /** * * \brief Add or replace datum to the current co-ordinate system definition * * \param datum Use this datum (overrides any datum found in the * current co-ordinate system definition). * * \return 1 if a change was made, 0 if not. **/ 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; } /** * * \brief Add or replace datum transformation parameters to the current * co-ordinate system definition * * \param datumtrans Index number of parameter set to use, 0 to leave * unspecifed (or remove specific parameters, leaving just * the datum name), -1 to list the available parameter * sets for this datum and exit. * * \param force Force editing of parameters even if current co-ordinate * system already contains fully specified parameters. * * \return 1 if a change was made, 0 if not. **/ 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, ¶ms); 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; }