/* * viking -- GPS Data and Topo Analyzer, Explorer, and Manager * * Copyright (C) 2003-2005, Evan Battaglia * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "coords.h" #include "vikcoord.h" /* all coord operations MUST BE ABSTRACTED!!! */ void vik_coord_convert(VikCoord *coord, VikCoordMode dest_mode) { VikCoord tmp; if ( coord->mode != dest_mode ) { if ( dest_mode == VIK_COORD_LATLON ) { a_coords_utm_to_latlon ( (struct UTM *)coord, (struct LatLon *)&tmp ); *((struct LatLon *)coord) = *((struct LatLon *)&tmp); } else { a_coords_latlon_to_utm ( (struct LatLon *)coord, (struct UTM *)&tmp ); *((struct UTM *)coord) = *((struct UTM *)&tmp); } coord->mode = dest_mode; } } void vik_coord_copy_convert(const VikCoord *coord, VikCoordMode dest_mode, VikCoord *dest) { if ( coord->mode == dest_mode ) { *dest = *coord; } else { if ( dest_mode == VIK_COORD_LATLON ) a_coords_utm_to_latlon ( (struct UTM *)coord, (struct LatLon *)dest ); else a_coords_latlon_to_utm ( (struct LatLon *)coord, (struct UTM *)dest ); dest->mode = dest_mode; } } static gdouble vik_coord_diff_safe(const VikCoord *c1, const VikCoord *c2) { struct LatLon a, b; vik_coord_to_latlon ( c1, &a ); vik_coord_to_latlon ( c2, &b ); return a_coords_latlon_diff ( &a, &b ); } gdouble vik_coord_diff(const VikCoord *c1, const VikCoord *c2) { if ( c1->mode == c2->mode ) return vik_coord_diff_safe ( c1, c2 ); if ( c1->mode == VIK_COORD_UTM ) return a_coords_utm_diff ( (const struct UTM *) c1, (const struct UTM *) c2 ); else return a_coords_latlon_diff ( (const struct LatLon *) c1, (const struct LatLon *) c2 ); } void vik_coord_load_from_latlon ( VikCoord *coord, VikCoordMode mode, const struct LatLon *ll ) { if ( mode == VIK_COORD_LATLON ) *((struct LatLon *)coord) = *ll; else a_coords_latlon_to_utm ( ll, (struct UTM *) coord ); coord->mode = mode; } void vik_coord_load_from_utm ( VikCoord *coord, VikCoordMode mode, const struct UTM *utm ) { if ( mode == VIK_COORD_UTM ) *((struct UTM *)coord) = *utm; else a_coords_utm_to_latlon ( utm, (struct LatLon *) coord ); coord->mode = mode; } void vik_coord_to_latlon ( const VikCoord *coord, struct LatLon *dest ) { if ( coord->mode == VIK_COORD_LATLON ) *dest = *((const struct LatLon *)coord); else a_coords_utm_to_latlon ( (const struct UTM *) coord, dest ); } void vik_coord_to_utm ( const VikCoord *coord, struct UTM *dest ) { if ( coord->mode == VIK_COORD_UTM ) *dest = *((const struct UTM *)coord); else a_coords_latlon_to_utm ( (const struct LatLon *) coord, dest ); } gboolean vik_coord_equals ( const VikCoord *coord1, const VikCoord *coord2 ) { if ( coord1->mode != coord2->mode ) return FALSE; if ( coord1->mode == VIK_COORD_LATLON ) return coord1->north_south == coord2->north_south && coord1->east_west == coord2->east_west; else /* VIK_COORD_UTM */ return coord1->utm_zone == coord2->utm_zone && coord1->north_south == coord2->north_south && coord1->east_west == coord2->east_west; } static void get_north_west(struct LatLon *center, struct LatLon *dist, struct LatLon *nw) { nw->lat = center->lat + dist->lat; nw->lon = center->lon - dist->lon; if (nw->lon < -180) nw->lon += 360.0; if (nw->lat > 90.0) { /* over north pole */ nw->lat = 180 - nw->lat; nw->lon = nw->lon - 180; } } static void get_south_east(struct LatLon *center, struct LatLon *dist, struct LatLon *se) { se->lat = center->lat - dist->lat; se->lon = center->lon + dist->lon; if (se->lon > 180.0) se->lon -= 360.0; if (se->lat < -90.0) { /* over south pole */ se->lat += 180; se->lon = se->lon - 180; } } void vik_coord_set_area(const VikCoord *coord, const struct LatLon *wh, VikCoord *tl, VikCoord *br) { struct LatLon center, nw, se; struct LatLon dist; dist.lat = wh->lat/2; dist.lon = wh->lon/2; vik_coord_to_latlon(coord, ¢er); get_north_west(¢er, &dist, &nw); get_south_east(¢er, &dist, &se); *((struct LatLon *)tl) = nw; *((struct LatLon *)br) = se; tl->mode = br->mode = VIK_COORD_LATLON; } gboolean vik_coord_inside(const VikCoord *coord, const VikCoord *tl, const VikCoord *br) { struct LatLon ll, tl_ll, br_ll; vik_coord_to_latlon(coord, &ll); vik_coord_to_latlon(tl, &tl_ll); vik_coord_to_latlon(br, &br_ll); if ((ll.lat > tl_ll.lat) || (ll.lon < tl_ll.lon)) return FALSE; if ((ll.lat < br_ll.lat) || (ll.lon > br_ll.lon)) return FALSE; return TRUE; }