[osm-gps-map] 01/11: Imported Upstream version 1.1.0

Ross Gammon ross-guest at moszumanska.debian.org
Wed Nov 25 22:21:04 UTC 2015


This is an automated email from the git hooks/post-receive script.

ross-guest pushed a commit to branch master
in repository osm-gps-map.

commit 9c08374ba08d7ccea316b8708b7e5490816e029f
Author: Ross Gammon <rossgammon at mail.dk>
Date:   Sat Nov 21 10:56:14 2015 +0100

    Imported Upstream version 1.1.0
---
 Makefile.am                |  18 +-
 NEWS                       |   9 +
 configure.ac               |  15 +-
 docs/reference/Makefile.am |   4 +-
 examples/Makefile.am       |  38 +++-
 examples/README            |   3 +
 examples/editable_track.c  |  42 +++++
 examples/mapviewer.c       |   9 +-
 examples/polygon.c         |  47 +++++
 m4/gtk-doc.m4              |  51 ++++--
 src/Makefile.am            |   2 +
 src/converter.c            |  28 +++
 src/converter.h            |   8 +
 src/osm-gps-map-image.c    |  37 ++++
 src/osm-gps-map-image.h    |   2 +
 src/osm-gps-map-polygon.c  | 185 +++++++++++++++++++
 src/osm-gps-map-polygon.h  |  60 +++++++
 src/osm-gps-map-source.c   |  22 ---
 src/osm-gps-map-source.h   |   3 -
 src/osm-gps-map-track.c    | 125 ++++++++++++-
 src/osm-gps-map-track.h    |  25 +++
 src/osm-gps-map-widget.c   | 434 ++++++++++++++++++++++++++++++++++++++++++---
 src/osm-gps-map-widget.h   |   7 +
 23 files changed, 1069 insertions(+), 105 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index fafc4bb..8f2d1d5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,30 +1,21 @@
 ## Process this file with automake to produce Makefile.in
 
 SUBDIRS = src examples docs
-DISTCHECK_CONFIGURE_FLAGS =                     \
-    --enable-gtk-doc                            \
-    --enable-maintainer-flags
+AM_DISTCHECK_CONFIGURE_FLAGS =                  \
+    --enable-gtk-doc
 
 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
 
-osm_gps_mapdocdir = ${prefix}/doc/osm-gps-map
-osm_gps_mapdoc_DATA =                           \
+doc_DATA =                                      \
 	README                                      \
 	COPYING                                     \
 	AUTHORS                                     \
 	ChangeLog                                   \
-	INSTALL                                     \
 	NEWS
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = osmgpsmap-1.0.pc
 
-EXTRA_DIST = $(openstreetmap_gps_mapdoc_DATA)   \
-	osmgpsmap-1.0.pc.in                         \
-	gtk-doc.make		                        \
-	m4/introspection.m4                         \
-	m4/gtk-doc.m4
-
 DISTCLEANFILES = gtk-doc.make
 
 # ChangeLog generation from nautils
@@ -34,8 +25,7 @@ distclean-local:
 	fi
 
 ChangeLog:
-	@echo Creating $@
-	@if test -d "$(srcdir)/.git"; then \
+	$(AM_V_GEN)if test -d "$(srcdir)/.git"; then \
 	  (GIT_DIR=$(top_srcdir)/.git ./missing --run git log 0.7.3.. --stat -M -C --name-status  --date=short --no-color) | fmt --split-only > $@.tmp \
 	  && mv -f $@.tmp $@ \
 	  || ($(RM) $@.tmp; \
diff --git a/NEWS b/NEWS
index ed3ce93..52e6d82 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+Changes in 1.1.0
+======================
+  * Add polygon support Samuel Cowen <samuel.cowen89 at gmail.com>
+  * Add osm_gps_map_zoom_fit_bbox Martijn Goedhart <goedhart.martijn at gmail.com>
+  * Fix leaks oman Lebedev <lebedev.ri at gmail.com>
+  * Remove Yahoo (API break) Quentin Glidic <sardemff7+git at sardemff7.net>
+  * Build fixes Quentin Glidic <sardemff7+git at sardemff7.net>
+  * Fix image rotation Christoph Gysin <christoph.gysin at gmail.com>
+
 Changes in 1.0.2
 ======================
   * Fix build with new giscanner
diff --git a/configure.ac b/configure.ac
index d5a6cd6..6e9ae8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,10 @@
 AC_PREREQ([2.63])
 AC_INIT([osm-gps-map],
-        [1.0.2],
+        [1.1.0],
         [http://github.com/nzjrs/osm-gps-map/issues],
         [osm-gps-map])
 
-AM_INIT_AUTOMAKE([1.11])
+AM_INIT_AUTOMAKE([1.11 foreign subdir-objects parallel-tests])
 
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SRCDIR([src/osm-gps-map.h])
@@ -25,11 +25,7 @@ PKG_CHECK_MODULES(SOUP24,   [libsoup-2.4])
 
 # The mapviewer demo also calls g_thread_init, so it needs to link against
 # libgthread-2.0.
-PKG_CHECK_MODULES(GTHREAD, [gthread-2.0], [
-    have_gthread="yes" ], [
-        have_gthread="no"
-        AC_MSG_RESULT([mapviewer demo disabled])])
-AM_CONDITIONAL([HAVE_GTHREAD], [ test "x$have_gthread" = "xyes" ])
+PKG_CHECK_MODULES(GTHREAD, [gthread-2.0])
 
 AC_CHECK_FUNCS(gdk_event_get_scroll_deltas)
 
@@ -52,16 +48,15 @@ AM_CONDITIONAL(OS_WIN32, [test $os_win32 = yes])
 # - If binary compatibility has been broken (eg removed or changed interfaces)
 #   change to C+1:0:0
 # - If the interface is the same as the previous version, change to C:R+1:A
-LT_VERSION_INFO=0:0:0
+LT_VERSION_INFO=1:0:0
 AC_SUBST(LT_VERSION_INFO)
 
 GOBJECT_INTROSPECTION_REQS=0.10.0
-GOBJECT_INTROSPECTION_REQUIRE([$GOBJECT_INTROSPECTION_REQS])
+GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_REQS])
 
 GTK_DOC_CHECK([1.12])
 
 GNOME_COMPILE_WARNINGS([maximum])
