Exemplo n.º 1
0
Arquivo: proj3.c Projeto: cran/GRASS
static int lookup(char *file, char *key, char *value, int len)
{
    char path[1024];

/*
    G__file_name (path, "", file, G_mapset());
    if (access(path,0) == 0)
	return G_lookup_key_value_from_file(path, key, value, len) == 1;
*/
    G__file_name (path, "", file, "PERMANENT");
    return G_lookup_key_value_from_file(path, key, value, len) == 1;
}
Exemplo n.º 2
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;
}