summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan McIntosh <ian_mcintosh@linuxadvocate.org>2005-10-10 02:07:36 +0000
committerIan McIntosh <ian_mcintosh@linuxadvocate.org>2005-10-10 02:07:36 +0000
commit7ae9d377f0993dfc08a3503b4e91c0bfb45ea283 (patch)
tree54256cf5528caa614ac5ed8d77e001e27a7d09e9 /src
parent143bad89cfacba80262ea4ce075dcba732139847 (diff)
Adjusting of zoom scales and styles.
Properly insert LOD3 table. Rivers only exist on LOD0. Add constant for middle mouse button. Make zoomscale widget instant. Middle mouse button drags map regardless of tool. Improvement of some web map URLs. Add zoomscale utility functions.
Diffstat (limited to 'src')
-rw-r--r--src/db.c7
-rw-r--r--src/import_tiger.c2
-rw-r--r--src/main.h1
-rw-r--r--src/mainwindow.c91
-rw-r--r--src/map.c130
-rw-r--r--src/map.h12
-rw-r--r--src/map_draw_gdk.c8
-rw-r--r--src/map_math.c2
-rw-r--r--src/map_style.c33
-rw-r--r--src/map_tilemanager.c4
-rw-r--r--src/searchwindow.c4
-rw-r--r--src/tooltipwindow.c3
-rw-r--r--src/util.c68
-rw-r--r--src/util.h8
14 files changed, 261 insertions, 112 deletions
diff --git a/src/db.c b/src/db.c
index 70448f6..b34ecf3 100644
--- a/src/db.c
+++ b/src/db.c
@@ -608,6 +608,13 @@ void db_create_tables()
" RoadNameID INT3 UNSIGNED NOT NULL," // NOTE: 3 bytes
" Coordinates point NOT NULL,"
" SPATIAL KEY (Coordinates));", NULL);
+
+ db_query(
+ "CREATE TABLE IF NOT EXISTS Road3("
+ " TypeID INT1 UNSIGNED NOT NULL,"
+ " RoadNameID INT3 UNSIGNED NOT NULL," // NOTE: 3 bytes
+ " Coordinates point NOT NULL,"
+ " SPATIAL KEY (Coordinates));", NULL);
// RoadName
db_query(
diff --git a/src/import_tiger.c b/src/import_tiger.c
index 71887b3..06abd7d 100644
--- a/src/import_tiger.c
+++ b/src/import_tiger.c
@@ -181,7 +181,7 @@ gint g_aaObjectTypeDetailAtLODs[MAP_NUM_OBJECT_TYPES][MAP_NUM_LEVELS_OF_DETAIL]
{0,0,0,0}, // (unused)
{1,8,0,0}, // rail
{1,1,1,1}, // park
- {2,16,0,0}, // river
+ {2,0,0,0}, // river
{1,1,1,1}, // lake
{1,1,1,1}, // misc area
{1,1,1,1}, // urban area
diff --git a/src/main.h b/src/main.h
index 15c19f8..bf7e5e7 100644
--- a/src/main.h
+++ b/src/main.h
@@ -32,6 +32,7 @@
#define USE_GFREELIST
#define MOUSE_BUTTON_LEFT (1) // These are X/GDK/GTK numbers, now with names.
+#define MOUSE_BUTTON_MIDDLE (2)
#define MOUSE_BUTTON_RIGHT (3)
//#define ENABLE_TIMING
diff --git a/src/mainwindow.c b/src/mainwindow.c
index 51e1fb8..68ddd51 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -327,15 +327,23 @@ void mainwindow_init_add_web_maps_menu_items()
typedef struct { gchar* pszName; gchar* pszURL; } web_map_url_t;
web_map_url_t aWebMapURLs[] = {
- {"Google Maps", "http://maps.google.com/?ll={LAT}%2C{LON}&z={ZOOM_NUMBER_REVERSED}"},
- {"Google Maps Satellite", "http://maps.google.com/?ll={LAT}%2C{LON}&t=k&z={ZOOM_NUMBER_REVERSED}"},
- {"Google Maps Hybrid", "http://maps.google.com/?ll={LAT}%2C{LON}&t=h&z={ZOOM_NUMBER_REVERSED}"},
+ {"Google Maps Roads", "http://maps.google.com/?ll={LAT}%2C{LON}&spn={LAT_SPAN}%2C{LON_SPAN}"},
+ {"Google Maps Satellite", "http://maps.google.com/?ll={LAT}%2C{LON}&spn={LAT_SPAN}%2C{LON_SPAN}&t=k"}, // t=k means sat
+ {"Google Maps Hybrid", "http://maps.google.com/?ll={LAT}%2C{LON}&spn={LAT_SPAN}%2C{LON_SPAN}&t=h"}, // t=h means hybrid
// XXX: how do we specify zoom level in YMaps URL?
{"Yahoo! Maps", "http://maps.yahoo.com/maps_result?lat={LAT}&lon={LON}"},
+
+ {"MSN Maps", "http://maps.msn.com/map.aspx?C={LAT}%2C{LON}&S=800%2C740&alts1={ALTITUDE_MILES}"},
+
+ {"MSN Virtual Earth Roads", "http://virtualearth.msn.com/default.aspx?v=1&cp={LAT}|{LON}&lvl={ZOOM_1_TO_19}&style=r"},
+ {"MSN Virtual Earth Satellite", "http://virtualearth.msn.com/default.aspx?v=1&cp={LAT}|{LON}&lvl={ZOOM_1_TO_19}&style=a"},
+ {"MSN Virtual Earth Hybrid", "http://virtualearth.msn.com/default.aspx?v=1&cp={LAT}|{LON}&lvl={ZOOM_1_TO_19}&style=h"},
+
+ // Mapquest doesn't seem to accept LAT/LON params
- // XXX: multimap zoomscales may not match ours
- //{"Multimap", "http://www.multimap.com/p/browse.cgi?lon={LON}&lat={LAT}&scale={ZOOM_SCALE}"},
+ // NOTE: multimap zoomscales may not match ours, so we're just hardcoding one for now
+ {"Multimap", "http://www.multimap.com/p/browse.cgi?lon={LON}&lat={LAT}&scale=10000"},
};
// Google Maps Directions:
// DIRS: http://maps.google.com/maps?saddr=42.358333+-71.060278+(boston)&daddr=40.714167+-74.006389+(new+york)
@@ -392,6 +400,9 @@ void mainwindow_init(GladeXML* pGladeXML)
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pZoomOutMenuItem, GTK_MENU_ITEM, "zoomoutmenuitem");
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pZoomScale, GTK_HSCALE, "zoomscale");
+ // make it instant-change using our hacky callback
+ g_signal_connect(G_OBJECT(g_MainWindow.pZoomScale), "change-value", G_CALLBACK(util_gtk_range_instant_set_on_value_changing_callback), NULL);
+
// Labels
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pPositionLabel, GTK_LABEL, "positionlabel");
GLADE_LINK_WIDGET(pGladeXML, g_MainWindow.pZoomScaleLabel, GTK_LABEL, "zoomscalelabel");
@@ -771,6 +782,7 @@ void mainwindow_set_zoomlevel(gint nZoomLevel)
// g_signal_handlers_unblock_by_func(g_MainWindow.pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
mainwindow_update_zoom_buttons();
+// g_print("nZoomLevel = %d, height = %f miles\n", nZoomLevel, map_get_altitude(g_MainWindow.pMap, UNIT_MILES));
}
// the range slider changed value
@@ -779,14 +791,16 @@ void mainwindow_on_zoomscale_value_changed(GtkRange *range, gpointer user_data)
gdouble fValue = gtk_range_get_value(range);
gint16 nValue = (gint16)fValue;
- // update GUI
- mainwindow_set_zoomlevel(nValue);
+ if(map_get_zoomlevel(g_MainWindow.pMap) != nValue) {
+ // update GUI
+ mainwindow_set_zoomlevel(nValue);
- // also redraw immediately and add history item
- mainwindow_draw_map(DRAWFLAG_GEOMETRY);
- mainwindow_set_draw_pretty_timeout(DRAW_PRETTY_ZOOM_TIMEOUT_MS);
+ // also redraw immediately and add history item
+ mainwindow_draw_map(DRAWFLAG_GEOMETRY);
+ mainwindow_set_draw_pretty_timeout(DRAW_PRETTY_ZOOM_TIMEOUT_MS);
- mainwindow_add_history();
+ mainwindow_add_history();
+ }
}
//
@@ -1095,6 +1109,8 @@ static gboolean mainwindow_on_mouse_button_click(GtkWidget* w, GdkEventButton *e
}
if(g_MainWindow.bDrawingZoomRect == TRUE) {
+ // Finished drawing a zoom-rect. Zoom in (if the rect was past the minimum threshold).
+
if((map_screenrect_width(&(g_MainWindow.rcZoomRect)) > ZOOM_TOOL_THRESHOLD) && (map_screenrect_height(&(g_MainWindow.rcZoomRect)) > ZOOM_TOOL_THRESHOLD)) {
map_zoom_to_screenrect(g_MainWindow.pMap, &(g_MainWindow.rcZoomRect));
@@ -1110,13 +1126,13 @@ static gboolean mainwindow_on_mouse_button_click(GtkWidget* w, GdkEventButton *e
// Since we're not redrawing the map, we need to erase the selection rectangle
mainwindow_draw_xor_rect(&(g_MainWindow.rcZoomRect));
}
-
// all done
g_MainWindow.bDrawingZoomRect = FALSE;
}
- // end scrolling, if active
if(g_MainWindow.bScrolling == TRUE) {
+ // End scrolling
+
// NOTE: don't restore cursor (mouse could *still* be over screen edge)
g_MainWindow.bScrolling = FALSE;
@@ -1200,6 +1216,29 @@ static gboolean mainwindow_on_mouse_button_click(GtkWidget* w, GdkEventButton *e
//gtk_menu_popup(pMenu, NULL, NULL, NULL, NULL, event->button, event->time);
}
}
+ else if(event->button == MOUSE_BUTTON_MIDDLE) {
+ if(event->type == GDK_BUTTON_PRESS) {
+ g_MainWindow.bMouseDragging = TRUE;
+ g_MainWindow.bMouseDragMovement = FALSE;
+ g_MainWindow.ptClickLocation.nX = nX;
+ g_MainWindow.ptClickLocation.nY = nY;
+ }
+ else if(event->type == GDK_BUTTON_RELEASE) {
+ if(g_MainWindow.bMouseDragging == TRUE) {
+ // restore cursor
+ GdkCursor* pCursor = gdk_cursor_new(GDK_LEFT_PTR);
+ gdk_window_set_cursor(GTK_WIDGET(g_MainWindow.pDrawingArea)->window, pCursor);
+ gdk_cursor_unref(pCursor);
+
+ g_MainWindow.bMouseDragging = FALSE;
+ if(g_MainWindow.bMouseDragMovement) {
+ mainwindow_cancel_draw_pretty_timeout();
+ mainwindow_draw_map(DRAWFLAG_ALL);
+ mainwindow_add_history();
+ }
+ }
+ }
+ }
map_hittest_maphit_free(g_MainWindow.pMap, pHitStruct);
return TRUE;
}
@@ -1863,19 +1902,31 @@ static void mainwindow_on_web_url_clicked(GtkWidget *_unused, gchar* pszURLPatte
static util_str_replace_t apszReplacements[] = {
{"{LAT}", NULL},
{"{LON}", NULL},
- {"{ZOOM_NUMBER}", NULL},
- {"{ZOOM_NUMBER_REVERSED}", NULL},
- {"{ZOOM_SCALE}", NULL}
+ {"{LAT_SPAN}", NULL},
+ {"{LON_SPAN}", NULL},
+ {"{ZOOM_SCALE}", NULL},
+ {"{ZOOM_1_TO_10}", NULL},
+ {"{ZOOM_1_TO_19}", NULL},
+ {"{ALTITUDE_MILES}", NULL},
};
mappoint_t ptCenter;
map_get_centerpoint(g_MainWindow.pMap, &ptCenter);
+ maprect_t rcVisible;
+ map_get_visible_maprect(g_MainWindow.pMap, &rcVisible);
+
+// nAltitudeMiles = map_get_altitude(
+
+ gdouble fZoomPercent = util_get_percent_of_range(map_get_zoomlevel(g_MainWindow.pMap), MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL);
- apszReplacements[0].pszReplace = g_strdup_printf("%f", ptCenter.fLatitude);
- apszReplacements[1].pszReplace = g_strdup_printf("%f", ptCenter.fLongitude);
- apszReplacements[2].pszReplace = g_strdup_printf("%d", map_get_zoomlevel(g_MainWindow.pMap));
- apszReplacements[3].pszReplace = g_strdup_printf("%d", MAX_ZOOM_LEVEL - map_get_zoomlevel(g_MainWindow.pMap));
+ apszReplacements[0].pszReplace = util_format_gdouble(ptCenter.fLatitude);
+ apszReplacements[1].pszReplace = util_format_gdouble(ptCenter.fLongitude);
+ apszReplacements[2].pszReplace = g_strdup_printf("%f", rcVisible.B.fLatitude - rcVisible.A.fLatitude);
+ apszReplacements[3].pszReplace = g_strdup_printf("%f", rcVisible.B.fLongitude - rcVisible.A.fLongitude);
apszReplacements[4].pszReplace = g_strdup_printf("%d", map_get_zoomlevel_scale(g_MainWindow.pMap));
+ apszReplacements[5].pszReplace = g_strdup_printf("%d", util_get_int_at_percent_of_range(fZoomPercent, 1, 10));
+ apszReplacements[6].pszReplace = g_strdup_printf("%d", util_get_int_at_percent_of_range(fZoomPercent, 1, 19));
+// apszReplacements[7].pszReplace = g_strdup_printf("%d", nAltitudeMiles);
//
gchar* pszURL = util_str_replace_many(pszURLPattern, apszReplacements, G_N_ELEMENTS(apszReplacements));
diff --git a/src/map.c b/src/map.c
index 23ffcb3..97e7ccf 100644
--- a/src/map.c
+++ b/src/map.c
@@ -72,66 +72,63 @@ static void map_init_location_hash(map_t* pMap);
static void map_store_location(map_t* pMap, location_t* pLocation, gint nLocationSetID);
static void map_data_clear(map_t* pMap);
-void map_get_render_metrics(map_t* pMap, rendermetrics_t* pMetrics);
+void map_get_render_metrics(const map_t* pMap, rendermetrics_t* pMetrics);
gdouble map_get_straight_line_distance_in_degrees(mappoint_t* p1, mappoint_t* p2);
-// Each zoomlevel has a scale and an optional name (name isn't used for anything)
+// Each zoomlevel has a scale (XXX: this should really be in an XML file)
zoomlevel_t g_sZoomLevels[NUM_ZOOM_LEVELS] = {
- // 1.166144850000 magic number for 2000-80000 in 25 steps. (each scale is previous * this #)
- // 1.181891000000 magic number for 2000-1,600,000 in 41 steps (11 major with 3 minor in between)
+ {150000000, UNIT_MILES,3000,UNIT_KILOMETERS,4000, 1, 3}, // *1
+ {123000000, UNIT_MILES,3000,UNIT_KILOMETERS,4000, 1, 3}, // 2
+ { 96000000, UNIT_MILES,2000,UNIT_KILOMETERS,2000, 1, 3}, // 3
+ { 69000000, UNIT_MILES,2000,UNIT_KILOMETERS,2000, 1, 3}, // 4
- {150000000, UNIT_MILES,2000,UNIT_KILOMETERS,2000, 1, 3}, // *1
- {123000000, UNIT_MILES,1000,UNIT_KILOMETERS,48, 1, 3}, // 2
- { 96000000, UNIT_MILES,500, UNIT_KILOMETERS,48, 1, 3}, // 3
- { 69000000, UNIT_MILES,200, UNIT_KILOMETERS,48, 1, 3}, // 4
+ { 42000000, UNIT_MILES,1000,UNIT_KILOMETERS,1000, 1, 3}, // *5
+ { 35000000, UNIT_MILES,1000,UNIT_KILOMETERS,1000, 1, 3}, // 6
+ { 28000000, UNIT_MILES,500,UNIT_KILOMETERS,500, 1, 3}, // 7
+ { 21000000, UNIT_MILES,500,UNIT_KILOMETERS,500, 1, 3}, // 8
- { 42000000, UNIT_MILES,100, UNIT_KILOMETERS,24, 1, 3}, // *5
- { 35000000, UNIT_MILES,50, UNIT_KILOMETERS,24, 1, 3}, // 6
- { 28000000, UNIT_MILES,20, UNIT_KILOMETERS,24, 1, 3}, // 7
- { 21000000, UNIT_MILES,10, UNIT_KILOMETERS,24, 1, 3}, // 8
-
- { 14000000, UNIT_MILES,10, UNIT_KILOMETERS,12, 2, 3}, // *9
- { 11600000, UNIT_MILES,10, UNIT_KILOMETERS,12, 2, 3}, // 10
- { 9200000, UNIT_MILES, 5, UNIT_KILOMETERS, 7, 2, 3}, // 11
- { 6800000, UNIT_MILES, 5, UNIT_KILOMETERS, 7, 2, 3}, // 12
+ { 14000000, UNIT_MILES,10, UNIT_KILOMETERS,12, 2, 2}, // *9
+ { 11600000, UNIT_MILES,10, UNIT_KILOMETERS,12, 2, 2}, // 10
+ { 9200000, UNIT_MILES, 5, UNIT_KILOMETERS, 7, 2, 2}, // 11
+ { 6800000, UNIT_MILES, 5, UNIT_KILOMETERS, 7, 2, 2}, // 12
{ 4400000, UNIT_MILES, 5, UNIT_KILOMETERS, 7, 3, 2}, // *13
{ 3850000, UNIT_MILES, 5, UNIT_KILOMETERS, 7, 3, 2}, // 14
{ 3300000, UNIT_MILES, 5, UNIT_KILOMETERS, 7, 3, 2}, // 15
{ 2750000, UNIT_MILES, 5, UNIT_KILOMETERS, 7, 3, 2}, // 16
- { 2200000, UNIT_MILES, 2, UNIT_KILOMETERS, 2, 4, 2}, // *17
- { 1832250, UNIT_MILES, 2, UNIT_KILOMETERS, 2, 4, 2}, // 18
- { 1464500, UNIT_MILES, 2, UNIT_KILOMETERS, 2, 4, 2}, // 19
- { 1100000, UNIT_MILES, 2, UNIT_KILOMETERS, 2, 4, 2}, // 20
-
- { 729000, UNIT_MILES, 2, UNIT_KILOMETERS, 2, 5, 1}, // *21
- { 607500, UNIT_MILES, 1, UNIT_KILOMETERS, 1, 5, 1}, // 22
- { 486000, UNIT_MILES, 1, UNIT_KILOMETERS, 1, 5, 1}, // 23
- { 364500, UNIT_MILES, 1, UNIT_KILOMETERS, 1, 5, 1}, // 24
-
- { 243000, UNIT_MILES, 1, UNIT_KILOMETERS, 1, 6, 1}, // *25
- { 202500, UNIT_FEET, 3000,UNIT_METERS, 500, 6, 1}, // 26
- { 162000, UNIT_FEET, 2000,UNIT_METERS, 500, 6, 1}, // 27
- { 121500, UNIT_FEET, 2000,UNIT_METERS, 500, 6, 1}, // 28
-
- { 81000, UNIT_FEET, 2000,UNIT_METERS, 300, 7, 0}, // *29
- { 67500, UNIT_FEET, 2000,UNIT_METERS, 300, 7, 0}, // 30
- { 54000, UNIT_FEET, 2000,UNIT_METERS, 300, 7, 0}, // 31
- { 40500, UNIT_FEET, 1000,UNIT_METERS, 200, 7, 0}, // 32
-
- { 27000, UNIT_FEET, 1000,UNIT_METERS, 200, 8, 0}, // *33
- { 22500, UNIT_FEET, 1000,UNIT_METERS, 200, 8, 0}, // 34
- { 18000, UNIT_FEET, 1000,UNIT_METERS, 200, 8, 0}, // 35
- { 13500, UNIT_FEET, 500, UNIT_METERS, 100, 8, 0}, // 36
-
- { 9000, UNIT_FEET, 500, UNIT_METERS, 100, 9, 0}, // *37
- { 7500, UNIT_FEET, 500, UNIT_METERS, 100, 9, 0}, // 38
- { 6000, UNIT_FEET, 300, UNIT_METERS, 50, 9, 0}, // 39
- { 4500, UNIT_FEET, 300, UNIT_METERS, 50, 9, 0}, // 40
-
- { 3000, UNIT_FEET, 300, UNIT_METERS, 50, 10, 0}, // *41
+ { 2200000, UNIT_MILES, 8, UNIT_KILOMETERS, 5, 4, 1}, // *17
+ { 1832250, UNIT_MILES, 8, UNIT_KILOMETERS, 5, 4, 1}, // 18
+ { 1464500, UNIT_MILES, 8, UNIT_KILOMETERS, 5, 4, 1}, // 19
+ { 1100000, UNIT_MILES, 8, UNIT_KILOMETERS, 5, 4, 1}, // 20
+
+ { 729000, UNIT_MILES,10, UNIT_KILOMETERS, 8, 5, 1}, // *21
+ { 607500, UNIT_MILES,10, UNIT_KILOMETERS, 8, 5, 1}, // 22
+ { 486000, UNIT_MILES,10, UNIT_KILOMETERS, 8, 5, 1}, // 23
+ { 364500, UNIT_MILES,10, UNIT_KILOMETERS, 8, 5, 1}, // 24
+
+ { 243000, UNIT_MILES, 5, UNIT_KILOMETERS, 4, 6, 1}, // *25
+ { 209750, UNIT_MILES, 5, UNIT_KILOMETERS, 4, 6, 1}, // 26
+ { 176500, UNIT_MILES, 5, UNIT_KILOMETERS, 4, 6, 1}, // 27
+ { 143250, UNIT_MILES, 5, UNIT_KILOMETERS, 4, 6, 1}, // 28
+
+ { 110000, UNIT_MILES, 2, UNIT_KILOMETERS,2, 7, 0}, // *29
+ { 89250, UNIT_MILES, 2, UNIT_KILOMETERS,2, 7, 0}, // 30
+ { 68500, UNIT_MILES, 2, UNIT_KILOMETERS,2, 7, 0}, // 31
+ { 47750, UNIT_MILES, 2, UNIT_KILOMETERS,2, 7, 0}, // 32
+
+ { 27000, UNIT_FEET, 2000,UNIT_METERS, 500, 8, 0}, // *33
+ { 22500, UNIT_FEET, 2000,UNIT_METERS, 500, 8, 0}, // 34
+ { 18000, UNIT_FEET, 2000,UNIT_METERS, 500, 8, 0}, // 35
+ { 13500, UNIT_FEET, 2000,UNIT_METERS, 500, 8, 0}, // 36
+
+ { 9000, UNIT_FEET, 500, UNIT_METERS, 200, 9, 0}, // *37
+ { 7500, UNIT_FEET, 500, UNIT_METERS, 200, 9, 0}, // 38
+ { 6000, UNIT_FEET, 500, UNIT_METERS, 200, 9, 0}, // 39
+ { 4500, UNIT_FEET, 500, UNIT_METERS, 200, 9, 0}, // 40
+
+ { 3000, UNIT_FEET, 200, UNIT_METERS, 50, 10, 0}, // *41
};
#define MIN_ZOOMLEVEL_FOR_LOCATIONS (6)
@@ -152,6 +149,8 @@ gchar* g_apszMapObjectTypeNames[] = { // XXX: would be nice to remove this. alth
"urban-areas",
};
+gchar* g_apszMapRenderTypeNames[] = {"lines", "polygons", "line-labels", "polygon-labels", "fill", "locations", "location-labels"};
+
// ========================================================
// Init
// ========================================================
@@ -295,6 +294,29 @@ guint32 map_get_zoomlevel_scale(const map_t* pMap)
return g_sZoomLevels[pMap->uZoomLevel-1].uScale; // returns "5000" for 1:5000 scale
}
+gdouble map_get_altitude(const map_t* pMap, EDistanceUnits eUnit)
+{
+ g_warning("broken function :)\n");
+
+ g_assert(eUnit == UNIT_MILES);
+
+ // How high are we off the ground?
+
+ // x = sqrt((SCALE*sqrt(1.25))^2 - (SCALE/2)^2)
+
+// gdouble fScale = (gdouble)(g_sZoomLevels[pMap->uZoomLevel-1].uScale);
+
+ rendermetrics_t renderMetrics = {0};
+ map_get_render_metrics(pMap, &renderMetrics);
+
+ gdouble fBase = renderMetrics.fScreenLatitude;
+ gdouble fEyeToTopOfScreen = sqrt( WORLD_FEET_TO_DEGREES(1) + 1 );
+
+ gdouble fDistanceInDegrees = sqrt(((fBase * fEyeToTopOfScreen)*(fBase * fEyeToTopOfScreen)) - ((fBase/2.0)*(fBase/2.0)));
+
+ return WORLD_DEGREES_TO_MILES(fDistanceInDegrees);
+}
+
gboolean map_can_zoom_in(const map_t* pMap)
{
// can we increase zoom level?
@@ -396,7 +418,7 @@ void map_set_dimensions(map_t* pMap, const dimensions_t* pDimensions)
// Draw Functions
// ========================================================
-void map_get_render_metrics(map_t* pMap, rendermetrics_t* pMetrics)
+void map_get_render_metrics(const map_t* pMap, rendermetrics_t* pMetrics)
{
g_assert(pMetrics != NULL);
@@ -440,8 +462,6 @@ gboolean map_object_type_atoi(const gchar* pszName, gint* pnReturnObjectTypeID)
gboolean map_layer_render_type_atoi(const gchar* pszName, gint* pnReturnRenderTypeID)
{
- gchar* g_apszMapRenderTypeNames[] = {"lines", "polygons", "line-labels", "polygon-labels", "fill", "locations", "location-labels"};
-
gint i;
for(i=0 ; i<G_N_ELEMENTS(g_apszMapRenderTypeNames) ; i++) {
if(strcmp(pszName, g_apszMapRenderTypeNames[i]) == 0) {
@@ -593,6 +613,14 @@ gboolean map_location_selection_remove(map_t* pMap, gint nLocationID)
return FALSE; // removed
}
+void map_get_visible_maprect(const map_t* pMap, maprect_t* pReturnMapRect)
+{
+ rendermetrics_t renderMetrics = {0};
+ map_get_render_metrics(pMap, &renderMetrics);
+
+ memcpy(pReturnMapRect, &(renderMetrics.rWorldBoundingBox), sizeof(maprect_t));
+}
+
#ifdef ROADSTER_DEAD_CODE
/*
diff --git a/src/map.h b/src/map.h
index 6c288d2..9f8b527 100644
--- a/src/map.h
+++ b/src/map.h
@@ -76,6 +76,7 @@ typedef enum {
// For road names: Bitstream Vera Sans Mono ?
#define INCHES_PER_METER (39.37007)
+#define FEET_PER_MILE (5280.0)
#define WORLD_CIRCUMFERENCE_IN_METERS (40075452.7)
#define WORLD_METERS_PER_DEGREE (WORLD_CIRCUMFERENCE_IN_METERS / 360.0)
@@ -85,12 +86,15 @@ typedef enum {
#define WORLD_KILOMETERS_TO_DEGREES(x) (((x) * KILOMETERS_PER_METER) / WORLD_METERS_PER_DEGREE)
#define WORLD_CIRCUMFERENCE_IN_FEET (131482939.8324)
+
+#define WORLD_MILES_PER_DEGREE ((WORLD_CIRCUMFERENCE_IN_FEET / 360.0) / FEET_PER_MILE)
#define WORLD_FEET_PER_DEGREE (WORLD_CIRCUMFERENCE_IN_FEET / 360.0)
#define WORLD_FEET_TO_DEGREES(X) ((X) / WORLD_FEET_PER_DEGREE)
-#define FEET_PER_MILE (5280.0)
#define WORLD_MILES_TO_DEGREES(x) ((x * FEET_PER_MILE) / WORLD_FEET_PER_DEGREE)
+#define WORLD_DEGREES_TO_MILES(x) ((x) * WORLD_MILES_PER_DEGREE)
+
// Earth is slightly egg shaped so there are infinite radius measurements:
// at poles: ?
@@ -278,7 +282,6 @@ gboolean map_can_zoom_in(const map_t* pMap);
gboolean map_can_zoom_out(const map_t* pMap);
void map_set_zoomlevel(map_t* pMap, guint16 uZoomLevel);
-//void map_get_render_metrics(rendermetrics_t* pMetrics);
void map_set_redraw_needed(map_t* pMap, gboolean bNeeded);
gboolean map_get_redraw_needed(const map_t* pMap);
@@ -294,7 +297,7 @@ gdouble map_distance_in_units_to_degrees(map_t* pMap, gdouble fDistance, gint nD
gdouble map_get_distance_in_meters(mappoint_t* pA, mappoint_t* pB);
gdouble map_get_straight_line_distance_in_degrees(mappoint_t* p1, mappoint_t* p2);
-gdouble map_pixels_to_degrees(map_t* pMap, gint16 nPixels, guint16 uZoomLevel);
+gdouble map_pixels_to_degrees(const map_t* pMap, gint16 nPixels, guint16 uZoomLevel);
gdouble map_degrees_to_pixels(map_t* pMap, gdouble fDegrees, guint16 uZoomLevel);
gboolean map_points_equal(mappoint_t* p1, mappoint_t* p2);
gdouble map_get_distance_in_pixels(map_t* pMap, mappoint_t* p1, mappoint_t* p2);
@@ -323,4 +326,7 @@ gint map_screenrect_width(const screenrect_t* pRect);
gint map_screenrect_height(const screenrect_t* pRect);
void map_get_screenrect_centerpoint(const screenrect_t* pRect, screenpoint_t* pPoint);
+void map_get_visible_maprect(const map_t* pMap, maprect_t* pReturnMapRect);
+gdouble map_get_altitude(const map_t* pMap, EDistanceUnits eUnit);
+
#endif
diff --git a/src/map_draw_gdk.c b/src/map_draw_gdk.c
index dd455bb..4a538e8 100644
--- a/src/map_draw_gdk.c
+++ b/src/map_draw_gdk.c
@@ -23,7 +23,7 @@
#define MAX_GDK_LINE_SEGMENTS (2000)
-//#define ENABLE_MAP_GRAYSCALE_HACK
+//#define ENABLE_MAP_GRAYSCALE_HACK // just a little test. black and white might be good for something
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
@@ -53,8 +53,6 @@ static void map_draw_gdk_locationset(map_t* pMap, GdkPixmap* pPixmap, rendermetr
//static void map_draw_gdk_tracks(map_t* pMap, GdkPixmap* pPixmap, rendermetrics_t* pRenderMetrics);
-//#define ENABLE_MAP_GRAYSCALE_HACK // just a little test. black and white might be good for something
-
void map_draw_gdk_set_color(GdkGC* pGC, color_t* pColor)
{
GdkColor clr;
@@ -76,9 +74,9 @@ void map_draw_gdk_xor_rect(map_t* pMap, GdkDrawable* pTargetDrawable, screenrect
GdkGCValues gcValues;
gdk_gc_get_values(pGC, &gcValues);
- GdkColor clrWhite = {0, 32000, 32000, 32000};
+ GdkColor clr = {0, 65535, 65535, 65535};
gdk_gc_set_function(pGC, GDK_XOR);
- gdk_gc_set_rgb_fg_color(pGC, &clrWhite);
+ gdk_gc_set_rgb_fg_color(pGC, &clr);
gdk_draw_rectangle(pTargetDrawable, pGC, FALSE,
min(pRect->A.nX, pRect->B.nX), min(pRect->A.nY, pRect->B.nY), // x,y
map_screenrect_width(pRect), map_screenrect_height(pRect)); // w,h
diff --git a/src/map_math.c b/src/map_math.c
index f9a7dbf..6d820ff 100644
--- a/src/map_math.c
+++ b/src/map_math.c
@@ -29,7 +29,7 @@
// ========================================================
// convert pixels to a span of degrees
-gdouble map_pixels_to_degrees(map_t* pMap, gint16 nPixels, guint16 uZoomLevel)
+gdouble map_pixels_to_degrees(const map_t* pMap, gint16 nPixels, guint16 uZoomLevel)
{
gdouble fMonitorPixelsPerInch = 85.333; // XXX: don't hardcode this
gdouble fPixelsPerMeter = fMonitorPixelsPerInch * INCHES_PER_METER;
diff --git a/src/map_style.c b/src/map_style.c
index ac2457d..f1b7bdf 100644
--- a/src/map_style.c
+++ b/src/map_style.c
@@ -33,7 +33,7 @@
#define MIN_STYLE_LEVEL (1)
#define MAX_STYLE_LEVEL (10)
-// utility functions for iterating through lists of XML things
+// utility macros for iterating through lists of XML things
#define EACH_ATTRIBUTE_OF_NODE(a,n) (a) = (n)->properties ; (a) != NULL ; (a) = (a)->next
#define EACH_CHILD_OF_NODE(c,n) (c) = (n)->children ; (c) != NULL ; (c) = (c)->next
@@ -49,18 +49,6 @@ static void map_style_parse_layer_property(map_t* pMap, xmlDocPtr pDoc, maplayer
static void map_style_print_layer(maplayer_t *layer);
static void map_style_print_color(color_t *color);
-
-// Callbacks
-// void map_style_callback_generic_error(void * ctx, const char * msg, ...)
-// {
-// g_print("map_style_callback_generic_error: %s\n", msg);
-// }
-//
-// void map_style_callback_structured_error(void * userData, xmlErrorPtr error)
-// {
-// g_print("map_style_callback_structured_error\n");
-// }
-
//
// Functions
//
@@ -105,7 +93,7 @@ static maplayer_t* map_style_new_layer()
return pLayer;
}
-gboolean map_style_parse_zoomlevel(const gchar* pszZoomLevel, gint* pnReturnMinZoomLevel, gint* pnReturnMaxZoomLevel)
+static gboolean map_style_parse_zoomlevel(const gchar* pszZoomLevel, gint* pnReturnMinZoomLevel, gint* pnReturnMaxZoomLevel)
{
g_assert(pszZoomLevel != NULL);
g_assert(pnReturnMinZoomLevel != NULL);
@@ -150,7 +138,7 @@ gboolean map_style_parse_zoomlevel(const gchar* pszZoomLevel, gint* pnReturnMinZ
#define MAX_DASH_LENGTH (50)
#define MIN_DASH_LENGTH (1)
-dashstyle_t* dashstyle_new(gdouble* pafValues, gint nValueCount)
+static dashstyle_t* dashstyle_new(gdouble* pafValues, gint nValueCount)
{
g_assert(pafValues != NULL);
@@ -162,7 +150,7 @@ dashstyle_t* dashstyle_new(gdouble* pafValues, gint nValueCount)
pNewDashStyle->pafDashList = g_malloc(sizeof(gdouble) * nValueCount);
memcpy(pNewDashStyle->pafDashList, pafValues, sizeof(gdouble) * nValueCount);
- // The list of int8's has to be converted list
+ // The list of int8's has to be converted
pNewDashStyle->panDashList = g_malloc(sizeof(gint8) * nValueCount);
gint i;
for(i=0 ; i<nValueCount ; i++) {
@@ -180,7 +168,7 @@ dashstyle_t* dashstyle_new(gdouble* pafValues, gint nValueCount)
return pNewDashStyle;
}
-gboolean map_style_parse_dashstyle(const gchar* pszDashStyle, dashstyle_t** ppReturnDashStyle)
+static gboolean map_style_parse_dashstyle(const gchar* pszDashStyle, dashstyle_t** ppReturnDashStyle)
{
g_assert(pszDashStyle);
g_assert(ppReturnDashStyle);
@@ -219,7 +207,7 @@ gboolean map_style_parse_dashstyle(const gchar* pszDashStyle, dashstyle_t** ppRe
return FALSE;
}
-gchar* get_attribute_value(const xmlDocPtr pDoc, const xmlAttrPtr pAttribute)
+static gchar* get_attribute_value(const xmlDocPtr pDoc, const xmlAttrPtr pAttribute)
{
g_assert(pDoc != NULL);
g_assert(pAttribute != NULL);
@@ -350,8 +338,7 @@ static void map_style_parse_layer(map_t* pMap, xmlDocPtr pDoc, xmlNodePtr pNode)
// map_style_print_layer(pLayer);
}
-static void
-map_style_parse_layer_property(map_t* pMap, xmlDocPtr pDoc, maplayer_t *pLayer, xmlNodePtr pNode)
+static void map_style_parse_layer_property(map_t* pMap, xmlDocPtr pDoc, maplayer_t *pLayer, xmlNodePtr pNode)
{
g_assert(pMap != NULL);
g_assert(pLayer != NULL);
@@ -484,8 +471,7 @@ map_style_parse_layer_property(map_t* pMap, xmlDocPtr pDoc, maplayer_t *pLayer,
/******************************************************************
* map_style_print_* functions for debugging
*****************************************************************/
-static void
-map_style_print_color(color_t* pColor)
+static void map_style_print_color(color_t* pColor)
{
g_assert(pColor != NULL);
g_print("color: %3.2f, %3.2f, %3.2f, %3.2f\n", pColor->fRed, pColor->fGreen, pColor->fBlue, pColor->fAlpha);
@@ -510,8 +496,7 @@ map_style_print_color(color_t* pColor)
color_t clrHalo;
*/
-static void
-map_style_print_layer(maplayer_t *pLayer)
+static void map_style_print_layer(maplayer_t *pLayer)
{
g_assert(pLayer != NULL);
diff --git a/src/map_tilemanager.c b/src/map_tilemanager.c
index d5d75ec..1fa67f0 100644
--- a/src/map_tilemanager.c
+++ b/src/map_tilemanager.c
@@ -159,10 +159,10 @@ static maptile_t* map_tilemanager_tile_new(maptilemanager_t* pTileManager, mapre
for(i=0 ; i<MAP_NUM_OBJECT_TYPES ; i++) {
pNewTile->apMapObjectArrays[i] = g_ptr_array_new();
}
- g_print("(");
+// g_print("(");
_map_tilemanager_tile_load_map_objects(pNewTile, pRect, nLOD);
// _map_tilemanager_tile_load_locations(pNewTile, pRect);
- g_print(")");
+// g_print(")");
// Add to cache
g_ptr_array_add(pTileManager->apTileCachedArrays[nLOD], pNewTile);
diff --git a/src/searchwindow.c b/src/searchwindow.c
index d3f6993..3c555d6 100644
--- a/src/searchwindow.c
+++ b/src/searchwindow.c
@@ -142,8 +142,8 @@ void searchwindow_clear_results(void)
static void searchwindow_update_next_and_prev_buttons()
{
- gtk_widget_set_sensitive(g_SearchWindow.pNextSearchResultMenuItem, g_SearchWindow.nNumResults > 0);
- gtk_widget_set_sensitive(g_SearchWindow.pPreviousSearchResultMenuItem, g_SearchWindow.nNumResults > 0);
+ gtk_widget_set_sensitive(GTK_WIDGET(g_SearchWindow.pNextSearchResultMenuItem), g_SearchWindow.nNumResults > 0);
+ gtk_widget_set_sensitive(GTK_WIDGET(g_SearchWindow.pPreviousSearchResultMenuItem), g_SearchWindow.nNumResults > 0);
}
void searchwindow_set_message(gchar* pszMessage)
diff --git a/src/tooltipwindow.c b/src/tooltipwindow.c
index d9dd364..acf3b6c 100644
--- a/src/tooltipwindow.c
+++ b/src/tooltipwindow.c
@@ -44,7 +44,6 @@ tooltip_t* tooltip_new()
gtk_frame_set_shadow_type(pFrame, GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(pNew->pWindow), GTK_WIDGET(pFrame));
-
// create label and add to frame
pNew->pLabel = GTK_LABEL(gtk_label_new("testing"));
gtk_container_add(GTK_CONTAINER(pFrame), GTK_WIDGET(pNew->pLabel));
@@ -86,5 +85,3 @@ static gboolean tooltip_on_mouse_motion(GtkWidget* pWidget, GdkEventMotion *__un
// in case the mouse makes its way onto the tooltip, hide it.
gtk_widget_hide(pWidget);
}
-
-
diff --git a/src/util.c b/src/util.c
index ec30a25..abc88b7 100644
--- a/src/util.c
+++ b/src/util.c
@@ -426,6 +426,53 @@ gboolean util_gtk_window_set_fullscreen(GtkWindow* pWindow, gboolean bFullscreen
}
}
+gint util_gtk_widget_style_get_property_gint(GtkWidget* pWidget, const gchar* pszName)
+{
+ GValue vValue = {0};
+ g_value_init(&vValue, G_TYPE_INT);
+ gtk_widget_style_get_property(pWidget, pszName, &vValue);
+ gint nValue = g_value_get_int(&vValue);
+ g_value_unset(&vValue);
+
+ return nValue;
+}
+
+// This callback changes the behavior of a GtkHScale. Clicking on the scale to the sides of the 'thumb' will
+// now cause the thumb to jump to that position.
+// To use: g_signal_connect(G_OBJECT(pScaleWidget), "change-value", util_gtk_range_instant_set_on_value_changing_callback, NULL);
+gboolean util_gtk_range_instant_set_on_value_changing_callback(GtkRange *pRangeWidget, GtkScrollType scroll, gdouble value, gpointer user_data)
+{
+ gint nMouseX;
+ gtk_widget_get_pointer(GTK_WIDGET(pRangeWidget), &nMouseX, NULL);
+
+ // Get the width of the "slider" gizmo (the thing the user clicks and drags)
+ gint nSliderWidth = util_gtk_widget_style_get_property_gint(GTK_WIDGET(pRangeWidget), "slider-length");
+
+ // The center of the slider is the actual setting, so we subtract slider width from total width
+ // Example: If the slider width is 4, the effect range of the slider would be the ===s here:
+ // [--===============--]
+
+ // Subtract half the width, which gives us: [===============----]
+ nMouseX -= ((nSliderWidth) / 2);
+ gint nEffectiveRangeWidth = (gdouble)(GTK_WIDGET(pRangeWidget)->allocation.width) - (nSliderWidth);
+
+ gdouble fPercent = (gdouble)nMouseX / (gdouble)nEffectiveRangeWidth;
+ if(fPercent < 0.0) fPercent = 0.0;
+ if(fPercent > 1.0) fPercent = 1.0;
+
+ // Get adjustment's range and set value as % of that range
+ GtkAdjustment* pAdjustment;
+ g_object_get(G_OBJECT(pRangeWidget), "adjustment", &pAdjustment, NULL);
+
+ gdouble fMin, fMax;
+ g_object_get(G_OBJECT(pAdjustment), "lower", &fMin, "upper", &fMax, NULL);
+
+ gdouble fNewValue = fMin + (fPercent * (fMax - fMin));
+ gtk_range_set_value(pRangeWidget, fNewValue);
+
+ return TRUE; // we handled it
+}
+
//
//
//
@@ -471,4 +518,25 @@ void util_gtk_entry_add_hint_text(GtkEntry* pEntry, const gchar* pszHint)
_util_gtk_entry_on_focus_out_event(pEntry, NULL, pszHint);
}
+gint util_get_int_at_percent_of_range(gdouble fPercent, gint nA, gint nB)
+{
+ if(fPercent > 1.0) fPercent = 1.0;
+ else if(fPercent < 0.0) fPercent = 0.0;
+
+ return (gint)(nA + (fPercent * (nB - nA)));
+}
+
+gdouble util_get_percent_of_range(gint nMiddle, gint nA, gint nB)
+{
+ if(nMiddle < nA) return 0.0;
+ else if(nMiddle > nB) return 1.0;
+
+ return (gdouble)(nMiddle - nA) / (gdouble)(nB - nA);
+}
+gchar* util_format_gdouble(gdouble d)
+{
+ gchar achBuffer[20];
+ g_ascii_dtostr(achBuffer, 20, d);
+ return g_strdup(achBuffer);
+}
diff --git a/src/util.h b/src/util.h
index 6d76d07..2efb0c8 100644
--- a/src/util.h
+++ b/src/util.h
@@ -61,6 +61,8 @@ gboolean util_gtk_tree_view_select_previous(GtkTreeView* pTreeView);
gboolean util_gtk_window_is_fullscreen(GtkWindow* pWindow);
gboolean util_gtk_window_set_fullscreen(GtkWindow* pWindow, gboolean bFullscreen);
+gboolean util_gtk_range_instant_set_on_value_changing_callback(GtkRange *range, GtkScrollType scroll, gdouble value, gpointer user_data);
+
// if glib < 2.6
#if(!GLIB_CHECK_VERSION(2,6,0))
gint g_strv_length(const gchar** a);
@@ -80,4 +82,10 @@ gchar** util_split_words_onto_two_lines(const gchar* pszText, gint nMinLineLengt
// GtkEntry "hint"
void util_gtk_entry_add_hint_text(GtkEntry* pEntry, const gchar* pszMessage);
+gint util_get_int_at_percent_of_range(gdouble fPercent, gint nA, gint nB);
+gdouble util_get_percent_of_range(gint nMiddle, gint nA, gint nB);
+
+gchar* util_format_gdouble(gdouble d);
+
+
#endif