-GNOME_MAINTAINER_MODE_DEFINES
 
 AC_OUTPUT([
 osmgpsmap-1.0.pc
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index cbc6461..07ccc2b 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -69,9 +69,9 @@ expand_content_files=
 # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
 # Only needed if you are using gtkdoc-scangobj to dynamically query widget
 # signals and properties.
-# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
 # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
-INCLUDES=-I$(top_srcdir) -I$(top_builddir) \
+AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(CAIRO_CFLAGS) \
diff --git a/examples/Makefile.am b/examples/Makefile.am
index ec123d4..fafab85 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -13,11 +13,7 @@ OSMGPSMAP_LIBS =            \
     $(SOUP24_LIBS)
 
 ## Demo Application
-if HAVE_GTHREAD
-noinst_PROGRAMS = mapviewer
-else
-noinst_PROGRAMS =
-endif
+noinst_PROGRAMS = mapviewer polygon editable_track
 
 mapviewer_SOURCES =         \
     mapviewer.c
@@ -34,6 +30,38 @@ mapviewer_LDADD =           \
     $(GTHREAD_LIBS)         \
     $(top_builddir)/src/libosmgpsmap-1.0.la
 
+
+polygon_SOURCES =         \
+    polygon.c
+
+polygon_CFLAGS =          \
+    -I$(top_srcdir)/src     \
+    $(WARN_CFLAGS)          \
+    $(DISABLE_DEPRECATED)   \
+    $(OSMGPSMAP_CFLAGS)     \
+    $(GTHREAD_CFLAGS)
+
+polygon_LDADD =           \
+    $(OSMGPSMAP_LIBS)       \
+    $(GTHREAD_LIBS)         \
+    $(top_builddir)/src/libosmgpsmap-1.0.la
+
+
+editable_track_SOURCES =         \
+    editable_track.c
+
+editable_track_CFLAGS =          \
+    -I$(top_srcdir)/src     \
+    $(WARN_CFLAGS)          \
+    $(DISABLE_DEPRECATED)   \
+    $(OSMGPSMAP_CFLAGS)     \
+    $(GTHREAD_CFLAGS)
+
+editable_track_LDADD =           \
+    $(OSMGPSMAP_LIBS)       \
+    $(GTHREAD_LIBS)         \
+    $(top_builddir)/src/libosmgpsmap-1.0.la
+
 ## Misc
 EXTRA_DIST = poi.png mapviewer.ui mapviewer.js README
 
diff --git a/examples/README b/examples/README
index 4009b04..1ccb183 100644
--- a/examples/README
+++ b/examples/README
@@ -3,6 +3,9 @@ osm-gps-map example applications
    C based demo app with many options. See '--help' for a list. Note, this
    must be executed from the examples directory so it can find the mapviewer.ui
    file.
+ * ./polygon
+   This example demonstrates editable polygons. Vertex points can be dragged. 
+   Clicking mid-points divides the line and creates another vertex.
  * ./mapviewer.py
    Python version of the C demo app, with examples showing how to do custom
    layers.
diff --git a/examples/editable_track.c b/examples/editable_track.c
new file mode 100644
index 0000000..07613aa
--- /dev/null
+++ b/examples/editable_track.c
@@ -0,0 +1,42 @@
+#include <gtk/gtk.h>
+#include "osm-gps-map.h"
+
+int
+main (int   argc,
+      char *argv[])
+{
+	OsmGpsMap *map;
+    GtkWidget *window;
+
+    gtk_init (&argc, &argv);
+
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_title (GTK_WINDOW (window), "Window");
+    g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+
+	map = g_object_new (OSM_TYPE_GPS_MAP, NULL);
+	gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(map));
+
+	OsmGpsMapTrack* track = osm_gps_map_track_new();
+
+	OsmGpsMapPoint* p1, *p2;
+	p1 = osm_gps_map_point_new_radians(1.25663706, -0.488692191);
+	p2 = osm_gps_map_point_new_radians(1.06465084, -0.750491578);
+
+	osm_gps_map_track_add_point(track, p1);
+	osm_gps_map_track_add_point(track, p2);
+
+	g_object_set(track, "editable", TRUE, NULL);
+
+	osm_gps_map_track_add(map, track);
+
+	gtk_widget_show (GTK_WIDGET(map));
+    gtk_widget_show (window);
+
+    gtk_main ();
+
+    return 0;
+}
+
+
diff --git a/examples/mapviewer.c b/examples/mapviewer.c
index 1acd779..bbe4272 100644
--- a/examples/mapviewer.c
+++ b/examples/mapviewer.c
@@ -30,6 +30,7 @@ static gboolean opt_friendly_cache = FALSE;
 static gboolean opt_no_cache = FALSE;
 static gboolean opt_debug = FALSE;
 static char *opt_cache_base_dir = NULL;
+static gboolean opt_editable_tracks = FALSE;
 static GOptionEntry entries[] =
 {
   { "friendly-cache", 'f', 0, G_OPTION_ARG_NONE, &opt_friendly_cache, "Store maps using friendly cache style (source name)", NULL },
@@ -37,6 +38,7 @@ static GOptionEntry entries[] =
   { "cache-basedir", 'b', 0, G_OPTION_ARG_FILENAME, &opt_cache_base_dir, "Cache basedir", NULL },
   { "debug", 'd', 0, G_OPTION_ARG_NONE, &opt_debug, "Enable debugging", NULL },
   { "map", 'm', 0, G_OPTION_ARG_INT, &opt_map_provider, "Map source", "N" },
+  { "editable-tracks", 'e', 0, G_OPTION_ARG_NONE, &opt_editable_tracks, "Make the tracks editable", NULL },
   { NULL }
 };
 
@@ -191,7 +193,7 @@ on_gps_color_changed (GtkColorChooser *widget, gpointer user_data)
     GdkRGBA c;
     OsmGpsMapTrack *track = OSM_GPS_MAP_TRACK(user_data);
     gtk_color_chooser_get_rgba (widget, &c);
-    g_object_set(track, "color", &c, NULL);
+    osm_gps_map_track_set_color(track, &c);
 }
 #else
 static void
@@ -200,7 +202,7 @@ on_gps_color_changed (GtkColorButton *widget, gpointer user_data)
     GdkRGBA c;
     OsmGpsMapTrack *track = OSM_GPS_MAP_TRACK(user_data);
     gtk_color_button_get_rgba (widget, &c);
-    g_object_set(track, "color", &c, NULL);
+    osm_gps_map_track_set_color(track, &c);
 }
 
 #endif
@@ -303,6 +305,9 @@ main (int argc, char **argv)
 
     //Add a second track for right clicks
     rightclicktrack = osm_gps_map_track_new();
+
+    if(opt_editable_tracks)
+        g_object_set(rightclicktrack, "editable", TRUE, NULL);
     osm_gps_map_track_add(OSM_GPS_MAP(map), rightclicktrack);
 
     g_free(cachedir);
diff --git a/examples/polygon.c b/examples/polygon.c
new file mode 100644
index 0000000..b8d1e89
--- /dev/null
+++ b/examples/polygon.c
@@ -0,0 +1,47 @@
+#include <gtk/gtk.h>
+#include "osm-gps-map.h"
+
+int
+main (int   argc,
+      char *argv[])
+{
+	OsmGpsMap *map;
+	OsmGpsMapPolygon* poly;
+    GtkWidget *window;
+
+    gtk_init (&argc, &argv);
+
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_title (GTK_WINDOW (window), "Window");
+    g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+
+	map = g_object_new (OSM_TYPE_GPS_MAP, NULL);
+	gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(map));
+
+	poly = osm_gps_map_polygon_new();
+	OsmGpsMapTrack* polytrack = osm_gps_map_track_new();
+
+	OsmGpsMapPoint* p1, *p2, *p3;
+	p1 = osm_gps_map_point_new_radians(1.25663706, -0.488692191);
+	p2 = osm_gps_map_point_new_radians(1.06465084, -0.750491578);
+	p3 = osm_gps_map_point_new_radians(1.064650849, -0.191986218);
+
+	osm_gps_map_track_add_point(polytrack, p1);
+	osm_gps_map_track_add_point(polytrack, p2);
+	osm_gps_map_track_add_point(polytrack, p3);
+
+	g_object_set(poly, "track", polytrack, NULL);
+	g_object_set(poly, "editable", TRUE, NULL);
+
+	osm_gps_map_polygon_add(map, poly);
+
+	gtk_widget_show (GTK_WIDGET(map));
+    gtk_widget_show (window);
+
+    gtk_main ();
+
+    return 0;
+}
+
+
diff --git a/m4/gtk-doc.m4 b/m4/gtk-doc.m4
index 0ada151..3675543 100644
--- a/m4/gtk-doc.m4
+++ b/m4/gtk-doc.m4
@@ -1,6 +1,6 @@
 dnl -*- mode: autoconf -*-
 
-# serial 1
+# serial 2
 
 dnl Usage:
 dnl   GTK_DOC_CHECK([minimum-gtk-doc-version])
@@ -10,8 +10,24 @@ AC_DEFUN([GTK_DOC_CHECK],
   AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
   AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
 
+  ifelse([$1],[],[gtk_doc_requires="gtk-doc"],[gtk_doc_requires="gtk-doc >= $1"])
+  AC_MSG_CHECKING([for gtk-doc])
+  PKG_CHECK_EXISTS([$gtk_doc_requires],[have_gtk_doc=yes],[have_gtk_doc=no])
+  AC_MSG_RESULT($have_gtk_doc)
+
+  if test "$have_gtk_doc" = "no"; then
+      AC_MSG_WARN([
+  You will not be able to create source packages with 'make dist'
+  because $gtk_doc_requires is not found.])
+  fi
+
   dnl check for tools we added during development
-  AC_PATH_PROG([GTKDOC_CHECK],[gtkdoc-check])
+  dnl Use AC_CHECK_PROG to avoid the check target using an absolute path that
+  dnl may not be writable by the user. Currently, automake requires that the
+  dnl test name must end in '.test'.
+  dnl https://bugzilla.gnome.org/show_bug.cgi?id=701638
+  AC_CHECK_PROG([GTKDOC_CHECK],[gtkdoc-check],[gtkdoc-check.test])
+  AC_PATH_PROG([GTKDOC_CHECK_PATH],[gtkdoc-check])
   AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true])
   AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf])
 
@@ -28,22 +44,22 @@ AC_DEFUN([GTK_DOC_CHECK],
                    [use gtk-doc to build documentation [[default=no]]]),,
     [enable_gtk_doc=no])
 
-  if test x$enable_gtk_doc = xyes; then
-    ifelse([$1],[],
-      [PKG_CHECK_EXISTS([gtk-doc],,
-                        AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))],
-      [PKG_CHECK_EXISTS([gtk-doc >= $1],,
-                        AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build $PACKAGE_NAME]))])
-    dnl don't check for glib if we build glib
-    if test "x$PACKAGE_NAME" != "xglib"; then
-      dnl don't fail if someone does not have glib
-      PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0,,)
-    fi
-  fi
-
   AC_MSG_CHECKING([whether to build gtk-doc documentation])
   AC_MSG_RESULT($enable_gtk_doc)
 
+  if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then
+    AC_MSG_ERROR([
+  You must have $gtk_doc_requires installed to build documentation for
+  $PACKAGE_NAME. Please install gtk-doc or disable building the
+  documentation by adding '--disable-gtk-doc' to '[$]0'.])
+  fi
+
+  dnl don't check for glib if we build glib
+  if test "x$PACKAGE_NAME" != "xglib"; then
+    dnl don't fail if someone does not have glib
+    PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0,,[:])
+  fi
+
   dnl enable/disable output formats
   AC_ARG_ENABLE([gtk-doc-html],
     AS_HELP_STRING([--enable-gtk-doc-html],
@@ -58,7 +74,12 @@ AC_DEFUN([GTK_DOC_CHECK],
     enable_gtk_doc_pdf=no
   fi
 
+  if test -z "$AM_DEFAULT_VERBOSITY"; then
+    AM_DEFAULT_VERBOSITY=1
+  fi
+  AC_SUBST([AM_DEFAULT_VERBOSITY])
 
+  AM_CONDITIONAL([HAVE_GTK_DOC], [test x$have_gtk_doc = xyes])
   AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes])
   AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes])
   AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes])
