/** * vik_viewport_compute_bearing: * @vp: self object * @x1: screen coord * @y1: screen coord * @x2: screen coord * @y2: screen coord * @angle: bearing in Radian (output) * @baseangle: UTM base angle in Radian (output) * * Compute bearing. */ void vik_viewport_compute_bearing ( VikViewport *vp, gint x1, gint y1, gint x2, gint y2, gdouble *angle, gdouble *baseangle ) { gdouble len = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); gdouble dx = (x2-x1)/len*10; gdouble dy = (y2-y1)/len*10; *angle = atan2(dy, dx) + M_PI_2; if ( vik_viewport_get_drawmode ( vp ) == VIK_VIEWPORT_DRAWMODE_UTM) { VikCoord test; struct LatLon ll; struct UTM u; gint tx, ty; vik_viewport_screen_to_coord ( vp, x1, y1, &test ); vik_coord_to_latlon ( &test, &ll ); ll.lat += vik_viewport_get_ympp ( vp ) * vik_viewport_get_height ( vp ) / 11000.0; // about 11km per degree latitude a_coords_latlon_to_utm ( &ll, &u ); vik_coord_load_from_utm ( &test, VIK_VIEWPORT_DRAWMODE_UTM, &u ); vik_viewport_coord_to_screen ( vp, &test, &tx, &ty ); *baseangle = M_PI - atan2(tx-x1, ty-y1); *angle -= *baseangle; } if (*angle < 0) *angle += 2*M_PI; if (*angle > 2*M_PI) *angle -= 2*M_PI; }
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 ); }
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_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; } }
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; } }
/* called every time we update coordinates/zoom */ static void viewport_utm_zone_check ( VikViewport *vvp ) { if ( vvp->coord_mode == VIK_COORD_UTM ) { struct UTM utm; struct LatLon ll; a_coords_utm_to_latlon ( (struct UTM *) &(vvp->center), &ll ); a_coords_latlon_to_utm ( &ll, &utm ); if ( utm.zone != vvp->center.utm_zone ) *((struct UTM *)(&vvp->center)) = utm; /* misc. stuff so we don't have to check later */ vvp->utm_zone_width = viewport_utm_zone_width ( vvp ); vvp->one_utm_zone = ( vik_viewport_rightmost_zone(vvp) == vik_viewport_leftmost_zone(vvp) ); } }
// Align displayed UTM values with displayed Lat/Lon values static void align_utm2ll (VikGeorefLayer *vgl) { struct LatLon ll_tl = get_ll_tl (vgl); struct UTM utm; a_coords_latlon_to_utm ( &ll_tl, &utm ); gtk_spin_button_set_value ( GTK_SPIN_BUTTON(vgl->cw.ce_spin), utm.easting ); gtk_spin_button_set_value ( GTK_SPIN_BUTTON(vgl->cw.cn_spin), utm.northing ); gchar tmp_letter[2]; tmp_letter[0] = utm.letter; tmp_letter[1] = '\0'; gtk_entry_set_text ( GTK_ENTRY(vgl->cw.utm_letter_entry), tmp_letter ); gtk_spin_button_set_value ( GTK_SPIN_BUTTON(vgl->cw.utm_zone_spin), utm.zone ); }
static gdouble viewport_utm_zone_width ( VikViewport *vvp ) { if ( vvp->coord_mode == VIK_COORD_UTM ) { struct LatLon ll; /* get latitude of screen bottom */ struct UTM utm = *((struct UTM *)(vik_viewport_get_center ( vvp ))); utm.northing -= vvp -> height * vvp -> ympp / 2; a_coords_utm_to_latlon ( &utm, &ll ); /* boundary */ ll.lon = (utm.zone - 1) * 6 - 180 ; a_coords_latlon_to_utm ( &ll, &utm); return fabs ( utm.easting - EASTING_OFFSET ) * 2; } else return 0.0; }
void vik_coord_layer_draw ( VikCoordLayer *vcl, gpointer data ) { VikViewport *vp = (VikViewport *) data; if ( !vcl->gc ) { return; } if ( vik_viewport_get_coord_mode(vp) != VIK_COORD_UTM ) { VikCoord left, right, left2, right2; gdouble l, r, i, j; gint x1, y1, x2, y2, smod = 1, mmod = 1; gboolean mins = FALSE, secs = FALSE; GdkGC *dgc = vik_viewport_new_gc_from_color(vp, vcl->color, vcl->line_thickness); GdkGC *mgc = vik_viewport_new_gc_from_color(vp, vcl->color, MAX(vcl->line_thickness/2, 1)); GdkGC *sgc = vik_viewport_new_gc_from_color(vp, vcl->color, MAX(vcl->line_thickness/5, 1)); vik_viewport_screen_to_coord ( vp, 0, 0, &left ); vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp), 0, &right ); vik_viewport_screen_to_coord ( vp, 0, vik_viewport_get_height(vp), &left2 ); vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp), vik_viewport_get_height(vp), &right2 ); #define CLINE(gc, c1, c2) { \ vik_viewport_coord_to_screen(vp, (c1), &x1, &y1); \ vik_viewport_coord_to_screen(vp, (c2), &x2, &y2); \ vik_viewport_draw_line (vp, (gc), x1, y1, x2, y2); \ } l = left.east_west; r = right.east_west; if (60*fabs(l-r) < 4) { secs = TRUE; smod = MIN(6, (int)ceil(3600*fabs(l-r)/30.0)); } if (fabs(l-r) < 4) { mins = TRUE; mmod = MIN(6, (int)ceil(60*fabs(l-r)/30.0)); } for (i=floor(l*60); i<ceil(r*60); i+=1.0) { if (secs) { for (j=i*60+1; j<(i+1)*60; j+=1.0) { left.east_west = j/3600.0; left2.east_west = j/3600.0; if ((int)j % smod == 0) CLINE(sgc, &left, &left2); } } if (mins) { left.east_west = i/60.0; left2.east_west = i/60.0; if ((int)i % mmod == 0) CLINE(mgc, &left, &left2); } if ((int)i % 60 == 0) { left.east_west = i/60.0; left2.east_west = i/60.0; CLINE(dgc, &left, &left2); } } vik_viewport_screen_to_coord ( vp, 0, 0, &left ); l = left2.north_south; r = left.north_south; for (i=floor(l*60); i<ceil(r*60); i+=1.0) { if (secs) { for (j=i*60+1; j<(i+1)*60; j+=1.0) { left.north_south = j/3600.0; right.north_south = j/3600.0; if ((int)j % smod == 0) CLINE(sgc, &left, &right); } } if (mins) { left.north_south = i/60.0; right.north_south = i/60.0; if ((int)i % mmod == 0) CLINE(mgc, &left, &right); } if ((int)i % 60 == 0) { left.north_south = i/60.0; right.north_south = i/60.0; CLINE(dgc, &left, &right); } } #undef CLINE g_object_unref(dgc); g_object_unref(sgc); g_object_unref(mgc); return; } if ( vik_viewport_get_coord_mode(vp) == VIK_COORD_UTM ) { const struct UTM *center = (const struct UTM *)vik_viewport_get_center ( vp ); gdouble xmpp = vik_viewport_get_xmpp ( vp ), ympp = vik_viewport_get_ympp ( vp ); guint16 width = vik_viewport_get_width ( vp ), height = vik_viewport_get_height ( vp ); struct LatLon ll, ll2, min, max; double lon; int x1, x2; struct UTM utm; utm = *center; utm.northing = center->northing - ( ympp * height / 2 ); a_coords_utm_to_latlon ( &utm, &ll ); utm.northing = center->northing + ( ympp * height / 2 ); a_coords_utm_to_latlon ( &utm, &ll2 ); { /* find corner coords in lat/lon. start at whichever is less: top or bottom left lon. goto whichever more: top or bottom right lon */ struct LatLon topleft, topright, bottomleft, bottomright; struct UTM temp_utm; temp_utm = *center; temp_utm.easting -= (width/2)*xmpp; temp_utm.northing += (height/2)*ympp; a_coords_utm_to_latlon ( &temp_utm, &topleft ); temp_utm.easting += (width*xmpp); a_coords_utm_to_latlon ( &temp_utm, &topright ); temp_utm.northing -= (height*ympp); a_coords_utm_to_latlon ( &temp_utm, &bottomright ); temp_utm.easting -= (width*xmpp); a_coords_utm_to_latlon ( &temp_utm, &bottomleft ); min.lon = (topleft.lon < bottomleft.lon) ? topleft.lon : bottomleft.lon; max.lon = (topright.lon > bottomright.lon) ? topright.lon : bottomright.lon; min.lat = (bottomleft.lat < bottomright.lat) ? bottomleft.lat : bottomright.lat; max.lat = (topleft.lat > topright.lat) ? topleft.lat : topright.lat; } lon = ((double) ((long) ((min.lon)/ vcl->deg_inc))) * vcl->deg_inc; ll.lon = ll2.lon = lon; for (; ll.lon <= max.lon; ll.lon+=vcl->deg_inc, ll2.lon+=vcl->deg_inc ) { a_coords_latlon_to_utm ( &ll, &utm ); x1 = ( (utm.easting - center->easting) / xmpp ) + (width / 2); a_coords_latlon_to_utm ( &ll2, &utm ); x2 = ( (utm.easting - center->easting) / xmpp ) + (width / 2); vik_viewport_draw_line (vp, vcl->gc, x1, height, x2, 0); } utm = *center; utm.easting = center->easting - ( xmpp * width / 2 ); a_coords_utm_to_latlon ( &utm, &ll ); utm.easting = center->easting + ( xmpp * width / 2 ); a_coords_utm_to_latlon ( &utm, &ll2 ); /* really lat, just reusing a variable */ lon = ((double) ((long) ((min.lat)/ vcl->deg_inc))) * vcl->deg_inc; ll.lat = ll2.lat = lon; for (; ll.lat <= max.lat ; ll.lat+=vcl->deg_inc, ll2.lat+=vcl->deg_inc ) { a_coords_latlon_to_utm ( &ll, &utm ); x1 = (height / 2) - ( (utm.northing - center->northing) / ympp ); a_coords_latlon_to_utm ( &ll2, &utm ); x2 = (height / 2) - ( (utm.northing - center->northing) / ympp ); vik_viewport_draw_line (vp, vcl->gc, width, x2, 0, x1); } } }
static void vik_viewport_init ( VikViewport *vvp ) { viewport_init_ra(); struct UTM utm; struct LatLon ll; ll.lat = a_vik_get_default_lat(); ll.lon = a_vik_get_default_long(); gdouble zoom_x = 4.0; gdouble zoom_y = 4.0; if ( a_vik_get_startup_method ( ) == VIK_STARTUP_METHOD_LAST_LOCATION ) { gdouble lat, lon, dzoom; if ( a_settings_get_double ( VIK_SETTINGS_VIEW_LAST_LATITUDE, &lat ) ) ll.lat = lat; if ( a_settings_get_double ( VIK_SETTINGS_VIEW_LAST_LONGITUDE, &lon ) ) ll.lon = lon; if ( a_settings_get_double ( VIK_SETTINGS_VIEW_LAST_ZOOM_X, &dzoom ) ) zoom_x = dzoom; if ( a_settings_get_double ( VIK_SETTINGS_VIEW_LAST_ZOOM_Y, &dzoom ) ) zoom_y = dzoom; } a_coords_latlon_to_utm ( &ll, &utm ); vvp->xmpp = zoom_x; vvp->ympp = zoom_y; vvp->xmfactor = MERCATOR_FACTOR (vvp->xmpp); vvp->ymfactor = MERCATOR_FACTOR (vvp->ympp); vvp->coord_mode = VIK_COORD_LATLON; vvp->drawmode = VIK_VIEWPORT_DRAWMODE_MERCATOR; vvp->center.mode = VIK_COORD_LATLON; vvp->center.north_south = ll.lat; vvp->center.east_west = ll.lon; vvp->center.utm_zone = (int)utm.zone; vvp->center.utm_letter = utm.letter; vvp->scr_buffer = NULL; vvp->alpha_pixbuf = NULL; vvp->alpha_pixbuf_width = vvp->alpha_pixbuf_height = 0; vvp->utm_zone_width = 0.0; vvp->background_gc = NULL; vvp->highlight_gc = NULL; vvp->scale_bg_gc = NULL; vvp->copyrights = NULL; vvp->draw_scale = TRUE; vvp->draw_centermark = TRUE; vvp->draw_highlight = TRUE; vvp->trigger = NULL; vvp->snapshot_buffer = NULL; vvp->half_drawn = FALSE; g_signal_connect (G_OBJECT(vvp), "configure_event", G_CALLBACK(vik_viewport_configure), NULL); #if GTK_CHECK_VERSION (2,18,0) gtk_widget_set_can_focus ( GTK_WIDGET(vvp), TRUE ); #else GTK_WIDGET_SET_FLAGS(vvp, GTK_CAN_FOCUS); /* allow VVP to have focus -- enabling key events, etc */ #endif }