Hi!
The attached patch reworks the scalebar code. Up to now, the scale bar
is fixed-size (in terms of pixles) and the resulting real-world length
is calculated from that.
With this patch, gpsdrive will first figure out which value in the
form of
1.0, 2.5, 5.0 * 10^n [nmi, mi, m, km, yd]
best fits 1/8 of the screen's width. Based upon that, 1/8th is
properly expanded to actually match the requested real-world length.
The patch should probably not go in as-is, because the printed length
isn't always properly placed in the middle of the bar. Someone with
more GTK+ knowledge should have a look. It also still contains
comments about the contents of the numeric values, which should or
should not be removed...
MfG, JBG
Index: src/gpsdrive.h
===================================================================
RCS file: /cvsroot/gpsdrive/src/gpsdrive.h,v
retrieving revision 1.14
diff -u -r1.14 gpsdrive.h
--- src/gpsdrive.h 5 May 2006 22:18:08 -0000 1.14
+++ src/gpsdrive.h 27 May 2006 19:02:17 -0000
@@ -216,6 +216,9 @@
/*** Mod by Arms (move) */
#define YMINUS 67
+/*** Number of elements in an array */
+#define ARRAY_SIZE(x) ((sizeof (x))/(sizeof ((x)[0])))
+
/*
* Mod by Rick Richardson:
*
@@ -279,9 +282,9 @@
#define MAPSCALE 20000
/* Mapscale / pixelfact is meter / pixel */
-#define PIXELFACT 2817.947378
-#define KM2MILES 0.62137119
-#define KM2NAUTIC 0.5399568
+#define PIXELFACT 2817.947378
+#define KM2MILES 0.62137119 /* international_mile / km */
+#define KM2NAUTIC 0.5399568 /* nautic_mile / km */
#define MAXMESG 8192
Index: src/gpsdrive.c
===================================================================
RCS file: /cvsroot/gpsdrive/src/gpsdrive.c,v
retrieving revision 1.103
diff -u -r1.103 gpsdrive.c
--- src/gpsdrive.c 21 May 2006 05:22:31 -0000 1.103
+++ src/gpsdrive.c 27 May 2006 19:02:30 -0000
@@ -2184,58 +2184,106 @@
}
}
-/*
*****************************************************************************
+/*
+ * Draw the scale bar ( |-------------| ) into the map. Also add a textual
+ * description of the currently used scale.
*/
void
draw_zoom_scale (void)
{
- gint pixels;
- gint m, l;
+ gdouble factor[] = { 1.0, 2.5, 5.0, };
+ gint exponent = 0;
+ gdouble remains = 0.0;
+ gint used_factor = 0;
+ gint i;
+ gint min_bar_length = SCREEN_X / 8; /* 1/8 of the display width */
+ const gint dist_x = 20; /* distance to the right */
+ const gint dist_y = 20; /* distance to bottom */
+ const gint frame_width = 5; /* grey pixles around the scale bar */
+ gint bar_length;
gchar txt[100];
+ gchar *format;
+ gchar *symbol;
+ gdouble approx_diaplayed_value;
+ gdouble conversion;
+ gint l;
- if (mydebug >50) printf ("draw_zoom_scale()\n");
+ /*
+ * We want a bar with at least (min_bar_length) pixles in
+ * length. Calculate the displayed value of this bar is whatever
+ * metric is requested.
+ *
+ * The bar length' value l (in m), divided by "conversion", will
+ * result in what to display to the user, in terms of "symbol".
+ */
+ approx_diaplayed_value /* m */ = min_bar_length * mapscale
+ / PIXELFACT / zoom;
- pixels = 141 / milesconv;
- m = mapscale / (20 * zoom);
- if (m < 1000)
- {
- if (!nauticflag)
- g_snprintf (txt, sizeof (txt), "%d%s", m,
- (milesflag) ? "yrds" : "m");
- else
- g_snprintf (txt, sizeof (txt), "%.3f%s", m / 1000.0,
- (milesflag) ? "mi" : ((metricflag) ? "km"
- : "nmi"));
+ if (nauticflag) {
+ conversion /* m/nmi */ = 1000.0 /* m/km */ / KM2NAUTIC /*
nmi/km */;
+ symbol = "nmi";
+ format = "%.2lf %s";
+ } else if (metricflag) {
+ conversion /* m/m */ = 1.0 /* m/m */;
+ symbol = "m";
+ format = "%.0lf %s";
+ if (approx_diaplayed_value / conversion > 1000) {
+ conversion /* m/km */ = 1000.0;
+ symbol = "km";
+ format = "%.0lf %s";
+ }
+ } else if (milesflag) {
+ conversion /* m/yd */ = 1000.0 /* m/km */
+ / 1760.0 /* yd/mi */
+ / KM2MILES /* mi/km */;
+ symbol = "yd";
+ format = "%.0lf %s";
+ if (approx_diaplayed_value / conversion > 1760.0) {
+ conversion /* m/mi */ = 1000.0 /* m/km */
+ / KM2MILES /* mi/km */;
+ symbol = "mi";
+ format = "%.0lf %s";
+ }
+ } else
+ return;
- if (!metricflag)
- pixels = pixels * milesconv * 0.9144;
- }
- else
- g_snprintf (txt, sizeof (txt), "%.1f%s", m / 1000.0,
- (milesflag) ? "mi" : ((metricflag) ? "km" :
- "nmi"));
- /* l =
- * (SCREEN_X - 20) - pixels + (pixels -
- * gdk_text_width (smalltextfont, txt,
- * strlen (txt))) / 2;
+ /*
+ * Now find a well-formed value that is about the expected size
+ * of the scale bar, or a bit longer.
*/
- l = (SCREEN_X - 40) - pixels + (pixels - strlen (txt) * 15);
+ for (i = 0; i < ARRAY_SIZE (factor); i++) {
+ gdouble rest;
+ gdouble log_value;
+
+ log_value = log10 (min_bar_length * mapscale / PIXELFACT
+ / conversion / zoom / factor[i]);
+
+ if ((rest = log_value - floor (log_value)) >= remains) {
+ remains = rest;
+ used_factor = i;
+ exponent = (gint) floor (log_value) + 1;
+ }
+ }
+ bar_length = factor[used_factor] * pow (10.0, exponent)
+ * conversion / (mapscale / PIXELFACT) * zoom;
+
+ g_snprintf (txt, sizeof (txt), format, factor[used_factor]
+ * pow (10.0, exponent),
+ symbol);
- /* if ( mydebug > 10 ) */
- /* g_print("%d\n", m); */
+ l = (SCREEN_X - 40) - bar_length + (bar_length - strlen (txt) * 15);
+ /* Draw greyish rectangle as background for the scale bar */
gdk_gc_set_function (kontext, GDK_OR);
gdk_gc_set_foreground (kontext, &textback);
gdk_draw_rectangle (drawable, kontext, 1,
- (SCREEN_X - 20) - pixels - 5, SCREEN_Y - 35,
- pixels + 10, 30);
+ SCREEN_X - dist_x - bar_length - frame_width,
+ SCREEN_Y - dist_y - 2 * frame_width,
+ bar_length + 2 * frame_width, 2 * frame_width);
gdk_gc_set_function (kontext, GDK_COPY);
-
gdk_gc_set_foreground (kontext, &black);
- /* gdk_draw_text (drawable, smalltextfont, kontext, l, SCREEN_Y -
20, txt,
- * strlen (txt));
- */
+ /* Print the meaning of the scale bar ("10 km") */
{
/* prints in pango */
PangoFontDescription *pfd;
@@ -2251,7 +2299,7 @@
pango_layout_set_font_description (wplabellayout, pfd);
gdk_draw_layout_with_colors (drawable, kontext,
- l, SCREEN_Y - 33,
+ l, SCREEN_Y - dist_y + frame_width,
wplabellayout, &black, NULL);
if (wplabellayout != NULL)
g_object_unref (G_OBJECT (wplabellayout));
@@ -2260,16 +2308,20 @@
}
+ /* Print the actual scale bar */
gdk_gc_set_line_attributes (kontext, 2, 0, 0, 0);
+ /* horizonthal */
gdk_draw_line (drawable, kontext,
- (SCREEN_X - 20) - pixels, SCREEN_Y - 20 + 5,
- (SCREEN_X - 20), SCREEN_Y - 20 + 5);
+ (SCREEN_X - dist_x) - bar_length, SCREEN_Y - dist_y +
frame_width,
+ (SCREEN_X - dist_x), SCREEN_Y - dist_y + frame_width);
+ /* left */
gdk_draw_line (drawable, kontext,
- (SCREEN_X - 20) - pixels, SCREEN_Y - 20,
- (SCREEN_X - 20) - pixels, SCREEN_Y - 20 + 10);
+ (SCREEN_X - dist_x) - bar_length, SCREEN_Y - dist_y,
+ (SCREEN_X - dist_x) - bar_length, SCREEN_Y - dist_y +
10);
+ /* right */
gdk_draw_line (drawable, kontext,
- (SCREEN_X - 20), SCREEN_Y - 20,
- (SCREEN_X - 20), SCREEN_Y - 20 + 10);
+ (SCREEN_X - dist_x), SCREEN_Y - dist_y,
+ (SCREEN_X - dist_x), SCREEN_Y - dist_y + 10);
#ifdef USETELEATLAS
/* display the streetname */
@@ -3573,7 +3625,7 @@
/*
*****************************************************************************
- * switching between kilometers and miles
+ * switching between kilometers and metric/nautic miles
*/
gint
miles_cb (GtkWidget * widget, guint datum)
--
Jan-Benedict Glaw jbglaw-D2rzxHzF5wuELgA04lAiVw@xxxxxxxxxxxxxxxx .
+49-172-7608481 _ O _
"Eine Freie Meinung in einem Freien Kopf | Gegen Zensur | Gegen Krieg _ _ O
für einen Freien Staat voll Freier Bürger" | im Internet! | im Irak! O O O
ret = do_actions((curr | FREE_SPEECH) & ~(NEW_COPYRIGHT_LAW | DRM | TCPA));
signature.asc
Description: Digital signature
|