diff --git a/src/Makefile.am b/src/Makefile.am
index 66d67da..d6e9596 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,6 +42,7 @@ sources_public_h =          \
     osm-gps-map-osd.h       \
     osm-gps-map-layer.h     \
     osm-gps-map-track.h     \
+	osm-gps-map-polygon.h	\
     osm-gps-map-point.h     \
     osm-gps-map-image.h     \
     osm-gps-map-source.h    \
@@ -54,6 +55,7 @@ sources_c =                 \
     osm-gps-map-osd.c       \
     osm-gps-map-layer.c     \
     osm-gps-map-track.c     \
+	osm-gps-map-polygon.c	\
     osm-gps-map-point.c     \
     osm-gps-map-image.c     \
     osm-gps-map-source.c    \
diff --git a/src/converter.c b/src/converter.c
index c83d20a..cfa7093 100644
--- a/src/converter.c
+++ b/src/converter.c
@@ -3,6 +3,7 @@
 /*
  * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
  * Copyright (C) 2013 John Stowers <john.stowers at gmail.com>
+ * Copyright (C) 2014 Martijn Goedhart <goedhart.martijn at gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -20,10 +21,22 @@
 
 #include <math.h>
 #include <stdio.h>
+#include <float.h>
 
 #include "private.h"
 #include "converter.h"
 
+/*
+ * The (i)logb(x) function is equal to `floor(log(x) / log(2))` or
+ * `floor(log2(x))`, but probably faster and also accepts negative values.
+ * But this is only true when FLT_RADIX equals 2, which is on allmost all
+ * machine.
+ */
+#if FLT_RADIX == 2
+#define LOG2(x) (ilogb(x))
+#else
+#define LOG2(x) ((int)floor(log2(abs(x))))
+#endif
 
 float
 deg2rad(float deg)
@@ -102,3 +115,18 @@ pixel2lat(  float zoom,
 
     return lat;
 }
+
+int
+latlon2zoom(int pix_height,
+	    int pix_width,
+	    float lat1,
+	    float lat2,
+	    float lon1,
+	    float lon2)
+{
+    float lat1_m = atanh(sin(lat1));
+    float lat2_m = atanh(sin(lat2));
+    int zoom_lon = LOG2((double)(2 * pix_width * M_PI) / (TILESIZE * (lon2 - lon1)));
+    int zoom_lat = LOG2((double)(2 * pix_height * M_PI) / (TILESIZE * (lat2_m - lat1_m)));
+    return MIN(zoom_lon, zoom_lat);
+}
diff --git a/src/converter.h b/src/converter.h
index 4e4fd1f..5051f58 100644
--- a/src/converter.h
+++ b/src/converter.h
@@ -42,3 +42,11 @@ pixel2lon(  float zoom,
 float
 pixel2lat(  float zoom,
             int pixel_y);
+
+int
+latlon2zoom(int pix_height,
+            int pix_width,
+            float lat1,
+            float lat2,
+            float lon1,
+            float lon2);
diff --git a/src/osm-gps-map-image.c b/src/osm-gps-map-image.c
index b57cdee..969930d 100644
--- a/src/osm-gps-map-image.c
+++ b/src/osm-gps-map-image.c
@@ -44,6 +44,7 @@ enum
     PROP_Y_ALIGN,
     PROP_POINT,
     PROP_Z_ORDER,
+    PROP_ROTATION
 };
 
 struct _OsmGpsMapImagePrivate
@@ -55,6 +56,7 @@ struct _OsmGpsMapImagePrivate
     gfloat          xalign;
     gfloat          yalign;
     int             zorder;
+    float           rotation;
 };
 
 static void
