📄 albers.c
字号:
/*Albers Equal-Area Conic Map Projectionby Paul Bamefrom "Graphics Gems", Academic Press, 1990*//* * Albers Conic Equal-Area Projection * Formulae taken from "Map Projections Used by the U.S. * Geological Survey" Bulletin #1532 * * Equation reference numbers and some variable names taken * from the reference. * To use, call albers setup() once and then albers_project() * for each coordinate pair of interest.*/#include "GGems.h" #include <stdio.h>#include <math.h>/* * This is the Clarke 1866 Earth spheroid data which is often * used by the USGS - there are other spheroids however - see the * book. */ /* * Earth radii in different units */#define CONST_EradiusKM (6378.2064) /* Kilometers */#define CONST_EradiusMI (CONST_EradiusKM/1.609) /* Miles */#define CONST_Ec (0.082271854) /* Eccentricity */#define CONST_Ecsq (0.006768658) /* Eccentricity squared *//* * To keep things simple, assume Earth radius is 1.0. Projected * coordinates (X and Y obtained from albers project ()) are * dimensionless and may be multiplied by any desired radius * to convert to desired units (usually Kilometers or Miles).*/#define CONST_Eradius 1.0/* Pre-computed variables */static double middlelon; /* longitude at center of map */static double bigC, cone_const, r0; /* See the reference */staticcalc_q_msq(lat, qp, msqp)double lat;double *qp;double *msqp;/* * Given latitude, calculate 'q' [eq 3-12] * if msqp is != NULL, m^2 [eq. 12-15].*/{ double s, c, es; s = sin(lat); es = s * CONST_Ec; *qp = (1.0 - CONST_Ecsq) * ((s / (1 - es * es))- (1 / (2 * CONST_Ec)) * log((1 - es) / (1 + es))); if (msqp != NULL) { c = cos(lat); *msqp = c * c/ (1 - es * es); }}albers_setup(southlat, northlat, originlon, originlat)double southlat, northlat;double originlon;double originlat;/* * Pre-compute a bunch of variables which are used by the * albers_project() * * southlat Southern latitude for Albers projection * northlat Northern latitude for Albers projection * originlon Longitude for origin of projected map * originlat Latitude for origin of projected map - * often (northlat + southlat) / 2*/{ double q1, q2, q0; double m1sq, m2sq; middlelon = originlon; calc_q_msq(southlat, &q1, &m1sq); calc_q_msq(northlat, &q2, &m2sq); calc_q_msq(originlat, &q0, (double *)NULL); cone_const = (m1sq - m2sq) / (q2 - q1); bigC = m1sq + cone_const * q1; r0 = CONST_Eradius * sqrt(bigC - cone_const *q0) / cone_const;}/***************************************************************/albers_project(lon, lat, xp, yp)double lon, lat;double *xp, *yp;/* * Project lon/lat (in radians) according to albers_setup and * return the results via xp, yp. Units of *xp and *yp are same * as the units used by CONST_Eradius.*/{ double q, r, theta; calc_q_msq(lat, &q, (double *)NULL); theta = cone_const * (lon -middlelon); r = CONST_Eradius * sqrt(bigC - cone_const * q) / cone_const; *xp = r * sin(theta); *yp = r0 - r * cos(theta);}#ifdef TESTPROGRAM/* * Test value from the USGS book. Because of roundoff, the * actual values are printed for visual inspection rather * than guessing what constitutes "close enough".*//* Convert a degrees, minutes pair to radians */#define DEG_MIN2RAD(degrees, minutes) \ ((double) ((degrees + minutes / 60.0) * M_PI / 180.0))#define Nlat DEG_MIN2RAD(29, 30) /* 29 degrees, 30' North Lat */#define Slat DEG_MIN2RAD(45, 30) #define Originlat DEG_MIN2RAD(23, 0) #define Originlon DEG_MIN2RAD(-96, 0) /* West longitude is negative */#define Testlat DEG_MIN2RAD(35, 0)#define Testlon DEG_MIN2RAD(-75, 0)#define TestX 1885.4727#define TestY 1535.9250main(){ int i; double x, y;/* Setup is also from USGS book test set */ albers_setup(Slat, Nlat, Originlon, Originlat); albers_project(Testlon, Testlat, &x, &y); printf("%.41f, %.41f =?= %.41f, %.41f/n", x * CONST_EradiusKM, y * CONST_EradiusKM, TestX, TestY);}#endif /* TESTPROGRAM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -