void vik_viewport_screen_to_coord ( VikViewport *vvp, int x, int y, VikCoord *coord ) { g_return_if_fail ( vvp != NULL ); if ( vvp->coord_mode == VIK_COORD_UTM ) { int zone_delta; struct UTM *utm = (struct UTM *) coord; coord->mode = VIK_COORD_UTM; utm->zone = vvp->center.utm_zone; utm->letter = vvp->center.utm_letter; utm->easting = ( ( x - ( vvp->width_2) ) * vvp->xmpp ) + vvp->center.east_west; zone_delta = floor( (utm->easting - EASTING_OFFSET ) / vvp->utm_zone_width + 0.5 ); utm->zone += zone_delta; utm->easting -= zone_delta * vvp->utm_zone_width; utm->northing = ( ( ( vvp->height_2) - y ) * vvp->ympp ) + vvp->center.north_south; } else if ( vvp->coord_mode == VIK_COORD_LATLON ) { coord->mode = VIK_COORD_LATLON; if ( vvp->drawmode == VIK_VIEWPORT_DRAWMODE_LATLON ) { coord->east_west = vvp->center.east_west + (180.0 * vvp->xmpp / 65536 / 256 * (x - vvp->width_2)); coord->north_south = vvp->center.north_south + (180.0 * vvp->ympp / 65536 / 256 * (vvp->height_2 - y)); } else if ( vvp->drawmode == VIK_VIEWPORT_DRAWMODE_EXPEDIA ) calcxy_rev(&(coord->east_west), &(coord->north_south), x, y, vvp->center.east_west, vvp->center.north_south, vvp->xmpp * ALTI_TO_MPP, vvp->ympp * ALTI_TO_MPP, vvp->width_2, vvp->height_2); else if ( vvp->drawmode == VIK_VIEWPORT_DRAWMODE_MERCATOR ) { /* This isn't called with a high frequently so less need to optimize */ coord->east_west = vvp->center.east_west + (180.0 * vvp->xmpp / 65536 / 256 * (x - vvp->width_2)); coord->north_south = DEMERCLAT ( MERCLAT(vvp->center.north_south) + (180.0 * vvp->ympp / 65536 / 256 * (vvp->height_2 - y)) ); } } }
/* * Since this function is used for every drawn trackpoint - it can get called alot * Thus x & y position factors are calculated once on zoom changes, * avoiding the need to do it here all the time. * For good measure the half width and height values are also pre calculated too. */ void vik_viewport_coord_to_screen ( VikViewport *vvp, const VikCoord *coord, int *x, int *y ) { static VikCoord tmp; g_return_if_fail ( vvp != NULL ); if ( coord->mode != vvp->coord_mode ) { g_warning ( "Have to convert in vik_viewport_coord_to_screen! This should never happen!"); vik_coord_copy_convert ( coord, vvp->coord_mode, &tmp ); coord = &tmp; } if ( vvp->coord_mode == VIK_COORD_UTM ) { struct UTM *center = (struct UTM *) &(vvp->center); struct UTM *utm = (struct UTM *) coord; if ( center->zone != utm->zone && vvp->one_utm_zone ) { *x = *y = VIK_VIEWPORT_UTM_WRONG_ZONE; return; } *x = ( (utm->easting - center->easting) / vvp->xmpp ) + (vvp->width_2) - (center->zone - utm->zone ) * vvp->utm_zone_width / vvp->xmpp; *y = (vvp->height_2) - ( (utm->northing - center->northing) / vvp->ympp ); } else if ( vvp->coord_mode == VIK_COORD_LATLON ) { struct LatLon *center = (struct LatLon *) &(vvp->center); struct LatLon *ll = (struct LatLon *) coord; double xx,yy; if ( vvp->drawmode == VIK_VIEWPORT_DRAWMODE_LATLON ) { *x = vvp->width_2 + ( MERCATOR_FACTOR(vvp->xmpp) * (ll->lon - center->lon) ); *y = vvp->height_2 + ( MERCATOR_FACTOR(vvp->ympp) * (center->lat - ll->lat) ); } else if ( vvp->drawmode == VIK_VIEWPORT_DRAWMODE_EXPEDIA ) { calcxy ( &xx, &yy, center->lon, center->lat, ll->lon, ll->lat, vvp->xmpp * ALTI_TO_MPP, vvp->ympp * ALTI_TO_MPP, vvp->width_2, vvp->height_2 ); *x = xx; *y = yy; } else if ( vvp->drawmode == VIK_VIEWPORT_DRAWMODE_MERCATOR ) { *x = vvp->width_2 + ( MERCATOR_FACTOR(vvp->xmpp) * (ll->lon - center->lon) ); *y = vvp->height_2 + ( MERCATOR_FACTOR(vvp->ympp) * ( MERCLAT(center->lat) - MERCLAT(ll->lat) ) ); } } }
static gboolean _coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest ) { g_assert ( src->mode == VIK_COORD_LATLON ); if ( xzoom != yzoom ) return FALSE; dest->scale = map_utils_mpp_to_scale ( xzoom ); if ( dest->scale == 255 ) return FALSE; dest->x = (src->east_west + 180) / 360 * VIK_GZ(17) / xzoom; dest->y = (180 - MERCLAT(src->north_south)) / 360 * VIK_GZ(17) / xzoom; dest->z = 0; return TRUE; }