@@ -81,6 +83,9 @@ osm_gps_map_image_get_property (GObject    *object,
         case PROP_Z_ORDER:
             g_value_set_int   (value, priv->zorder);
             break;
+        case PROP_ROTATION:
+            g_value_set_float(value, priv->rotation);
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -114,6 +119,9 @@ osm_gps_map_image_set_property (GObject      *object,
         case PROP_Z_ORDER:
             priv->zorder = g_value_get_int (value);
             break;
+        case PROP_ROTATION:
+            priv->rotation = g_value_get_float(value);
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -193,6 +201,16 @@ osm_gps_map_image_class_init (OsmGpsMapImageClass *klass)
                                                         100, /* maximum property value */
                                                           0,
                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+    g_object_class_install_property (object_class,
+                                     PROP_ROTATION,
+                                     g_param_spec_float ("rotation",
+                                                       "rotation",
+                                                       "image rotation",
+                                                       -180.0, /* minimum property value */
+                                                        180.0, /* maximum property value */
+                                                          0.0f,
+                                                        G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
 }
 
 static void
@@ -222,9 +240,17 @@ osm_gps_map_image_draw (OsmGpsMapImage *object, cairo_t *cr, GdkRectangle *rect)
     x = rect->x - xoffset;
     y = rect->y - yoffset;
 
+     cairo_translate(cr, x+(priv->w/2), y+(priv->h/2));
+    cairo_rotate(cr, deg2rad(priv->rotation));
+    cairo_translate(cr,  -(x+(priv->w/2)), -(y+(priv->h/2)));
+
     gdk_cairo_set_source_pixbuf (cr, priv->pixbuf, x, y);
     cairo_paint (cr);
 
+    cairo_translate(cr, x+(priv->w/2), y+(priv->h/2));
+    cairo_rotate(cr, -deg2rad(priv->rotation));
+    cairo_translate(cr,  -(x+(priv->w/2)), -(y+(priv->h/2)));
+
     rect->width = priv->w;
     rect->height = priv->h;
 }
@@ -242,3 +268,14 @@ osm_gps_map_image_get_zorder(OsmGpsMapImage *object)
     g_return_val_if_fail (OSM_IS_GPS_MAP_IMAGE (object), 0);
     return object->priv->zorder;
 }
+
+float osm_gps_map_image_get_rotation(OsmGpsMapImage* object)
+{
+    return object->priv->rotation;
+}
+
+void osm_gps_map_image_set_rotation(OsmGpsMapImage* object, float rot)
+{
+    object->priv->rotation = rot;
+}
+
diff --git a/src/osm-gps-map-image.h b/src/osm-gps-map-image.h
index f1f92a4..ba31fcc 100644
--- a/src/osm-gps-map-image.h
+++ b/src/osm-gps-map-image.h
@@ -57,6 +57,8 @@ OsmGpsMapImage *osm_gps_map_image_new (void);
 void            osm_gps_map_image_draw (OsmGpsMapImage *object, cairo_t *cr, GdkRectangle *rect);
 const OsmGpsMapPoint *osm_gps_map_image_get_point(OsmGpsMapImage *object);
 gint osm_gps_map_image_get_zorder(OsmGpsMapImage *object);
+float osm_gps_map_image_get_rotation(OsmGpsMapImage* object);
+void osm_gps_map_image_set_rotation(OsmGpsMapImage* object, float rot);
 
 G_END_DECLS
 
diff --git a/src/osm-gps-map-polygon.c b/src/osm-gps-map-polygon.c
new file mode 100644
index 0000000..29c437f
--- /dev/null
+++ b/src/osm-gps-map-polygon.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2013 Samuel Cowen <samuel.cowen at camelsoftware.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <gdk/gdk.h>
+
+#include "converter.h"
+#include "osm-gps-map-polygon.h"
+
+G_DEFINE_TYPE (OsmGpsMapPolygon, osm_gps_map_polygon, G_TYPE_OBJECT)
+
+enum
+{
+    PROP_0,
+    PROP_VISIBLE,
+    PROP_TRACK,
+	PROP_SHADED,
+    PROP_EDITABLE
+};
+
+struct _OsmGpsMapPolygonPrivate
+{
+    OsmGpsMapTrack* track;
+	gboolean visible;
+    gboolean editable;
+	gboolean shaded;
+};
+
+#define DEFAULT_R   (60000)
+#define DEFAULT_G   (0)
+#define DEFAULT_B   (0)
+#define DEFAULT_A   (0.6)
+
+static void
+osm_gps_map_polygon_get_property (GObject    *object,
+                                guint       property_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+    OsmGpsMapPolygonPrivate *priv = OSM_GPS_MAP_POLYGON(object)->priv;
+
+    switch (property_id)
+    {
+        case PROP_VISIBLE:
+            g_value_set_boolean(value, priv->visible);
+            break;
+        case PROP_TRACK:
+            g_value_set_pointer(value, priv->track);
+            break;
+		case PROP_SHADED:
+			g_value_set_boolean(value, priv->shaded);
+			break;
+        case PROP_EDITABLE:
+            g_value_set_boolean(value, priv->editable);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+osm_gps_map_polygon_set_property (GObject      *object,
+                                guint         property_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+    OsmGpsMapPolygonPrivate *priv = OSM_GPS_MAP_POLYGON(object)->priv;
+
+    switch (property_id)
+    {
+        case PROP_VISIBLE:
+            priv->visible = g_value_get_boolean (value);
+            break;
+        case PROP_TRACK:
+            priv->track = g_value_get_pointer (value);
+            break;
+        case PROP_SHADED:
+			priv->shaded = g_value_get_boolean(value);
+			break;
+        case PROP_EDITABLE:
+            priv->editable = g_value_get_boolean(value);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+osm_gps_map_polygon_dispose (GObject *object)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP_POLYGON (object));
+	OsmGpsMapPolygon* poly = OSM_GPS_MAP_POLYGON(object);
+	g_object_unref(poly->priv->track);
+
+    G_OBJECT_CLASS (osm_gps_map_polygon_parent_class)->dispose (object);
+}
+
+static void
+osm_gps_map_polygon_finalize (GObject *object)
+{
+    G_OBJECT_CLASS (osm_gps_map_polygon_parent_class)->finalize (object);
+}
+
+static void
+osm_gps_map_polygon_class_init (OsmGpsMapPolygonClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    g_type_class_add_private (klass, sizeof (OsmGpsMapPolygonPrivate));
+
+    object_class->get_property = osm_gps_map_polygon_get_property;
+    object_class->set_property = osm_gps_map_polygon_set_property;
+    object_class->dispose = osm_gps_map_polygon_dispose;
+    object_class->finalize = osm_gps_map_polygon_finalize;
+
+    g_object_class_install_property (object_class,
+                                     PROP_VISIBLE,
+                                     g_param_spec_boolean ("visible",
+                                                           "visible",
+                                                           "should this poly be visible",
+                                                           TRUE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+    g_object_class_install_property (object_class,
+                                     PROP_TRACK,
+                                     g_param_spec_pointer ("track",
+                                                           "track",
+                                                           "list of points for the polygon",
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+
+    g_object_class_install_property (object_class,
+                                     PROP_EDITABLE,
+                                     g_param_spec_boolean ("editable",
+                                                           "editable",
+                                                           "should this polygon be editable",
+                                                           FALSE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+                                     PROP_SHADED,
+                                     g_param_spec_boolean ("shaded",
+                                                           "shaded",
+                                                           "should this polygon be shaded",
+                                                           TRUE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+}
+
+static void
+osm_gps_map_polygon_init (OsmGpsMapPolygon *self)
+{
+    self->priv = G_TYPE_INSTANCE_GET_PRIVATE((self), OSM_TYPE_GPS_MAP_POLYGON, OsmGpsMapPolygonPrivate);
+	self->priv->track = osm_gps_map_track_new();
+}
+
+OsmGpsMapTrack*
+osm_gps_map_polygon_get_track(OsmGpsMapPolygon* poly)
+{
+	return poly->priv->track;
+}
+
+OsmGpsMapPolygon *
+osm_gps_map_polygon_new (void)
+{
+    return g_object_new (OSM_TYPE_GPS_MAP_POLYGON, "track", osm_gps_map_track_new(), NULL);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/osm-gps-map-polygon.h b/src/osm-gps-map-polygon.h
new file mode 100644
index 0000000..5eb3139
--- /dev/null
+++ b/src/osm-gps-map-polygon.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 Samuel Cowen <samuel.cowen at camelsoftware.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _OSM_GPS_MAP_POLYGON_H
+#define _OSM_GPS_MAP_POLYGON_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#include "osm-gps-map-track.h"
+
+#define OSM_TYPE_GPS_MAP_POLYGON              osm_gps_map_polygon_get_type()
+#define OSM_GPS_MAP_POLYGON(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP_POLYGON, OsmGpsMapPolygon))
+#define OSM_GPS_MAP_POLYGON_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP_POLYGON, OsmGpsMapPolygonClass))
+#define OSM_IS_GPS_MAP_POLYGON(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP_POLYGON))
+#define OSM_IS_GPS_MAP_POLYGON_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP_POLYGON))
+#define OSM_GPS_MAP_POLYGON_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP_POLYGON, OsmGpsMapPolygonClass))
+
+typedef struct _OsmGpsMapPolygon OsmGpsMapPolygon;
+typedef struct _OsmGpsMapPolygonClass OsmGpsMapPolygonClass;
+typedef struct _OsmGpsMapPolygonPrivate OsmGpsMapPolygonPrivate;
+
+struct _OsmGpsMapPolygon
+{
+    GObject parent;
+
+    OsmGpsMapPolygonPrivate *priv;
+};
+
+struct _OsmGpsMapPolygonClass
+{
+    GObjectClass parent_class;
+};
+
+GType osm_gps_map_polygon_get_type (void) G_GNUC_CONST;
+
+OsmGpsMapPolygon*		osm_gps_map_polygon_new           (void);
+OsmGpsMapTrack*			osm_gps_map_polygon_get_track(OsmGpsMapPolygon* poly);
+
+G_END_DECLS
+
+#endif /* _OSM_GPS_MAP_POLYGON_H */
diff --git a/src/osm-gps-map-source.c b/src/osm-gps-map-source.c
index 9dbb807..06f960f 100644
--- a/src/osm-gps-map-source.c
+++ b/src/osm-gps-map-source.c
@@ -53,12 +53,6 @@ osm_gps_map_source_get_friendly_name(OsmGpsMapSource_t source)
             return "Virtual Earth Satellite";
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
             return "Virtual Earth Hybrid";
-        case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
-            return "Yahoo Maps";
-        case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
-            return "Yahoo Satellite";
-        case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
-            return "Yahoo Hybrid";
         case OSM_GPS_MAP_SOURCE_LAST:
         default:
             return NULL;
@@ -109,16 +103,6 @@ osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source)
             return "http://a#R.ortho.tiles.virtualearth.net/tiles/a#W.jpeg?g=50";
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
             return "http://a#R.ortho.tiles.virtualearth.net/tiles/h#W.jpeg?g=50";
-        case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
-        case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
-        case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
-            /* TODO: Implement signed Y, aka U
-             * http://us.maps3.yimg.com/aerial.maps.yimg.com/ximg?v=1.7&t=a&s=256&x=%d&y=%-d&z=%d 
-             *  x = tilex,
-             *  y = (1 << (MAX_ZOOM - zoom)) - tiley - 1,
-             *  z = zoom - (MAX_ZOOM - 17));
-             */
-            return NULL;
         case OSM_GPS_MAP_SOURCE_LAST:
         default:
             return NULL;
@@ -143,9 +127,6 @@ osm_gps_map_source_get_image_format(OsmGpsMapSource_t source)
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
-        case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
-        case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
-        case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
         case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
         case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
             return "jpg";
@@ -180,9 +161,6 @@ osm_gps_map_source_get_max_zoom(OsmGpsMapSource_t source)
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
-        case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
-        case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
-        case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
             return 17;
         case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
             return 15;
diff --git a/src/osm-gps-map-source.h b/src/osm-gps-map-source.h
index 073c0c3..0237700 100644
--- a/src/osm-gps-map-source.h
+++ b/src/osm-gps-map-source.h
@@ -38,9 +38,6 @@ typedef enum {
     OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET,
     OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE,
     OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID,
-    OSM_GPS_MAP_SOURCE_YAHOO_STREET,
-    OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE,
-    OSM_GPS_MAP_SOURCE_YAHOO_HYBRID,
     OSM_GPS_MAP_SOURCE_OSMC_TRAILS,
 
     OSM_GPS_MAP_SOURCE_LAST
diff --git a/src/osm-gps-map-track.c b/src/osm-gps-map-track.c
index c388917..6faac49 100644
--- a/src/osm-gps-map-track.c
+++ b/src/osm-gps-map-track.c
@@ -29,6 +29,7 @@
  **/
 
 #include <gdk/gdk.h>
+#include <math.h>
 
 #include "converter.h"
 #include "osm-gps-map-track.h"
@@ -42,13 +43,17 @@ enum
     PROP_TRACK,
     PROP_LINE_WIDTH,
     PROP_ALPHA,
-    PROP_COLOR
+    PROP_COLOR,
+    PROP_EDITABLE
 };
 
 enum
 {
-	POINT_ADDED,
-	LAST_SIGNAL
+    POINT_ADDED,
+    POINT_CHANGED,
+    POINT_INSERTED,
+    POINT_REMOVED,
+    LAST_SIGNAL
 };
 
 static guint signals[LAST_SIGNAL] = {0,};
@@ -60,9 +65,10 @@ struct _OsmGpsMapTrackPrivate
     gfloat linewidth;
     gfloat alpha;
     GdkRGBA color;
+    gboolean editable;
 };
 
-#define DEFAULT_R   (60000)
+#define DEFAULT_R   (0.6)
 #define DEFAULT_G   (0)
 #define DEFAULT_B   (0)
 #define DEFAULT_A   (0.6)
@@ -92,6 +98,9 @@ osm_gps_map_track_get_property (GObject    *object,
         case PROP_COLOR:
             g_value_set_boxed(value, &priv->color);
             break;
+        case PROP_EDITABLE:
+            g_value_set_boolean(value, priv->editable);
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -124,7 +133,12 @@ osm_gps_map_track_set_property (GObject      *object,
             priv->color.red = c->red;
             priv->color.green = c->green;
             priv->color.blue = c->blue;
+            printf("\n%f %f %f\n", c->red, c->green, c->blue);
+            fflush(stdout);
             } break;
+        case PROP_EDITABLE:
+            priv->editable = g_value_get_boolean(value);
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -203,9 +217,17 @@ osm_gps_map_track_class_init (OsmGpsMapTrackClass *klass)
                                      g_param_spec_boxed ("color",
                                                          "color",
                                                          "color of the track",
-                                                         GDK_TYPE_COLOR,
+                                                         GDK_TYPE_RGBA,
                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
 
+    g_object_class_install_property (object_class,
+                                     PROP_EDITABLE,
+                                     g_param_spec_boolean ("editable",
+                                                           "editable",
+                                                           "should this track be editable",
+                                                           FALSE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
 	/**
 	 * OsmGpsMapTrack::point-added:
 	 * @self: A #OsmGpsMapTrack
@@ -222,6 +244,40 @@ osm_gps_map_track_class_init (OsmGpsMapTrackClass *klass)
 	                            G_TYPE_NONE,
 	                            1,
                                 OSM_TYPE_GPS_MAP_POINT);
+
+    
+    signals [POINT_CHANGED] = g_signal_new ("point-changed",
+	                            OSM_TYPE_GPS_MAP_TRACK,
+	                            G_SIGNAL_RUN_FIRST,
+	                            0,
+	                            NULL,
+	                            NULL,
+	                            g_cclosure_marshal_VOID__VOID,
+	                            G_TYPE_NONE,
+	                            1,
+	                            G_TYPE_INT);
+
+    signals [POINT_INSERTED] = g_signal_new ("point-inserted",
+	                            OSM_TYPE_GPS_MAP_TRACK,
+	                            G_SIGNAL_RUN_FIRST,
+	                            0,
+	                            NULL,
+	                            NULL,
+	                            g_cclosure_marshal_VOID__INT,
+	                            G_TYPE_NONE,
+	                            1,
+	                            G_TYPE_INT);
+
+    signals [POINT_REMOVED] = g_signal_new ("point-removed",
+	                            OSM_TYPE_GPS_MAP_TRACK,
+	                            G_SIGNAL_RUN_FIRST,
+	                            0,
+	                            NULL,
+	                            NULL,
+	                            g_cclosure_marshal_VOID__INT,
+	                            G_TYPE_NONE,
+	                            1,
+	                            G_TYPE_INT);
 }
 
 static void
@@ -245,6 +301,34 @@ osm_gps_map_track_add_point (OsmGpsMapTrack *track, const OsmGpsMapPoint *point)
     g_signal_emit (track, signals[POINT_ADDED], 0, p);
 }
 
+void
+osm_gps_map_track_remove_point(OsmGpsMapTrack* track, int pos)
+{
+    OsmGpsMapTrackPrivate *priv = track->priv;
+    gpointer pgl = g_slist_nth_data(priv->track, pos);
+    priv->track = g_slist_remove(priv->track, pgl);
+    g_signal_emit(track, signals[POINT_REMOVED], 0, pos);
+}
+
+int osm_gps_map_track_n_points(OsmGpsMapTrack* track)
+{
+    return g_slist_length(track->priv->track);
+}
+
+void osm_gps_map_track_insert_point(OsmGpsMapTrack* track, OsmGpsMapPoint* np, int pos)
+{
+    OsmGpsMapTrackPrivate* priv = track->priv;
+    priv->track = g_slist_insert(priv->track, np, pos);
+    g_signal_emit(track, signals[POINT_INSERTED], 0, pos);
+}
+
+OsmGpsMapPoint* osm_gps_map_track_get_point(OsmGpsMapTrack* track, int pos)
+{
+    OsmGpsMapTrackPrivate* priv = track->priv;
+    return g_slist_nth_data(priv->track, pos);
+}
+
+
 GSList *
 osm_gps_map_track_get_points (OsmGpsMapTrack *track)
 {
@@ -252,6 +336,15 @@ osm_gps_map_track_get_points (OsmGpsMapTrack *track)
     return track->priv->track;
 }
 
+void                
+osm_gps_map_track_set_color (OsmGpsMapTrack *track, GdkRGBA *color)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP_TRACK (track));
+    track->priv->color.red = color->red;
+    track->priv->color.green = color->green;
+    track->priv->color.blue = color->blue;
+}
+
 void
 osm_gps_map_track_get_color (OsmGpsMapTrack *track, GdkRGBA *color)
 {
@@ -261,6 +354,28 @@ osm_gps_map_track_get_color (OsmGpsMapTrack *track, GdkRGBA *color)
     color->blue = track->priv->color.blue;
 }
 
+double
+osm_gps_map_track_get_length(OsmGpsMapTrack* track)
+{
+    GSList* points = track->priv->track;
+    double ret = 0;
+    OsmGpsMapPoint* point_a = NULL;
+    OsmGpsMapPoint* point_b = NULL;
+       
+    while(points)
+    {
+        point_a = point_b;
+        point_b = points->data;
+        if(point_a)
+        {
+            ret += acos(sin(point_a->rlat)*sin(point_b->rlat) 
+                    + cos(point_a->rlat)*cos(point_b->rlat)*cos(point_b->rlon-point_a->rlon)) * 6371109; //the mean raduis of earth
+        }
+        points = points->next;
+    }
+    return ret;
+}
+
 
 OsmGpsMapTrack *
 osm_gps_map_track_new (void)
diff --git a/src/osm-gps-map-track.h b/src/osm-gps-map-track.h
index ac5e1ba..ed01e9e 100644
--- a/src/osm-gps-map-track.h
+++ b/src/osm-gps-map-track.h
@@ -78,8 +78,33 @@ void                osm_gps_map_track_add_point     (OsmGpsMapTrack *track, cons
  * Since: 0.7.0
  **/
 GSList *            osm_gps_map_track_get_points    (OsmGpsMapTrack *track);
+void                osm_gps_map_track_set_color     (OsmGpsMapTrack *track, GdkRGBA *color);
 void                osm_gps_map_track_get_color     (OsmGpsMapTrack *track, GdkRGBA *color);
 
+/**
+ * osm_gps_map_track_remove_point:
+ * @track (in): a #OsmGpsMapTrack
+ * @pos: Position of the point to remove
+ *
+ **/
+void                osm_gps_map_track_remove_point(OsmGpsMapTrack* track, int pos);
+
+/**
+ *
+ **/
+int                 osm_gps_map_track_n_points(OsmGpsMapTrack* track);
+void                osm_gps_map_track_insert_point(OsmGpsMapTrack* track, OsmGpsMapPoint* np, int pos);
+OsmGpsMapPoint*     osm_gps_map_track_get_point(OsmGpsMapTrack* track, int pos);
+
+/**
+ * osm_gps_map_track_get_length:
+ * @track (in): a #OsmGpsMapTrack
+ * 
+ * Returns: the length of the track in meters.
+ **/
+double              osm_gps_map_track_get_length(OsmGpsMapTrack* track);
+
+
 G_END_DECLS
 
 #endif /* _OSM_GPS_MAP_TRACK_H */
diff --git a/src/osm-gps-map-widget.c b/src/osm-gps-map-widget.c
index b6fd542..a14b2f0 100644
--- a/src/osm-gps-map-widget.c
+++ b/src/osm-gps-map-widget.c
@@ -148,6 +148,7 @@
 #define USER_AGENT                  "libosmgpsmap/1.0"
 #define DOWNLOAD_RETRIES            3
 #define MAX_DOWNLOAD_TILES          10000
+#define DOT_RADIUS                  4.0
 
 struct _OsmGpsMapPrivate
 {
@@ -205,6 +206,7 @@ struct _OsmGpsMapPrivate
     //additional images or tracks added to the map
     GSList *tracks;
     GSList *images;
+    GSList *polygons;
 
     //Used for storing the joined tiles
     cairo_surface_t *pixmap;
@@ -226,6 +228,10 @@ struct _OsmGpsMapPrivate
     int drag_limit;
     guint drag_expose_source;
 
+    /* Properties for dragging a point with right mouse button. */
+    OsmGpsMapPoint* drag_point;
+    OsmGpsMapTrack* drag_track;
+
     /* for customizing the redering of the gps track */
     int ui_gps_point_inner_radius;
     int ui_gps_point_outer_radius;
@@ -248,6 +254,7 @@ struct _OsmGpsMapPrivate
     guint is_button_down : 1;
     guint is_fullscreen : 1;
     guint is_google : 1;
+    guint is_dragging_point : 1;
 };
 
 typedef struct
@@ -308,8 +315,6 @@ static gchar    *replace_string(const gchar *src, const gchar *from, const gchar
 static gchar    *replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y);
 static void     osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data);
 static void     osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw);
-static gboolean osm_gps_map_map_redraw (OsmGpsMap *map);
-static void     osm_gps_map_map_redraw_idle (OsmGpsMap *map);
 static GdkPixbuf* osm_gps_map_render_tile_upscaled (OsmGpsMap *map, GdkPixbuf *tile, int tile_zoom, int zoom, int x, int y);
 
 static void
@@ -1150,22 +1155,27 @@ osm_gps_map_print_track (OsmGpsMap *map, OsmGpsMapTrack *track, cairo_t *cr)
     GdkRGBA color;
 
     g_object_get (track,
-            "track", &points,
-            "line-width", &lw,
-            "alpha", &alpha,
-            NULL);
+                  "track", &points,
+                  "line-width", &lw,
+                  "alpha", &alpha,
+                  NULL);
     osm_gps_map_track_get_color(track, &color);
 
     if (points == NULL)
         return;
 
+    gboolean path_editable = FALSE;
+    g_object_get(track, "editable", &path_editable, NULL);
+
     cairo_set_line_width (cr, lw);
-    cairo_set_source_rgba (cr, color.red/65535.0, color.green/65535.0, color.blue/65535.0, alpha);
+    cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha);
     cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
     cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
 
     map_x0 = priv->map_x - EXTRA_BORDER;
     map_y0 = priv->map_y - EXTRA_BORDER;
+
+    int last_x = 0, last_y = 0;
     for(pt = points; pt != NULL; pt = pt->next)
     {
         OsmGpsMapPoint *tp = pt->data;
@@ -1174,24 +1184,42 @@ osm_gps_map_print_track (OsmGpsMap *map, OsmGpsMapTrack *track, cairo_t *cr)
         y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0;
 
         /* first time through loop */
-        if (pt == points) {
+        if (pt == points)
             cairo_move_to(cr, x, y);
-        }
 
         cairo_line_to(cr, x, y);
+        cairo_stroke(cr);
+        if(path_editable)
+        {
+            cairo_arc (cr, x, y, DOT_RADIUS, 0.0, 2 * M_PI);
+            cairo_stroke(cr);
+
+            if(pt != points)
+            {
+                cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha*0.75);
+                cairo_arc(cr, (last_x + x)/2.0, (last_y+y)/2.0, DOT_RADIUS, 0.0, 2*M_PI);
+                cairo_stroke(cr);
+                cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha);
+            }
+        }
+
+        cairo_move_to(cr, x, y);
 
         max_x = MAX(x,max_x);
         min_x = MIN(x,min_x);
         max_y = MAX(y,max_y);
         min_y = MIN(y,min_y);
+
+        last_x = x;
+        last_y = y;
     }
 
     gtk_widget_queue_draw_area (
-                                GTK_WIDGET(map),
-                                min_x - lw,
-                                min_y - lw,
-                                max_x + (lw * 2),
-                                max_y + (lw * 2));
+        GTK_WIDGET(map),
+        min_x - lw,
+        min_y - lw,
+        max_x + (lw * 2),
+        max_y + (lw * 2));
 
     cairo_stroke(cr);
 }
@@ -1216,6 +1244,124 @@ osm_gps_map_print_tracks (OsmGpsMap *map, cairo_t *cr)
     }
 }
 
+static void
+osm_gps_map_print_polygon (OsmGpsMap *map, OsmGpsMapPolygon *poly, cairo_t *cr)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    GSList *pt,*points;
+    int x,y;
+    int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
+    gfloat lw, alpha;
+    int map_x0, map_y0;
+    GdkRGBA color;
+
+    OsmGpsMapTrack* track = osm_gps_map_polygon_get_track(poly);
+
+    if(!track)
+        return;
+    g_object_get (track,
+                  "track", &points,
+                  "line-width", &lw,
+                  "alpha", &alpha,
+                  NULL);
+    osm_gps_map_track_get_color(track, &color);
+
+    if (points == NULL)
+        return;
+
+    gboolean path_editable = FALSE;
+    gboolean poly_shaded = FALSE;
+    g_object_get(poly, "editable", &path_editable, NULL);
+    g_object_get(poly, "shaded", &poly_shaded, NULL);
+
+    cairo_set_line_width (cr, lw);
+    cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+
+    map_x0 = priv->map_x - EXTRA_BORDER;
+    map_y0 = priv->map_y - EXTRA_BORDER;
+
+    int first_x = 0, first_y = 0;
+    for(pt = points; pt != NULL; pt = pt->next)
+    {
+        OsmGpsMapPoint *tp = pt->data;
+
+        x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0;
+        y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0;
+
+        /* first time through loop */
+        if (pt == points)
+        {
+            cairo_move_to(cr, x, y);
+            first_x = x; first_y = y;
+        }
+
+        cairo_line_to(cr, x, y);
+    }
+    //close off polygon
+    cairo_line_to(cr, first_x, first_y);
+    if(poly_shaded)
+        cairo_fill(cr);
+    else
+        cairo_stroke(cr);
+
+    if(path_editable)
+    {
+        int last_x = 0, last_y = 0;
+        for(pt = points; pt != NULL; pt = pt->next)
+        {
+            OsmGpsMapPoint *tp = pt->data;
+
+            x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0;
+            y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0;
+
+            cairo_arc (cr, x, y, DOT_RADIUS, 0.0, 2 * M_PI);
+            cairo_stroke(cr);
+
+            if(pt != points)
+            {
+                cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha*0.75);
+                cairo_arc(cr, (last_x + x)/2.0, (last_y+y)/2.0, DOT_RADIUS, 0.0, 2*M_PI);
+                cairo_stroke(cr);
+                cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha);
+            }
+            last_x = x; last_y = y;
+        }
+
+        x = first_x; y = first_y;
+        cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha*0.75);
+        cairo_arc(cr, (last_x + x)/2.0, (last_y+y)/2.0, DOT_RADIUS, 0.0, 2*M_PI);
+        cairo_stroke(cr);
+        cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha);
+    }
+
+    gtk_widget_queue_draw_area (
+        GTK_WIDGET(map),
+        min_x - lw,
+        min_y - lw,
+        max_x + (lw * 2),
+        max_y + (lw * 2));
+
+}
+
+static void
+osm_gps_map_print_polygons (OsmGpsMap *map, cairo_t* cr)
+{
+    GSList *tmp;
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (priv->polygons) {
+        tmp = priv->polygons;
+        while (tmp != NULL) {
+            osm_gps_map_print_polygon (map, OSM_GPS_MAP_POLYGON(tmp->data), cr);
+            tmp = g_slist_next(tmp);
+        }
+    }
+}
+
+
 static gboolean
 osm_gps_map_purge_cache_check(gpointer key, gpointer value, gpointer user)
 {
@@ -1235,7 +1381,7 @@ osm_gps_map_purge_cache (OsmGpsMap *map)
    g_hash_table_foreach_remove(priv->tile_cache, osm_gps_map_purge_cache_check, priv);
 }
 
