diff --git a/sw/ground_segment/cockpit/map2d.ml b/sw/ground_segment/cockpit/map2d.ml index 139f42ff99..1c64c4e6dc 100644 --- a/sw/ground_segment/cockpit/map2d.ml +++ b/sw/ground_segment/cockpit/map2d.ml @@ -3,7 +3,7 @@ * * Multi aircrafts map display * - * Copyright (C) 2004 CENA/ENAC, Pascal Brisset, Antoine Drouin + * Copyright (C) 2004-2006 ENAC, Pascal Brisset, Antoine Drouin * * This file is part of paparazzi. * @@ -52,6 +52,12 @@ let (//) = Filename.concat let default_path_srtm = home // "data" // "srtm" let default_path_maps = home // "data" // "maps" // "" let default_path_missions = home // "conf" +let gm_tiles_path = home // "var" // "maps" +let _ = + ignore (Sys.command (sprintf "mkdir -p %s" gm_tiles_path)) + +let google_maps_url = fun s -> sprintf "http://kh1.google.com/kh?n=404&v=3&t=%s" s + type aircraft = { @@ -117,17 +123,23 @@ let set_geo_ref = fun geomap wgs84 -> map_ref := Some utm_ref +exception Wget_failure of string -let file_of_url = fun ?(extension=".xml") url -> +let file_of_url = fun ?(extension=".xml") ?dest url -> if String.sub url 0 7 = "file://" then String.sub url 7 (String.length url - 7) else - let tmp_file = Filename.temp_file "fp" extension in + let tmp_file = + match dest with + Some s -> s + | None -> Filename.temp_file "fp" extension in let c = sprintf "wget --cache=off -O %s '%s'" tmp_file url in if Sys.command c = 0 then tmp_file - else - failwith c + else begin + Sys.remove tmp_file; + raise (Wget_failure url) + end let load_mission = fun color geomap xml -> let lat0 = float_attr xml "lat0" @@ -487,19 +499,40 @@ let en_of_wgs84 = fun geomap wgs84 -> {G.east=utm.utm_x -. utm_ref.utm_x; north=utm.utm_y -. utm_ref.utm_y} +let is_prefix = fun a b -> + String.length b >= String.length a && + a = String.sub b 0 (String.length a) + +let get_gm_from_cache = fun f -> + let files = Sys.readdir gm_tiles_path in + let rec loop = fun i -> + if i < Array.length files then + let fi = files.(i) in + if is_prefix (Filename.chop_extension fi) f then + let (sw, s) = Latlong.gm_lat_long_of_tile f in + (gm_tiles_path // fi, sw, s) + else + loop (i+1) + else + raise Not_found in + loop 0 + let rec get_gm_tile = fun wgs84 zoom -> if zoom < 10 then try let (gm_string, sw, scale) = Latlong.gm_tile_string wgs84 zoom in - let url = sprintf "http://kh1.google.com/kh?n=404&v=3&t=%s" gm_string in - let jpg_file = file_of_url ~extension:".jpg" url in - - (jpg_file, sw, scale) + try get_gm_from_cache gm_string with + Not_found -> + let url = google_maps_url gm_string in + let jpg_file = gm_tiles_path // (gm_string ^ ".jpg") in + ignore (file_of_url ~extension:".jpg" ~dest:jpg_file url); + (jpg_file, sw, scale) with (** Error, let's try a lower zoom *) - _ -> get_gm_tile wgs84 (zoom+1) + Wget_failure __ -> get_gm_tile wgs84 (zoom+1) else - failwith "get_gm_tile" + failwith "download_gm_tile" + diff --git a/sw/lib/ocaml/latlong.ml b/sw/lib/ocaml/latlong.ml index 1119dd27e4..091192202c 100644 --- a/sw/lib/ocaml/latlong.ml +++ b/sw/lib/ocaml/latlong.ml @@ -3,7 +3,7 @@ * * Geographic conversion utilities * - * Copyright (C) 2004 CENA/ENAC, Pascal Brisset, Antoine Drouin + * Copyright (C) 2004-2006 ENAC, Pascal Brisset, Antoine Drouin * * This file is part of paparazzi. * @@ -360,6 +360,22 @@ let (/.=) r x = r := !r /. x let (+.=) r x = r := !r +. x let (-.=) r x = r := !r -. x + +let gm_pos_and_scale = fun keyholeString tLat latHeight tLon lonWidth -> + let tmp_lat = fun l -> 2. *. atan (exp (l *. pi)) -. pi/.2. in + let bl_lat = tmp_lat tLat in + let tr_lat = tmp_lat (tLat +. latHeight) in + let bottom_left = {posn_lat = bl_lat ; posn_long = tLon *. pi} in + let top_right = {posn_lat = tr_lat; + posn_long = bottom_left.posn_long +. lonWidth *. pi } in + + let utm_bottom_left = utm_of WGS84 bottom_left + and utm_top_right = utm_of WGS84 top_right in +(*** Printf.fprintf stderr "%fx%f\n" (utm_bottom_left.utm_x -. utm_top_right.utm_x) (utm_bottom_left.utm_y -. utm_top_right.utm_y); ***) + let scale = utm_distance utm_bottom_left utm_top_right /. sqrt (2. *. 256.*.256.) in + (keyholeString, bottom_left, scale) + + (** Returns a keyhole string for a longitude (x), latitude (y), and zoom for Google Maps (http://www.ponies.me.uk/maps/GoogleTileUtils.java) *) let gm_tile_string = fun wgs84 zoom -> @@ -403,26 +419,14 @@ let gm_tile_string = fun wgs84 zoom -> end end done; - let tmp_lat = fun l -> 2. *. atan (exp (l *. pi)) -. pi/.2. in - let bl_lat = tmp_lat !tLat in - let tr_lat = tmp_lat (!tLat +. !latHeight) in - let bottom_left = {posn_lat = bl_lat ; posn_long = !tLon *. pi} in - let top_right = {posn_lat = tr_lat; - posn_long = bottom_left.posn_long +. !lonWidth *. pi } in - - let utm_bottom_left = utm_of WGS84 bottom_left - and utm_top_right = utm_of WGS84 top_right in - Printf.fprintf stderr "%fx%f\n" (utm_bottom_left.utm_x -. utm_top_right.utm_x) (utm_bottom_left.utm_y -. utm_top_right.utm_y); - let scale = utm_distance utm_bottom_left utm_top_right /. sqrt (2. *. 256.*.256.) in - (Buffer.contents keyholeString, bottom_left, scale) - + gm_pos_and_scale (Buffer.contents keyholeString) !tLat !latHeight !tLon !lonWidth let gm_lat_long_of_tile = fun keyholeStr -> assert(keyholeStr.[0] = 't'); let lon = ref (-180.) and lonWidth = ref 360. - and lat = ref (-1.) + and lat = ref (-1.) and latHeight = ref 2. in for i = 1 to String.length keyholeStr - 1 do @@ -439,11 +443,5 @@ let gm_lat_long_of_tile = fun keyholeStr -> | _ -> invalid_arg ("gm_get_lat_long " ^ keyholeStr) done; - latHeight +.= !lat; - latHeight := (2. *. atan (exp (pi *. !latHeight))) -. (pi /. 2.); - - lat := (2. *. atan (exp (pi *. !lat))) -. (pi /. 2.); - - latHeight -.= !lat; - lon := (Deg>>Rad)!lon; - { posn_lat = !lat; posn_long = !lon } + let (_, sw, s) = gm_pos_and_scale keyholeStr !lat !latHeight (!lon/.180.) (!lonWidth/.180.) in + (sw, s) diff --git a/sw/lib/ocaml/latlong.mli b/sw/lib/ocaml/latlong.mli index daccf2e17f..dd7c8e92c7 100644 --- a/sw/lib/ocaml/latlong.mli +++ b/sw/lib/ocaml/latlong.mli @@ -117,8 +117,8 @@ val of_string : string -> geographic val gm_tile_string : geographic -> int -> string * geographic * float (** [gm_tile_string geo zoom] Returns the string code designing the - Google Map tile *) + Google Map tile, coordinates of SW corner and scale *) -val gm_lat_long_of_tile : string -> geographic +val gm_lat_long_of_tile : string -> geographic * float (** [gm_lat_long_of_tile google_maps_tile_key] Returns the coordinates of the -South West corner of the given tile. *) +South West corner and the scale of the given tile. *)