2 * This file is part of mapper
4 * Copyright (C) 2007 Kaj-Michael Lang
6 * Original Algorithms from misc web sites
8 * Default map data provided by http://www.openstreetmap.org/
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * Different Lat/Lon and related functions
27 * (conversion, distances, etc)
33 #include <glib/gi18n.h>
34 #include <glib/gstdio.h>
42 DEG_FORMAT_TEXT[DDPDDDDD] = "-dd.ddddd°";
43 DEG_FORMAT_TEXT[DD_MMPMMM] = "-dd°mm.mmm'";
44 DEG_FORMAT_TEXT[DD_MM_SSPS] = "-dd°mm'ss.s\"";
45 DEG_FORMAT_TEXT[DDPDDDDD_NSEW] = "dd.ddddd° S";
46 DEG_FORMAT_TEXT[DD_MMPMMM_NSEW] = "dd°mm.mmm' S";
47 DEG_FORMAT_TEXT[DD_MM_SSPS_NSEW] = "dd°mm'ss.s\" S";
49 UNITS_TEXT[UNITS_KM] = _("km");
50 UNITS_TEXT[UNITS_MI] = _("mi.");
51 UNITS_TEXT[UNITS_NM] = _("n.m.");
55 angle_diff(gfloat a, gfloat b)
69 magnitude(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
75 return sqrt((x*x)+(y*y));
79 distance_point_to_line(gdouble x, gdouble y, gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble *d)
84 lm=magnitude(x1,y1,x2,y2);
88 tmp=((x-x1)*(x2-x1))+((y-y1)*(y2-y1));
97 *d=magnitude(x,y, ix, iy);
103 * QuadTile calculation functions, from:
104 * http://trac.openstreetmap.org/browser/sites/rails_port/lib/quad_tile/quad_tile.h
107 xy2tile(guint x, guint y)
112 for (i=15;i>=0;i--) {
113 tile=(tile << 1) | ((x >> i) & 1);
114 tile=(tile << 1) | ((y >> i) & 1);
122 return round((lon + 180.0) * 65535.0 / 360.0);
128 return round((lat + 90.0) * 65535.0 / 180.0);
132 * Convert latitude to integerized+mercator projected value
135 lat2mp_int(gdouble lat)
137 return lat > 85.051128779 ? LATLON_MAX : lat < -85.051128779 ? LATLON_MIN :
138 lrint(log(tan(M_PI_4l+lat*M_PIl/360))/M_PIl*LATLON_MAX);
142 * Convert longitude to integerized+mercator projected value
145 lon2mp_int(gdouble lon)
147 return lrint(lon/180*LATLON_MAX);
151 mp_int2lon(gint32 lon)
153 return (gdouble)lon/LATLON_MAX*180;
157 mp_int2lat(gint32 lat)
163 * Quick distance calculation, (does not handle earth curvature, so use for quick non exact needs only)
166 calculate_idistance(gint lat1, gint lon1, gint lat2, gint lon2)
168 return lrint(sqrt((double)((lat1-lat2)*(lat1-lat2)+(lon1-lon2)*(lon1-lon2))));
172 calculate_ddistance(gint lat1, gint lon1, gint lat2, gint lon2)
174 return sqrt((double)((lat1-lat2)*(lat1-lat2)+(lon1-lon2)*(lon1-lon2)));
178 * Quick distance for comparing, skips the final square root
181 calculate_idistance_cmp(gint lat1, gint lon1, gint lat2, gint lon2)
183 return ((lat1-lat2)*(lat1-lat2)+(lon1-lon2)*(lon1-lon2));
187 * Calculate the distance between two lat/lon pairs.
188 * The distance is returned in kilometers.
192 calculate_distance(gdouble lat1, gdouble lon1, gdouble lat2, gdouble lon2)
194 gdouble dlat, dlon, slat, slon, a;
196 /* Convert to radians. */
197 lat1*=(M_PIl / 180.f);
198 lon1*=(M_PIl / 180.f);
199 lat2*=(M_PIl / 180.f);
200 lon2*=(M_PIl / 180.f);
205 slat=sin(dlat / 2.f);
206 slon=sin(dlon / 2.f);
208 a=(slat * slat) + (cos(lat1) * cos(lat2) * slon * slon);
210 return ((2.f * atan2(sqrt(a), sqrt(1.f - a))) * EARTH_RADIUS);
214 * Calculate course from lat1,lon1 to lat2,lon2
218 calculate_course_rad(gdouble lat1, gdouble lon1, gdouble lat2, gdouble lon2)
222 lat1*=(M_PIl / 180.f);
223 lon1*=(M_PIl / 180.f);
224 lat2*=(M_PIl / 180.f);
225 lon2*=(M_PIl / 180.f);
228 y=sin(dlon)*cos(lat2);
229 x=cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(dlon);
236 calculate_course(gdouble lat1, gdouble lon1, gdouble lat2, gdouble lon2)
240 c=calculate_course_rad(lat1, lon1, lat2, lon2);
248 deg_format(DegFormat degformat, gdouble coor, gchar * scoor, gchar neg_char, gchar pos_char)
251 gdouble acoor=fabs(coor);
255 g_sprintf(scoor, "%.5f°", coor);
258 g_sprintf(scoor, "%.5f° %c", acoor, coor < 0.f ? neg_char : pos_char);
261 g_sprintf(scoor, "%d°%06.3f'", (int)coor, (acoor - (int)acoor) * 60.0);
264 g_sprintf(scoor, "%d°%06.3f' %c", (int)acoor, (acoor - (int)acoor) * 60.0, coor < 0.f ? neg_char : pos_char);
267 min = (acoor - (int)acoor) * 60.0;
268 g_sprintf(scoor, "%d°%02d'%04.1f\"", (int)coor, (int)min, ((min - (int)min) * 60.0));
270 case DD_MM_SSPS_NSEW:
271 min = (acoor - (int)acoor) * 60.0;
272 g_sprintf(scoor, "%d°%02d'%04.1f\" %c", (int)acoor, (int)min, ((min - (int)min) * 60.0), coor < 0.f ? neg_char : pos_char);
275 g_return_if_reached();