-static gboolean
+gboolean
 osm_gps_map_map_redraw (OsmGpsMap *map)
 {
     cairo_t *cr;
@@ -1285,6 +1431,7 @@ osm_gps_map_map_redraw (OsmGpsMap *map)
     osm_gps_map_fill_tiles_pixel(map, cr);
 
     osm_gps_map_print_tracks(map, cr);
+    osm_gps_map_print_polygons(map, cr);
     osm_gps_map_print_images(map, cr);
 
     /* draw the gps point using the appropriate virtual private method */
@@ -1310,7 +1457,7 @@ osm_gps_map_map_redraw (OsmGpsMap *map)
     return FALSE;
 }
 
-static void
+void
 osm_gps_map_map_redraw_idle (OsmGpsMap *map)
 {
     OsmGpsMapPrivate *priv = map->priv;
@@ -1563,6 +1710,8 @@ osm_gps_map_setup(OsmGpsMap *map)
             g_free(priv->repo_uri);
 
             priv->repo_uri = g_strdup(uri);
+
+            g_free(priv->image_format);
             priv->image_format = g_strdup(
                 osm_gps_map_source_get_image_format(priv->map_source));
             priv->max_zoom = osm_gps_map_source_get_max_zoom(priv->map_source);
@@ -1574,16 +1723,19 @@ osm_gps_map_setup(OsmGpsMap *map)
 
     /* setup the tile cache */
     if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0 ) {
+        g_free(priv->cache_dir);
         priv->cache_dir = NULL;
     } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0 ) {
         char *base = osm_gps_map_get_cache_base_dir(priv);
         char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);
