logo       

[ gpsdrive ] [PATCH] Rework scalebar code: msg#00108

Subject: [ gpsdrive ] [PATCH] Rework scalebar code
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));

Attachment: signature.asc
Description: Digital signature

<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

Recently Viewed:
qnx.openqnx.dev...    politics.lenini...    audio.emagic.ex...    tex.texinfo.gen...    handhelds.linux...    ietf.sipping/20...    lang.erlang.gen...    cygwin.talk/200...    yellowdog.gener...    mozilla.devel.l...    xfree86.newbie/...    openbsd.ports/2...    db.oracle.devel...    kde.kalyxo.deve...    user-groups.lin...    bbc.cvs/2003-04...    gnu.libtool.bug...    redhat.k12osn/2...    emulators.wine....    freebsd.devel.d...    search.xapian.g...    java.izpack.use...    network.mrtg.us...    windows.total-c...   
Home | blog view | USPTO Patent Archive | advertise | OSDir is an inevitable website. super tiny logo

Free Magazines

Cisco News
Receive a free quarterly e-newsletter with exclusive articles on how Cisco IT uses its own products and solutions to enable the business.
subscribe

Systems Management News, the newspaper for IT systems administration and data center managers! Each issue of Systems Management News is chock-full of news and analysis to help you understand what's happening in your field.
subscribe

The Enterprise Newsweekly eWeek is the essential technology information source for builders of e-business.
subscribe

Oracle Magazine Oracle Magazine contains technology strategy articles, sample code, tips, Oracle and partner news, how to articles for developers and DBAs, and more. Oracle (NASDAQ: ORCL) is the world's largest enterprise software company.
subscribe

Total Telecom Total Telecom is "The Economist of the communications industry".
subscribe