123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /*
- * G_calc_solar_position() calculates solar position parameters from
- * given position, date and time
- *
- * Written by Markus Neteler <neteler@geog.uni-hannover.de>
- * with kind help from Morten Hulden <morten untamo.net>
- *
- *----------------------------------------------------------------------------
- * using solpos.c with permission from
- * From rredc@nrel.gov Wed Mar 21 18:37:25 2001
- * Message-Id: <v04220805b6de9b1ad6ff@[192.174.39.30]>
- * Mary Anderberg
- * http://rredc.nrel.gov
- * National Renewable Energy Laboratory
- * 1617 Cole Boulevard
- * Golden, Colorado, USA 80401
- *
- * http://rredc.nrel.gov/solar/codes_algs/solpos/
- *
- * G_calc_solar_position is based on: soltest.c
- * by
- * Martin Rymes
- * National Renewable Energy Laboratory
- * 25 March 1998
- *----------------------------------------------------------------------------*/
- /* uncomment to get debug output */
- #include <math.h>
- #include <string.h>
- #include <stdio.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- #include <grass/gprojects.h>
- #include "solpos00.h"
- struct posdata pd, *pdat; /* declare solpos data struct and a pointer for it */
- long calc_solar_position(double longitude, double latitude, double timezone,
- int year, int month, int day, int hour, int minute,
- int second)
- {
- /* Note: this code is valid from year 1950 to 2050 (solpos restriction)
- - the algorithm will compensate for leap year.
- - longitude, latitude: decimal degree
- - timezone: DO NOT ADJUST FOR DAYLIGHT SAVINGS TIME.
- - timezone: negative for zones west of Greenwich
- - lat/long: east and north positive
- - the atmospheric refraction is calculated for 1013hPa, 15 degrees C
- - time: local time from your watch
- */
- long retval; /* to capture S_solpos return codes */
- struct Key_Value *in_proj_info, *in_unit_info; /* projection information of input map */
- struct pj_info iproj; /* input map proj parameters */
- struct pj_info oproj; /* output map proj parameters */
- extern struct Cell_head window;
- int inside;
- /* we don't like to run G_calc_solar_position in xy locations */
- if (window.proj == 0)
- G_fatal_error(_("Unable to calculate sun position in un-projected locations. "
- "Specify sunposition directly."));
- pdat = &pd; /* point to the structure for convenience */
- /* Initialize structure to default values. (Optional only if ALL input
- parameters are initialized in the calling code, which they are not
- in this example.) */
- S_init(pdat);
- /* check if given point is in current window */
- G_debug(1, "window.north: %f, window.south: %f\n", window.north,
- window.south);
- G_debug(1, "window.west: %f, window.east : %f\n", window.west,
- window.east);
-
- inside = 0;
- if (latitude >= window.south && latitude <= window.north &&
- longitude >= window.west && longitude <= window.east)
- inside = 1;
- if (!inside)
- G_warning(_("Specified point %f, %f outside of current region, "
- "is that intended? Anyway, it will be used."),
- longitude, latitude);
- /* if coordinates are not in lat/long format, transform them: */
- if ((G_projection() != PROJECTION_LL) && window.proj != 0) {
- G_debug(1, "Transforming input coordinates to lat/long (req. for solar position)");
-
- /* read current projection info */
- if ((in_proj_info = G_get_projinfo()) == NULL)
- G_fatal_error(_("Unable to get projection info of current location"));
- if ((in_unit_info = G_get_projunits()) == NULL)
- G_fatal_error(_("Unable to get projection units of current location"));
- if (pj_get_kv(&iproj, in_proj_info, in_unit_info) < 0)
- G_fatal_error(_("Unable to get projection key values of current location"));
-
- G_free_key_value(in_proj_info);
- G_free_key_value(in_unit_info);
- /* Try using pj_print_proj_params() instead of all this */
- G_debug(1, "Projection found in location:");
- G_debug(1, "IN: meter: %f zone: %i proj: %s (iproj struct)",
- iproj.meters, iproj.zone, iproj.proj);
- G_debug(1, "IN coord: longitude: %f, latitude: %f", longitude,
- latitude);
- /* see src/include/projects.h, struct PJconsts */
-
- /* set output projection to lat/long for solpos */
- oproj.zone = 0;
- oproj.meters = 1.;
- sprintf(oproj.proj, "ll");
- if ((oproj.pj = pj_latlong_from_proj(iproj.pj)) == NULL)
- G_fatal_error("Unable to set up lat/long projection parameters");
- /* XX do the transform
- * outx outy in_info out_info */
- if (pj_do_proj(&longitude, &latitude, &iproj, &oproj) < 0) {
- G_fatal_error(_("Error in pj_do_proj (projection of input coordinate pair)"));
- }
- G_debug(1, "Transformation to lat/long:");
- G_debug(1, "OUT: longitude: %f, latitude: %f", longitude,
- latitude);
- } /* transform if not LL */
- pdat->longitude = longitude; /* Note that latitude and longitude are */
- pdat->latitude = latitude; /* in DECIMAL DEGREES, not Deg/Min/Sec */
- pdat->timezone = timezone; /* DO NOT ADJUST FOR DAYLIGHT SAVINGS TIME. */
- pdat->year = year; /* The year */
- pdat->function &= ~S_DOY;
- pdat->month = month;
- pdat->day = day; /* the algorithm will compensate for leap year, so
- you just count days). S_solpos can be
- configured to accept day-of-the year */
- /* The time of day (STANDARD (GMT) time) */
- pdat->hour = hour;
- pdat->minute = minute;
- pdat->second = second;
- /* Let's assume that the temperature is 20 degrees C and that
- the pressure is 1013 millibars. The temperature is used for the
- atmospheric refraction correction, and the pressure is used for the
- refraction correction and the pressure-corrected airmass. */
- pdat->temp = 20.0;
- pdat->press = 1013.0;
- /* Finally, we will assume that you have a flat surface
- facing nowhere, tilted at latitude. */
- pdat->tilt = pdat->latitude; /* tilted at latitude */
- pdat->aspect = 180.0;
- /* perform the calculation */
- retval = S_solpos(pdat); /* S_solpos function call: returns long value */
- S_decode(retval, pdat); /* prints an error in case of problems */
- return retval;
- }
|