+        g_free(priv->cache_dir);
         priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, md5);
         g_free(base);
         g_free(md5);
     } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0 ) {
         char *base = osm_gps_map_get_cache_base_dir(priv);
         const char *fname = osm_gps_map_source_get_friendly_name(priv->map_source);
+        g_free(priv->cache_dir);
         priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, fname);
         g_free(base);
     } else {
@@ -1678,10 +1830,13 @@ osm_gps_map_finalize (GObject *object)
     if (priv->tile_dir)
         g_free(priv->tile_dir);
 
+    g_free(priv->tile_base_dir);
+
     if (priv->cache_dir)
         g_free(priv->cache_dir);
 
     g_free(priv->repo_uri);
+    g_free(priv->proxy_uri);
     g_free(priv->image_format);
 
     /* trip and tracks contain simple non GObject types, so free them here */
@@ -1712,10 +1867,12 @@ osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, G
             priv->map_auto_download_enabled = g_value_get_boolean (value);
             break;
         case PROP_REPO_URI:
+            g_free(priv->repo_uri);
             priv->repo_uri = g_value_dup_string (value);
             break;
         case PROP_PROXY_URI:
             if ( g_value_get_string(value) ) {
+                g_free(priv->proxy_uri);
                 priv->proxy_uri = g_value_dup_string (value);
                 g_debug("Setting proxy server: %s", priv->proxy_uri);
 
@@ -1726,25 +1883,32 @@ osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, G
                 g_object_set_property(G_OBJECT(priv->soup_session),SOUP_SESSION_PROXY_URI,&val);
 
             } else {
+                g_free(priv->proxy_uri);
                 priv->proxy_uri = NULL;
             }
             break;
         case PROP_TILE_CACHE_DIR:
             if ( g_value_get_string(value) ) {
+                g_free(priv->tile_dir);
                 priv->tile_dir = g_value_dup_string (value);
                 if ((g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0)    ||
                     (g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0)        ||
                     (g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0)) {
                     /* this case is handled by osm_gps_map_setup */
                 } else {
+                    if (priv->cache_dir)
+                        g_free(priv->cache_dir);
                     priv->cache_dir = g_strdup(priv->tile_dir);
                     g_debug("Cache dir: %s", priv->cache_dir);
                 }
             } else {
+                if (priv->tile_dir)
+                    g_free(priv->tile_dir);
                 priv->tile_dir = g_strdup(OSM_GPS_MAP_CACHE_DISABLED);
             }
             break;
         case PROP_TILE_CACHE_BASE_DIR:
+            g_free(priv->tile_base_dir);
             priv->tile_base_dir = g_value_dup_string (value);
             break;
         case PROP_TILE_ZOOM_OFFSET:
@@ -1794,6 +1958,7 @@ osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, G
 
             } } break;
         case PROP_IMAGE_FORMAT:
