2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2005, Evan Battaglia <viking@greentorch.org>
6 * Some formulas or perhaps even code derived from GPSDrive
7 * GPSDrive Copyright (C) 2001-2004 Fritz Ganter <ganter@ganter.at>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <glib/gi18n.h>
39 #include "vikmapslayer.h"
43 static gboolean
expedia_coord_to_mapcoord ( const VikCoord
*src
, gdouble xzoom
, gdouble yzoom
, MapCoord
*dest
);
44 static void expedia_mapcoord_to_center_coord ( MapCoord
*src
, VikCoord
*dest
);
45 static int expedia_download ( MapCoord
*src
, const gchar
*dest_fn
);
47 static DownloadOptions expedia_options
= { NULL
, 2, a_check_map_file
};
50 VikMapsLayer_MapType map_type
= { 5, 0, 0, VIK_VIEWPORT_DRAWMODE_EXPEDIA
, expedia_coord_to_mapcoord
, expedia_mapcoord_to_center_coord
, expedia_download
};
51 maps_layer_register_type(_("Expedia Street Maps"), 5, &map_type
);
54 #define EXPEDIA_SITE "expedia.com"
55 #define MPP_MARGIN_OF_ERROR 0.01
56 #define DEGREES_TO_RADS 0.0174532925
57 #define HEIGHT_OF_LAT_DEGREE (111318.84502/ALTI_TO_MPP)
58 #define HEIGHT_OF_LAT_MINUTE (1855.3140837/ALTI_TO_MPP)
59 #define WIDTH_BUFFER 0
60 #define HEIGHT_BUFFER 25
61 #define REAL_WIDTH_BUFFER 1
62 #define REAL_HEIGHT_BUFFER 26
64 /* first buffer is to cut off the expedia/microsoft logo. Annoying little buggers ;) */
65 /* second is to allow for a 1-pixel overlap on each side. this is a good thing (tm) */
67 static const guint expedia_altis
[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 };
68 /* square this number to find out how many per square degree. */
69 static const gdouble expedia_altis_degree_freq
[] = { 120, 60, 30, 15, 8, 4, 2, 1, 1, 1 };
70 static const guint expedia_altis_count
= sizeof(expedia_altis
) / sizeof(expedia_altis
[0]);
72 gdouble
expedia_altis_freq ( gint alti
)
75 for ( i
= 0; i
< expedia_altis_count
; i
++ )
76 if ( expedia_altis
[i
] == alti
)
77 return expedia_altis_degree_freq
[ i
];
79 g_error ( _("Invalid expedia altitude") );
83 /* returns -1 if none of the above. */
84 gint
expedia_zoom_to_alti ( gdouble zoom
)
87 for ( i
= 0; i
< expedia_altis_count
; i
++ )
88 if ( fabs(expedia_altis
[i
] - zoom
) / zoom
< MPP_MARGIN_OF_ERROR
)
89 return expedia_altis
[i
];
94 gint expedia_pseudo_zone ( gint alti, gint x, gint y )
96 return (int) (x/expedia_altis_freq(alti)*180) + (int) (y/expedia_altis_freq(alti)*90);
100 void expedia_snip ( const gchar
*file
)
102 /* Load the pixbuf */
104 GdkPixbuf
*old
, *cropped
;
107 old
= gdk_pixbuf_new_from_file ( file
, &gx
);
110 g_warning ( _("Couldn't open EXPEDIA image file (right after successful download! Please report and delete image file!): %s"), gx
->message
);
115 width
= gdk_pixbuf_get_width ( old
);
116 height
= gdk_pixbuf_get_height ( old
);
118 cropped
= gdk_pixbuf_new_subpixbuf ( old
, WIDTH_BUFFER
, HEIGHT_BUFFER
,
119 width
- 2*WIDTH_BUFFER
, height
- 2*HEIGHT_BUFFER
);
121 gdk_pixbuf_save ( cropped
, file
, "png", &gx
, NULL
);
123 g_warning ( _("Couldn't save EXPEDIA image file (right after successful download! Please report and delete image file!): %s"), gx
->message
);
127 g_object_unref ( cropped
);
128 g_object_unref ( old
);
131 /* if degree_freeq = 60 -> nearest minute (in middle) */
132 /* everything starts at -90,-180 -> 0,0. then increments by (1/degree_freq) */
133 static gboolean
expedia_coord_to_mapcoord ( const VikCoord
*src
, gdouble xzoom
, gdouble yzoom
, MapCoord
*dest
)
137 g_assert ( src
->mode
== VIK_COORD_LATLON
);
139 if ( xzoom
!= yzoom
)
142 alti
= expedia_zoom_to_alti ( xzoom
);
146 dest
->x
= (int) (((src
->east_west
+180) * expedia_altis_freq(alti
))+0.5);
147 dest
->y
= (int) (((src
->north_south
+90) * expedia_altis_freq(alti
))+0.5);
148 /* + 0.5 to round off and not floor */
150 /* just to space out tiles on the filesystem */
157 void expedia_xy_to_latlon_middle ( gint alti
, gint x
, gint y
, struct LatLon
*ll
)
159 ll
->lon
= (((gdouble
)x
) / expedia_altis_freq(alti
)) - 180;
160 ll
->lat
= (((gdouble
)y
) / expedia_altis_freq(alti
)) - 90;
163 static void expedia_mapcoord_to_center_coord ( MapCoord
*src
, VikCoord
*dest
)
165 dest
->mode
= VIK_COORD_LATLON
;
166 dest
->east_west
= (((gdouble
)src
->x
) / expedia_altis_freq(src
->scale
)) - 180;
167 dest
->north_south
= (((gdouble
)src
->y
) / expedia_altis_freq(src
->scale
)) - 90;
170 static int expedia_download ( MapCoord
*src
, const gchar
*dest_fn
)
177 expedia_xy_to_latlon_middle ( src
->scale
, src
->x
, src
->y
, &ll
);
179 height
= HEIGHT_OF_LAT_DEGREE
/ expedia_altis_freq(src
->scale
) / (src
->scale
);
180 width
= height
* cos ( ll
.lat
* DEGREES_TO_RADS
);
182 height
+= 2*REAL_HEIGHT_BUFFER
;
183 width
+= 2*REAL_WIDTH_BUFFER
;
185 uri
= g_strdup_printf ( "/pub/agent.dll?qscr=mrdt&ID=3XNsF.&CenP=%lf,%lf&Lang=%s&Alti=%d&Size=%d,%d&Offs=0.000000,0.000000&BCheck&tpid=1",
186 ll
.lat
, ll
.lon
, (ll
.lon
> -30) ? "EUR0809" : "USA0409", src
->scale
, width
, height
);
188 if ((res
= a_http_download_get_url ( EXPEDIA_SITE
, uri
, dest_fn
, &expedia_options
)) == 0) /* All OK */
189 expedia_snip ( dest_fn
);