Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 26651)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 26652)
@@ -28,4 +28,5 @@
 
 import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
+import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
 import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
@@ -57,7 +58,9 @@
     protected List<MapMarker> mapMarkerList;
     protected List<MapRectangle> mapRectangleList;
+    protected List<MapPolygon> mapPolygonList;
 
     protected boolean mapMarkersVisible;
     protected boolean mapRectanglesVisible;
+    protected boolean mapPolygonsVisible;
 
     protected boolean tileGridVisible;
@@ -116,6 +119,8 @@
         mapMarkerList = new LinkedList<MapMarker>();
         mapRectangleList = new LinkedList<MapRectangle>();
+        mapPolygonList = new LinkedList<MapPolygon>();
         mapMarkersVisible = true;
         mapRectanglesVisible = true;
+        mapPolygonsVisible = true;
         tileGridVisible = false;
         setLayout(null);
@@ -247,10 +252,18 @@
 
     /**
-     * Sets the displayed map pane and zoom level so that all map markers are
+     * Sets the displayed map pane and zoom level so that all chosen map elements are
      * visible.
      */
-    public void setDisplayToFitMapMarkers() {
-        if (mapMarkerList == null || mapMarkerList.size() == 0)
+    public void setDisplayToFitMapElements(boolean markers, boolean rectangles, boolean polygons) {
+        int nbElemToCheck = 0;
+        if (markers && mapMarkerList != null)
+            nbElemToCheck += mapMarkerList.size();
+        if (rectangles && mapRectangleList != null)
+            nbElemToCheck += mapRectangleList.size();
+        if (polygons && mapPolygonList != null)
+            nbElemToCheck += mapPolygonList.size();
+        if (nbElemToCheck == 0)
             return;
+        
         int x_min = Integer.MAX_VALUE;
         int y_min = Integer.MAX_VALUE;
@@ -258,22 +271,44 @@
         int y_max = Integer.MIN_VALUE;
         int mapZoomMax = tileController.getTileSource().getMaxZoom();
-        for (MapMarker marker : mapMarkerList) {
-            int x = OsmMercator.LonToX(marker.getLon(), mapZoomMax);
-            int y = OsmMercator.LatToY(marker.getLat(), mapZoomMax);
-            x_max = Math.max(x_max, x);
-            y_max = Math.max(y_max, y);
-            x_min = Math.min(x_min, x);
-            y_min = Math.min(y_min, y);
-        }
+        
+        if (markers) {
+            for (MapMarker marker : mapMarkerList) {
+                int x = OsmMercator.LonToX(marker.getLon(), mapZoomMax);
+                int y = OsmMercator.LatToY(marker.getLat(), mapZoomMax);
+                x_max = Math.max(x_max, x);
+                y_max = Math.max(y_max, y);
+                x_min = Math.min(x_min, x);
+                y_min = Math.min(y_min, y);
+            }
+        }
+        
+        if (rectangles) {
+            for (MapRectangle rectangle : mapRectangleList) {
+                x_max = Math.max(x_max, OsmMercator.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax));
+                y_max = Math.max(y_max, OsmMercator.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax));
+                x_min = Math.min(x_min, OsmMercator.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax));
+                y_min = Math.min(y_min, OsmMercator.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax));
+            }
+        }
+        
+        if (polygons) {
+            for (MapPolygon polygon : mapPolygonList) {
+                for (Coordinate c : polygon.getPoints()) {
+                    int x = OsmMercator.LonToX(c.getLon(), mapZoomMax);
+                    int y = OsmMercator.LatToY(c.getLat(), mapZoomMax);
+                    x_max = Math.max(x_max, x);
+                    y_max = Math.max(y_max, y);
+                    x_min = Math.min(x_min, x);
+                    y_min = Math.min(y_min, y);
+                }
+            }
+        }
+        
         int height = Math.max(0, getHeight());
         int width = Math.max(0, getWidth());