+            g_free(priv->image_format);
             priv->image_format = g_value_dup_string (value);
             break;
         case PROP_DRAG_LIMIT:
@@ -1908,7 +2073,7 @@ osm_gps_map_scroll_event (GtkWidget *widget, GdkEventScroll  *event)
 {
     OsmGpsMap *map;
     OsmGpsMapPoint *pt;
-    float lat, lon;
+    float lat, lon, c_lat, c_lon;
 
     map = OSM_GPS_MAP(widget);
     pt = osm_gps_map_point_new_degrees(0.0,0.0);
@@ -1917,10 +2082,20 @@ osm_gps_map_scroll_event (GtkWidget *widget, GdkEventScroll  *event)
     osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, pt);
     osm_gps_map_point_get_degrees (pt, &lat, &lon);
 
-    if (event->direction == GDK_SCROLL_UP)
+    c_lat = rad2deg(map->priv->center_rlat);
+    c_lon = rad2deg(map->priv->center_rlon);
+
+
+
+    if ((event->direction == GDK_SCROLL_UP) && (map->priv->map_zoom < map->priv->max_zoom)) {
+        lat = c_lat + ((lat - c_lat)/2.0);
+        lon = c_lon + ((lon - c_lon)/2.0);
         osm_gps_map_set_center_and_zoom(map, lat, lon, map->priv->map_zoom+1);
-    else if (event->direction == GDK_SCROLL_DOWN)
+    } else if ((event->direction == GDK_SCROLL_DOWN) && (map->priv->map_zoom > map->priv->min_zoom)) {
+        lat = c_lat + ((c_lat - lat)*1.0);
+        lon = c_lon + ((c_lon - lon)*1.0);
         osm_gps_map_set_center_and_zoom(map, lat, lon, map->priv->map_zoom-1);
+    }
 
     osm_gps_map_point_free (pt);
 
@@ -1933,15 +2108,148 @@ osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)
     OsmGpsMap *map = OSM_GPS_MAP(widget);
     OsmGpsMapPrivate *priv = map->priv;
 
-    if (priv->layers) {
+    if (priv->layers)
+    {
         GSList *list;
-        for(list = priv->layers; list != NULL; list = list->next) {
+        for(list = priv->layers; list != NULL; list = list->next)
+        {
             OsmGpsMapLayer *layer = list->data;
             if (osm_gps_map_layer_button_press(layer, map, event))
                 return FALSE;
         }
     }
 
+    if(event->button == 1)
+    {
+        GSList* tracks = priv->tracks;
+        while(tracks)
+        {
+            OsmGpsMapTrack* track = tracks->data;
+            gboolean path_editable = FALSE;
+            g_object_get(track, "editable", &path_editable, NULL);
+            if(path_editable)
+            {
+                GSList* points = osm_gps_map_track_get_points(track);
+                int ctr = 0;
+                int last_x = 0;
+                int last_y = 0;
+                while(points)
+                {
+                    //if the mouse has gone down on a point, start dragging it
+                    int cx, cy;
+                    OsmGpsMapPoint* point = (OsmGpsMapPoint*)points->data;
+                    osm_gps_map_convert_geographic_to_screen(map, point, &cx, &cy);
+
+                    float dist_sqrd = (event->x - cx) * (event->x-cx) + (event->y-cy) * (event->y-cy);
+                    if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1)))
+                    {
+                        priv->is_button_down = TRUE;
+                        priv->drag_point = point;
+                        priv->drag_track = track;
+                        priv->is_dragging_point = TRUE;
+                        osm_gps_map_map_redraw(map);
+                        return FALSE;
+                    }
+
+                    //add a new point if a 'breaker' has been clicked
+                    if(ctr != 0)
+                    {
+                        int ptx = (last_x+cx)/2.0;
+                        int pty = (last_y+cy)/2.0;
+                        dist_sqrd = (event->x - ptx) * (event->x-ptx) + (event->y-pty) * (event->y-pty);
+                        if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1)))
+                        {
+                            OsmGpsMapPoint* newpoint = malloc(sizeof(OsmGpsMapPoint));
+                            osm_gps_map_convert_screen_to_geographic(map, ptx, pty, newpoint);
+                            osm_gps_map_track_insert_point(track, newpoint, ctr);
+                            osm_gps_map_map_redraw(map);
+                            return FALSE;
+                        }
+                    }
+
+                    last_x = cx;
+                    last_y = cy;
+                    points = points->next;
+                    ctr++;
+                }
+            }
+            tracks = tracks->next;
+        }
+
+        GSList* polys = priv->polygons;
+        while(polys)
+        {
+            OsmGpsMapPolygon* poly = polys->data;
+            gboolean path_editable = FALSE;
+            OsmGpsMapTrack* track = osm_gps_map_polygon_get_track(poly);
+            g_object_get(poly, "editable", &path_editable, NULL);
+            if(path_editable)
+            {
+                GSList* points = osm_gps_map_track_get_points(track);
+                int ctr = 0;
+                int last_x = 0;
+                int last_y = 0;
+                int first_x = 0; int first_y = 0;
+                while(points)
+                {
+                    //if the mouse has gone down on a point, start dragging it
+                    int cx, cy;
+                    OsmGpsMapPoint* point = (OsmGpsMapPoint*)points->data;
+                    osm_gps_map_convert_geographic_to_screen(map, point, &cx, &cy);
+
+                    float dist_sqrd = (event->x - cx) * (event->x-cx) + (event->y-cy) * (event->y-cy);
+                    if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1)))
+                    {
+                        priv->is_button_down = TRUE;
+                        priv->drag_point = point;
+                        priv->drag_track = track;
+                        priv->is_dragging_point = TRUE;
+                        osm_gps_map_map_redraw(map);
+                        return FALSE;
+                    }
+
+                    //add a new point if a 'breaker' has been clicked
+                    if(ctr != 0)
+                    {
+                        int ptx = (last_x+cx)/2.0;
+                        int pty = (last_y+cy)/2.0;
+                        dist_sqrd = (event->x - ptx) * (event->x-ptx) + (event->y-pty) * (event->y-pty);
+                        if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1)))
+                        {
+                            OsmGpsMapPoint* newpoint = malloc(sizeof(OsmGpsMapPoint));
+                            osm_gps_map_convert_screen_to_geographic(map, ptx, pty, newpoint);
+                            osm_gps_map_track_insert_point(track, newpoint, ctr);
+                            osm_gps_map_map_redraw(map);
+                            return FALSE;
+                        }
+                    }
+                    else
+                    {
+                        first_x = cx; first_y = cy;
+                    }
+
+                    last_x = cx;
+                    last_y = cy;
+                    points = points->next;
+                    ctr++;
+                }
+
+                int ptx = (last_x+first_x)/2.0;
+                int pty = (last_y+first_y)/2.0;
+                float dist_sqrd = (event->x - ptx) * (event->x-ptx) + (event->y-pty) * (event->y-pty);
+                if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1)))
+                {
+                    OsmGpsMapPoint* newpoint = malloc(sizeof(OsmGpsMapPoint));
+                    osm_gps_map_convert_screen_to_geographic(map, ptx, pty, newpoint);
+                    osm_gps_map_track_insert_point(track, newpoint, ctr);
+                    osm_gps_map_map_redraw(map);
+                    return FALSE;
+                }
+            }
+            polys = polys->next;
+        }
+    }
+
     priv->is_button_down = TRUE;
     priv->drag_counter = 0;
     priv->drag_start_mouse_x = (int) event->x;