-        // System.out.println(x_min + " < x < " + x_max);
-        // System.out.println(y_min + " < y < " + y_max);
-        // System.out.println("tiles: " + width + " " + height);
         int newZoom = mapZoomMax;
         int x = x_max - x_min;
         int y = y_max - y_min;
         while (x > width || y > height) {
-            // System.out.println("zoom: " + zoom + " -> " + x + " " + y);
             newZoom--;
             x >>= 1;
@@ -287,43 +322,27 @@
         setDisplayPosition(x, y, newZoom);
     }
-
+    
     /**
      * Sets the displayed map pane and zoom level so that all map markers are
      * visible.
      */
-    public void setDisplayToFitMapRectangle() {
-        if (mapRectangleList == null || mapRectangleList.size() == 0)
-            return;
-        int x_min = Integer.MAX_VALUE;
-        int y_min = Integer.MAX_VALUE;
-        int x_max = Integer.MIN_VALUE;
-        int y_max = Integer.MIN_VALUE;
-        int mapZoomMax = tileController.getTileSource().getMaxZoom();
-        for (MapRectangle rectangle : mapRectangleList) {
-            x_max = Math.max(x_max, OsmMercator.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax));
-            y_max = Math.max(y_max, OsmMercator.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax));
-            x_min = Math.min(x_min, OsmMercator.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax));
-            y_min = Math.min(y_min, OsmMercator.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax));
-        }
-        int height = Math.max(0, getHeight());
-        int width = Math.max(0, getWidth());
-        // System.out.println(x_min + " < x < " + x_max);
-        // System.out.println(y_min + " < y < " + y_max);
-        // System.out.println("tiles: " + width + " " + height);
-        int newZoom = mapZoomMax;
-        int x = x_max - x_min;
-        int y = y_max - y_min;
-        while (x > width || y > height) {
-            // System.out.println("zoom: " + zoom + " -> " + x + " " + y);
-            newZoom--;
-            x >>= 1;
-            y >>= 1;
-        }
-        x = x_min + (x_max - x_min) / 2;
-        y = y_min + (y_max - y_min) / 2;
-        int z = 1 << (mapZoomMax - newZoom);
-        x /= z;
-        y /= z;
-        setDisplayPosition(x, y, newZoom);
+    public void setDisplayToFitMapMarkers() {
+        setDisplayToFitMapElements(true, false, false);
+    }
+
+    /**
+     * Sets the displayed map pane and zoom level so that all map rectangles are
+     * visible.
+     */
+    public void setDisplayToFitMapRectangles() {
+        setDisplayToFitMapElements(false, true, false);
+    }
+    
+    /**
+     * Sets the displayed map pane and zoom level so that all map polygons are
+     * visible.
+     */
+    public void setDisplayToFitMapPolygons() {
+        setDisplayToFitMapElements(false, false, true);
     }
 
@@ -507,15 +526,13 @@
         // g.drawString("Tiles in cache: " + tileCache.getTileCount(), 50, 20);
 
+        if (mapPolygonsVisible && mapPolygonList != null) {
+            for (MapPolygon polygon : mapPolygonList) {
+                paintPolygon(g, polygon);
+            }
+        }
+
         if (mapRectanglesVisible && mapRectangleList != null) {
             for (MapRectangle rectangle : mapRectangleList) {
-                Coordinate topLeft = rectangle.getTopLeft();
-                Coordinate bottomRight = rectangle.getBottomRight();
-                if (topLeft != null && bottomRight != null) {
-                    Point pTopLeft = getMapPosition(topLeft.getLat(), topLeft.getLon(), false);
-                    Point pBottomRight = getMapPosition(bottomRight.getLat(), bottomRight.getLon(), false);
-                    if (pTopLeft != null && pBottomRight != null) {
-                        rectangle.paint(g, pTopLeft, pBottomRight);
-                    }
-                }
+                paintRectangle(g, rectangle);
             }
         }
@@ -539,4 +556,37 @@
     }
 