@@ -1976,6 +2284,13 @@ osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)
         osm_gps_map_map_redraw_idle(map);
     }
 
+    if( priv->is_dragging_point)
+    {
+        priv->is_dragging_point = FALSE;
+        osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, priv->drag_point);
+        g_signal_emit_by_name(priv->drag_track, "point-changed");
+    }
+
     priv->drag_counter = -1;
     priv->is_button_down = FALSE;
 
@@ -2005,6 +2320,13 @@ osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
     if(!priv->is_button_down)
         return FALSE;
 
+    if(priv->is_dragging_point)
+    {
+        osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, priv->drag_point);
+        osm_gps_map_map_redraw_idle(map);
+        return FALSE;
+    }
+
     if (event->is_hint)
         // gdk_window_get_pointer (event->window, &x, &y, &state);
         gdk_window_get_device_position( event->window, pointer, &x, &y, &state);
@@ -2020,14 +2342,14 @@ osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
     if (!(state & GDK_BUTTON1_MASK))
         return FALSE;
 
-    if (priv->drag_counter < 0) 
+    if (priv->drag_counter < 0)
         return FALSE;
 
     /* not yet dragged far enough? */
     if(!priv->drag_counter &&
-       ( (x - priv->drag_start_mouse_x) * (x - priv->drag_start_mouse_x) + 
-         (y - priv->drag_start_mouse_y) * (y - priv->drag_start_mouse_y) <
-         priv->drag_limit*priv->drag_limit))
+            ( (x - priv->drag_start_mouse_x) * (x - priv->drag_start_mouse_x) +
+              (y - priv->drag_start_mouse_y) * (y - priv->drag_start_mouse_y) <
+              priv->drag_limit*priv->drag_limit))
         return FALSE;
 
     priv->drag_counter++;
@@ -2042,7 +2364,7 @@ osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
 
     /* instead of redrawing directly just add an idle function */
     if (!priv->drag_expose_source)
-        priv->drag_expose_source = 
+        priv->drag_expose_source =
             g_idle_add ((GSourceFunc)osm_gps_map_idle_expose, widget);
 
     return FALSE;
@@ -2074,7 +2396,7 @@ osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)
     gint pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
 
     priv->map_x = pixel_x - w/2;
-    priv->map_y = pixel_y - w/2;
+    priv->map_y = pixel_y - h/2;
 
     osm_gps_map_map_redraw(OSM_GPS_MAP(widget));
 
@@ -2618,6 +2940,21 @@ osm_gps_map_get_bbox (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2)
 }
 
 /**
+ * osm_gps_map_zoom_fit_bbox:
+ * Zoom and center the map so that both points fit inside the window.
+ **/
+void
+osm_gps_map_zoom_fit_bbox (OsmGpsMap *map, float latitude1, float latitude2, float longitude1, float longitude2)
+{
+    GtkAllocation allocation;
+    int zoom;
+    gtk_widget_get_allocation (GTK_WIDGET (map), &allocation);
+    zoom = latlon2zoom (allocation.height, allocation.width, deg2rad(latitude1), deg2rad(latitude2), deg2rad(longitude1), deg2rad(longitude2));
+    osm_gps_map_set_center (map, (latitude1 + latitude2) / 2, (longitude1 + longitude2) / 2);
+    osm_gps_map_set_zoom (map, zoom);
+}
+
+/**
  * osm_gps_map_set_center_and_zoom:
  *
  * Since: 0.7.0
@@ -2886,6 +3223,49 @@ osm_gps_map_track_remove (OsmGpsMap *map, OsmGpsMapTrack *track)
     return data != NULL;
 }
 
+void
+osm_gps_map_polygon_add (OsmGpsMap *map, OsmGpsMapPolygon *poly)
+{
+    OsmGpsMapPrivate *priv;
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    g_object_ref(poly);
+
+    OsmGpsMapTrack* track = osm_gps_map_polygon_get_track(poly);
+    g_signal_connect(track, "point-added",
+                    G_CALLBACK(on_gps_point_added), map);
+    g_signal_connect(track, "notify",
+                    G_CALLBACK(on_track_changed), map);
+
+    priv->polygons = g_slist_append(priv->polygons, poly);
+    osm_gps_map_map_redraw_idle(map);
+}
+
+void
+osm_gps_map_polygon_remove_all(OsmGpsMap *map)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+
+    gslist_of_gobjects_free(&map->priv->polygons);
+    osm_gps_map_map_redraw_idle(map);
+}
+
+gboolean
+osm_gps_map_polygon_remove(OsmGpsMap *map, OsmGpsMapPolygon *poly)
+{
+    GSList *data;
+
+    g_return_val_if_fail (OSM_IS_GPS_MAP (map), FALSE);
+    g_return_val_if_fail (poly != NULL, FALSE);
+
+    data = gslist_remove_one_gobject (&map->priv->polygons, G_OBJECT(poly));
+    osm_gps_map_map_redraw_idle(map);
+    return data != NULL;
+}
+
+
 /**
  * osm_gps_map_gps_clear:
  *
diff --git a/src/osm-gps-map-widget.h b/src/osm-gps-map-widget.h
index b310361..f2f66aa 100644
--- a/src/osm-gps-map-widget.h
+++ b/src/osm-gps-map-widget.h
@@ -44,6 +44,7 @@ typedef struct _OsmGpsMapPrivate OsmGpsMapPrivate;
 #include "osm-gps-map-layer.h"
 #include "osm-gps-map-point.h"
 #include "osm-gps-map-track.h"
+#include "osm-gps-map-polygon.h"
 #include "osm-gps-map-image.h"
 
 struct _OsmGpsMapClass
@@ -84,6 +85,7 @@ gchar*          osm_gps_map_get_default_cache_directory (void);
 void            osm_gps_map_download_maps               (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2, int zoom_start, int zoom_end);
 void            osm_gps_map_download_cancel_all         (OsmGpsMap *map);
 void            osm_gps_map_get_bbox                    (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2);
+void            osm_gps_map_zoom_fit_bbox               (OsmGpsMap *map, float latitude1, float latitude2, float longitude1, float longitude2);
 void            osm_gps_map_set_center_and_zoom         (OsmGpsMap *map, float latitude, float longitude, int zoom);
 void            osm_gps_map_set_center                  (OsmGpsMap *map, float latitude, float longitude);
 int             osm_gps_map_set_zoom                    (OsmGpsMap *map, int zoom);
@@ -96,6 +98,9 @@ void            osm_gps_map_set_keyboard_shortcut       (OsmGpsMap *map, OsmGpsM
 void            osm_gps_map_track_add                   (OsmGpsMap *map, OsmGpsMapTrack *track);
 void            osm_gps_map_track_remove_all            (OsmGpsMap *map);
 gboolean        osm_gps_map_track_remove                (OsmGpsMap *map, OsmGpsMapTrack *track);
+void            osm_gps_map_polygon_add                 (OsmGpsMap *map, OsmGpsMapPolygon *poly);
+void            osm_gps_map_polygon_remove_all          (OsmGpsMap *map);
+gboolean        osm_gps_map_polygon_remove                (OsmGpsMap *map, OsmGpsMapPolygon *poly);
 void            osm_gps_map_gps_add                     (OsmGpsMap *map, float latitude, float longitude, float heading);
 void            osm_gps_map_gps_clear                   (OsmGpsMap *map);
 OsmGpsMapTrack *osm_gps_map_gps_get_track               (OsmGpsMap *map);
@@ -111,6 +116,8 @@ void            osm_gps_map_layer_remove_all            (OsmGpsMap *map);
 void            osm_gps_map_convert_screen_to_geographic(OsmGpsMap *map, gint pixel_x, gint pixel_y, OsmGpsMapPoint *pt);
 void            osm_gps_map_convert_geographic_to_screen(OsmGpsMap *map, OsmGpsMapPoint *pt, gint *pixel_x, gint *pixel_y);
 OsmGpsMapPoint *osm_gps_map_get_event_location          (OsmGpsMap *map, GdkEventButton *event);
+gboolean        osm_gps_map_map_redraw                  (OsmGpsMap *map);
+void            osm_gps_map_map_redraw_idle             (OsmGpsMap *map);
 
 G_END_DECLS
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/osm-gps-map.git



More information about the Pkg-grass-devel mailing list