+    /**
+     * Paint a single rectangle.
+     */
+    protected void paintRectangle(Graphics g, MapRectangle rectangle) {
+        Coordinate topLeft = rectangle.getTopLeft();
+        Coordinate bottomRight = rectangle.getBottomRight();
+        if (topLeft != null && bottomRight != null) {
+            Point pTopLeft = getMapPosition(topLeft, false);
+            Point pBottomRight = getMapPosition(bottomRight, false);
+            if (pTopLeft != null && pBottomRight != null) {
+                rectangle.paint(g, pTopLeft, pBottomRight);
+            }
+        }
+    }
+
+    /**
+     * Paint a single polygon.
+     */
+    protected void paintPolygon(Graphics g, MapPolygon polygon) {
+        List<Coordinate> coords = polygon.getPoints();
+        if (coords != null && coords.size() >= 3) {
+            List<Point> points = new LinkedList<Point>();
+            for (Coordinate c : coords) {
+                Point p = getMapPosition(c, false);
+                if (p == null) {
+                    return;
+                }
+                points.add(p);
+            }
+            polygon.paint(g, points);
+        }
+    }
+    
     /**
      * Moves the visible map pane.
@@ -661,4 +711,13 @@
     }
 
+    public void setMapPolygonList(List<MapPolygon> mapPolygonList) {
+        this.mapPolygonList = mapPolygonList;
+        repaint();
+    }
+
+    public List<MapPolygon> getMapPolygonList() {
+        return mapPolygonList;
+    }
+
     public void addMapMarker(MapMarker marker) {
         mapMarkerList.add(marker);
@@ -691,4 +750,19 @@
     }
 
+    public void addMapPolygon(MapPolygon polygon) {
+        mapPolygonList.add(polygon);
+        repaint();
+    }
+
+    public void removeMapPolygon(MapPolygon polygon) {
+        mapPolygonList.remove(polygon);
+        repaint();
+    }
+
+    public void removeAllMapPolygons() {
+        mapPolygonList.clear();
+        repaint();
+    }
+    
     public void setZoomContolsVisible(boolean visible) {
         zoomSlider.setVisible(visible);
@@ -736,5 +810,5 @@
      * Enables or disables painting of the {@link MapRectangle}
      * 
-     * @param mapMarkersVisible
+     * @param mapRectanglesVisible
      * @see #addMapRectangle(MapRectangle)
      * @see #getMapRectangleList()
@@ -742,4 +816,20 @@
     public void setMapRectanglesVisible(boolean mapRectanglesVisible) {
         this.mapRectanglesVisible = mapRectanglesVisible;
+        repaint();
+    }
+
+    public boolean isMapPolygonsVisible() {
+        return mapPolygonsVisible;
+    }
+
+    /**
+     * Enables or disables painting of the {@link MapPolygon}
+     * 
+     * @param mapPolygonsVisible
+     * @see #addMapPolygon(MapPolygon)
+     * @see #getMapPolygonList()
+     */
+    public void setMapPolygonsVisible(boolean mapPolygonsVisible) {
+        this.mapPolygonsVisible = mapPolygonsVisible;
         repaint();
     }
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapPolygonImpl.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapPolygonImpl.java	(revision 26652)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapPolygonImpl.java	(revision 26652)
@@ -0,0 +1,85 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.gui.jmapviewer;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.awt.Stroke;
+import java.util.List;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
+
+/**
+ * @author Vincent
+ *
+ */
+public class MapPolygonImpl implements MapPolygon {
+
+    private List<Coordinate> points;
+    private Color color;
+    private Stroke stroke;
+
+    public MapPolygonImpl(List<Coordinate> points) {
+        this(points, Color.BLUE, new BasicStroke(2));
+    }
+
+    public MapPolygonImpl(List<Coordinate> points, Color color, Stroke stroke) {
+        this.points = points;
+        this.color = color;
+        this.stroke = stroke;
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#getPoints()
+     */
+    @Override
+    public List<Coordinate> getPoints() {
+        return this.points;
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#paint(java.awt.Graphics, java.util.List)
+     */
+    @Override
+    public void paint(Graphics g, List<Point> points) {
+        Polygon polygon = new Polygon();
+        for (Point p : points) {
+            polygon.addPoint(p.x, p.y);
+        }
+        paint(g, polygon);
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#paint(java.awt.Graphics, java.awt.Polygon)
+     */
+    @Override
+    public void paint(Graphics g, Polygon polygon) {
+        // Prepare graphics
+        Color oldColor = g.getColor();
+        g.setColor(color);
+        Stroke oldStroke = null;
+        if (g instanceof Graphics2D) {
+            Graphics2D g2 = (Graphics2D) g;
+            oldStroke = g2.getStroke();
+            g2.setStroke(stroke);
+        }
+        // Draw
+        g.drawPolygon(polygon);
+        // Restore graphics
+        g.setColor(oldColor);
+        if (g instanceof Graphics2D) {
+            ((Graphics2D) g).setStroke(oldStroke);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "MapPolygon [points=" + points + "]";
+    }
+}
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapRectangleImpl.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapRectangleImpl.java	(revision 26651)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapRectangleImpl.java	(revision 26652)
@@ -2,7 +2,10 @@
 package org.openstreetmap.gui.jmapviewer;
 
+import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Graphics;
+import java.awt.Graphics2D;
 import java.awt.Point;
+import java.awt.Stroke;
 
 import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
@@ -17,14 +20,16 @@
     private Coordinate topLeft;
     private Coordinate bottomRight;
-    Color color;
+    private Color color;
+    private Stroke stroke;
 
     public MapRectangleImpl(Bounds bounds) {
-        this(bounds, Color.BLUE);
+        this(bounds, Color.BLUE, new BasicStroke(2));
     }
 
-    public MapRectangleImpl(Bounds bounds, Color color) {
+    public MapRectangleImpl(Bounds bounds, Color color, Stroke stroke) {
         this.topLeft = new Coordinate(bounds.getMax().lat(), bounds.getMin().lon());
         this.bottomRight = new Coordinate(bounds.getMin().lat(), bounds.getMax().lon());
         this.color = color;
+        this.stroke = stroke;
     }
 
@@ -50,6 +55,20 @@
     @Override
     public void paint(Graphics g, Point topLeft, Point bottomRight) {
+        // Prepare graphics
+        Color oldColor = g.getColor();
         g.setColor(color);
+        Stroke oldStroke = null;
+        if (g instanceof Graphics2D) {
+            Graphics2D g2 = (Graphics2D) g;
+            oldStroke = g2.getStroke();
+            g2.setStroke(stroke);
+        }
+        // Draw
         g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);
+        // Restore graphics
+        g.setColor(oldColor);
+        if (g instanceof Graphics2D) {
+            ((Graphics2D) g).setStroke(oldStroke);
+        }
     }
 
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapPolygon.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapPolygon.java	(revision 26652)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapPolygon.java	(revision 26652)
@@ -0,0 +1,40 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.util.List;
+
+import org.openstreetmap.gui.jmapviewer.Coordinate;
+
+/**
+ * Interface to be implemented by polygons that can be displayed on the map.
+ *
+ * @author Vincent
+ */
+public interface MapPolygon {
+
+    /**
+     * @return Latitude/Longitude of each point of polygon
+     */
+    public List<Coordinate> getPoints();
+
+    /**
+     * Paints the map rectangle on the map. The <code>points</code> 
+     * are specifying the coordinates within <code>g</code>
+     *
+     * @param g
+     * @param points
+     */
+    public void paint(Graphics g, List<Point> points);
+
+    /**
+     * Paints the map rectangle on the map. The <code>polygon</code> 
+     * is specifying the coordinates within <code>g</code>
+     *
+     * @param g
+     * @param polygon
+     */
+    public void paint(Graphics g, Polygon polygon);
+}
