Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java	(revision 4162)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java	(revision 4162)
@@ -0,0 +1,193 @@
+package org.openstreetmap.josm.plugins.validator;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+
+import javax.swing.Icon;
+import javax.swing.JMenuItem;
+import javax.swing.JSeparator;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.RenameLayerAction;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.osm.*;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.data.osm.visitor.Visitor;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
+import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.plugins.validator.util.Util;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * A debug layer for testing the grid cells a segment or way crosses.
+ * 
+ * @author frsantos
+ */
+public class GridLayer extends Layer
+{
+	/**
+	 * Constructor 
+	 * @param name
+	 */
+	public GridLayer(String name) 
+    {
+		super(name);
+	}
+
+	/**
+	 * Return a static icon.
+	 */
+	@Override public Icon getIcon() {
+		return ImageProvider.get("layer", "validator");
+	}
+
+    /**
+     * Draw the grid and highlight all cells acuppied by any selected primitive.
+     */
+    @Override 
+    public void paint(final Graphics g, final MapView mv) 
+    {
+    	if( !Main.pref.hasKey(PreferenceEditor.PREF_DEBUG + ".grid") )
+    		return;
+    	
+    	int gridWidth = Integer.parseInt(Main.pref.get(PreferenceEditor.PREF_DEBUG + ".grid") );
+    	int width = mv.getWidth();
+		int height = mv.getHeight();
+
+		EastNorth origin = mv.getEastNorth(0, 0);
+		EastNorth border = mv.getEastNorth(width, height);
+
+    	if( border.east() * gridWidth > 50 )
+    		return;
+
+        g.setColor(Color.RED.darker().darker());
+    	HighlightCellVisitor visitor = new HighlightCellVisitor(g, mv, gridWidth);
+    	for(OsmPrimitive p : Main.ds.getSelected() )
+    		p.visit(visitor);
+        
+        long x0 = (long)Math.floor(origin.east()  * gridWidth);
+		long x1 = (long)Math.floor(border.east()  * gridWidth);
+        long y0 = (long)Math.floor(origin.north() * gridWidth) + 1;
+        long y1 = (long)Math.floor(border.north() * gridWidth) + 1;        
+        long aux;
+        if( x0 > x1 ) { aux = x0; x0 = x1; x1 = aux; }
+        if( y0 > y1 ) { aux = y0; y0 = y1; y1 = aux; }
+        
+        g.setColor(Color.RED.brighter().brighter());
+    	for( double x = x0; x <= x1; x++)
+    	{
+    		Point point = mv.getPoint( new EastNorth(x/gridWidth, 0));
+			g.drawLine(point.x, 0, point.x, height);
+    	}
+
+    	for( double y = y0; y <= y1; y++)
+    	{
+    		Point point = mv.getPoint( new EastNorth(0, y/gridWidth));
+			g.drawLine(0, point.y, width, point.y);
+    	}
+    }
+
+	@Override 
+    public String getToolTipText() 
+    {
+		return null;
+	}
+
+	@Override 
+	public void mergeFrom(Layer from) {}
+
+	@Override 
+	public boolean isMergable(Layer other) {
+		return false;
+	}
+
+	@Override 
+	public void visitBoundingBox(BoundingXYVisitor v) {}
+
+	@Override 
+	public Object getInfoComponent() 
+    {
+	    return getToolTipText();
+	}
+
+	@Override 
+	public Component[] getMenuEntries() 
+    {
+        return new Component[]{
+                new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)),
+                new JMenuItem(new LayerListDialog.DeleteLayerAction(this)),
+                new JSeparator(),
+                new JMenuItem(new RenameLayerAction(null, this)),
+                new JSeparator(),
+                new JMenuItem(new LayerListPopup.InfoAction(this))};
+    }
+
+	@Override public void destroy() { }
+	
+	/**
+	 * Visitor that highlights all cells the selected primitives go through
+	 */
+	class HighlightCellVisitor implements Visitor
+	{
+		/** The MapView */
+		private final MapView mv;
+		/** The graphics */
+		private final Graphics g;
+		/** The grid width */
+		private final int gridDetail;
+		/** The width of a cell */
+		private int cellWidth;
+
+		/**
+		 * Constructor
+		 * @param g the graphics
+		 * @param mv The MapView
+		 * @param gridDetail The grid detail
+		 */
+		public HighlightCellVisitor(final Graphics g, final MapView mv, int gridDetail)
+		{
+			this.g = g;
+			this.mv = mv;
+			this.gridDetail = gridDetail;
+			
+    		Point p = mv.getPoint( new EastNorth(0, 0) );
+    		Point p2 = mv.getPoint( new EastNorth(1d/gridDetail, 1d/gridDetail) );
+    		cellWidth = Math.abs(p2.x - p.x);
+		}
+
+		public void visit(Node n) 
+		{
+			double x = n.eastNorth.east() * gridDetail;
+	        double y = n.eastNorth.north()* gridDetail + 1;
+
+	        drawCell( Math.floor(x), Math.floor(y) );
+		}
+
+		public void visit(Segment s) 
+		{
+			for( Point2D p : Util.getSegmentCells(s, gridDetail))
+			{
+		        drawCell( p.getX(), p.getY() );
+			}
+		}
+
+		public void visit(Way w) 
+		{
+			for( Segment s : w.segments )
+				visit(s);
+		}
+		
+		/** 
+		 * Draws a solid cell at the (x,y) location
+		 * @param x
+		 * @param y
+		 */
+		protected void drawCell(double x, double y)
+		{
+    		Point p = mv.getPoint( new EastNorth(x/gridDetail, y/gridDetail) );
+			g.fillRect(p.x, p.y, cellWidth, cellWidth);
+		}
+	}
+}
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java	(revision 4161)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/OSMValidatorPlugin.java	(revision 4162)
@@ -83,4 +83,6 @@
 	        newFrame.addToggleDialog(validationDialog);
             Main.main.addLayer(new ErrorLayer(tr("Validation errors")));
+        	if( Main.pref.hasKey(PreferenceEditor.PREF_DEBUG + ".grid") )
+        		Main.main.addLayer(new GridLayer(tr("Grid")));
             Layer.listeners.add(this); 
 		}
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/PreferenceEditor.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/PreferenceEditor.java	(revision 4161)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/PreferenceEditor.java	(revision 4162)
@@ -26,5 +26,8 @@
 	/** The preferences prefix */
 	public static final String PREFIX = "validator";
-	
+
+	/** The preferences key for debug preferences */
+	public static final String PREF_DEBUG = PREFIX + ".debug";
+
 	/** The preferences key for enabled tests */
 	public static final String PREF_TESTS = PREFIX + ".tests";
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingSegments.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingSegments.java	(revision 4161)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingSegments.java	(revision 4162)
@@ -10,4 +10,5 @@
 import org.openstreetmap.josm.plugins.validator.*;
 import org.openstreetmap.josm.plugins.validator.util.Bag;
+import org.openstreetmap.josm.plugins.validator.util.Util;
 
 /**
@@ -53,9 +54,12 @@
             return;
         
-        if( w.get("highway") == null && w.get("waterway") == null && w.get("railway") == null )
+        String coastline1 = w.get("natural"); 
+        boolean isCoastline1 = coastline1 != null && (coastline1.equals("water") || coastline1.equals("coastline"));
+        String railway1 = w.get("railway"); 
+        boolean isSubway1 = railway1 != null && railway1.equals("subway");
+        if( w.get("highway") == null && w.get("waterway") == null && !isSubway1 && !isCoastline1) 
         	return;
         
         String layer1 = w.get("layer");
-        String railway1 = w.get("railway");
         for(Segment s : w.segments)
         {
@@ -63,5 +67,5 @@
         		continue;
         	
-            ExtendedSegment es1 = new ExtendedSegment(s, layer1, railway1);
+            ExtendedSegment es1 = new ExtendedSegment(s, layer1, railway1, coastline1);
             List<List<ExtendedSegment>> cellSegments = getSegments(s);
             for( List<ExtendedSegment> segments : cellSegments)
@@ -74,13 +78,18 @@
 	                String layer2 = es2.layer;
 	                String railway2 = es2.railway;
-	                if( (layer1 == null && layer2 == null || layer1 != null && layer1.equals(layer2)) &&
-	                	!("subway".equals(railway1) && "subway".equals(railway2)) &&	
-	                	es1.intersects(es2))
-	                {
-	                    List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
-	                    primitives.add(es1.s);
-	                    primitives.add(es2.s);
-	                    errors.add( new TestError(this, Severity.WARNING, tr("Crossing roads"), primitives) );
-	                }
+	                String coastline2 = es2.coastline;
+	                if( (layer1 != null || layer2 != null) && (layer1 == null || !layer1.equals(layer2)) )
+	                	continue;
+	                
+	                if( !es1.intersects(es2) ) continue;
+		            if( isSubway1 && "subway".equals(railway2)) continue;
+		            
+		            boolean isCoastline2 = coastline2 != null && (coastline2.equals("water") || coastline2.equals("coastline"));
+	                if( isCoastline1 != isCoastline2 ) continue;
+	                
+                    List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
+                    primitives.add(es1.s);
+                    primitives.add(es2.s);
+                    errors.add( new TestError(this, Severity.WARNING, tr("Crossing roads"), primitives) );
 	            }
 	            segments.add(es1);
@@ -92,8 +101,4 @@
      * Returns all the cells this segment crosses . Each cell contains the list
      * of segments already processed
-     * <p>
-     * This method uses the Bresenham algorithm to follow all cells this segment
-     * crosses, so, in very few cases (when the segment is very long, and
-     * crosses a cell very close to the corner), it can miss a cell.
      * 
      * @param s The segment
@@ -103,44 +108,13 @@
 	{
 		List<List<ExtendedSegment>> cells = new ArrayList<List<ExtendedSegment>>();
-		long x0 = Math.round(s.from.eastNorth.east() * 1000);
-		long x1 = Math.round(s.to.eastNorth.east()   * 1000);
-        long y0 = Math.round(s.from.eastNorth.north()* 1000);
-        long y1 = Math.round(s.to.eastNorth.north()  * 1000);
-        
-        boolean steep = Math.abs(y1 - y0) > Math.abs(x1 - x0);
-        long aux;
-        if( steep )
-        {
-            aux = x0; x0 = x1; x1 = aux;
-            aux = y0; y0 = y1; y1 = aux;
-        }
-        if( x0 > x1 )
-        {
-            aux = x0; x0 = x1; x1 = aux;
-            aux = y0; y0 = y1; y1 = aux;
-        }
-        long dx  = x1 - x0,
-             dy  = Math.abs(y1 - y0),
-             y   = y0,
-             error = -dx/2,
-             ystep = y0 < y1 ? 1 : -1;
-      
-        for( long x = x0; x <= x1; x++ )  
-        {
-            Point2D p = steep ? new Point2D.Double(y, x) : new Point2D.Double(x, y);
-            List<ExtendedSegment> segments = cellSegments.get( p );
+		for( Point2D cell : Util.getSegmentCells(s, 10000) )
+		{
+            List<ExtendedSegment> segments = cellSegments.get( cell );
             if( segments == null )
             {
                 segments = new ArrayList<ExtendedSegment>();
-                cellSegments.put(p, segments);
+                cellSegments.put(cell, segments);
             }
             cells.add(segments);
-            
-            error += dy;
-            if( error > 0 )
-            {
-                error -= dx;
-                y += ystep;
-            }
         }
         
@@ -162,4 +136,7 @@
         /** The railway type */
 		private String railway;
+
+		/** The coastline type */
+		private String coastline;
         
         /**
@@ -168,10 +145,12 @@
          * @param layer The layer of the way this segment is in
          * @param railway The railway type of the way this segment is in
+         * @param coastline The coastlyne typo of the way the segment is in
          */
-        public ExtendedSegment(Segment s, String layer, String railway)
+        public ExtendedSegment(Segment s, String layer, String railway, String coastline)
         {
             this.s = s;
             this.layer = layer;
             this.railway = railway;
+            this.coastline = coastline;
         }
         
Index: /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/Util.java
===================================================================
--- /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/Util.java	(revision 4161)
+++ /applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/Util.java	(revision 4162)
@@ -261,8 +261,8 @@
 
         // First, round coordinates
-        long x0 = Math.round(start.from.eastNorth.east()  * 100000);
-        long y0 = Math.round(start.from.eastNorth.north() * 100000);
-        long x1 = Math.round(end.to.eastNorth.east()      * 100000);
-        long y1 = Math.round(end.to.eastNorth.north()     * 100000);
+        long x0 = Math.round(start.from.eastNorth.east()  * 10000);
+        long y0 = Math.round(start.from.eastNorth.north() * 10000);
+        long x1 = Math.round(end.to.eastNorth.east()      * 10000);
+        long y1 = Math.round(end.to.eastNorth.north()     * 10000);
 
         // Start of the way
@@ -292,8 +292,8 @@
 
         // Then floor coordinates, in case the way is in the border of the cell.
-        x0 = (long)Math.floor(start.from.eastNorth.east()  * 100000);
-        y0 = (long)Math.floor(start.from.eastNorth.north() * 100000);
-        x1 = (long)Math.floor(end.to.eastNorth.east()      * 100000);
-        y1 = (long)Math.floor(end.to.eastNorth.north()     * 100000);
+        x0 = (long)Math.floor(start.from.eastNorth.east()  * 10000);
+        y0 = (long)Math.floor(start.from.eastNorth.north() * 10000);
+        x1 = (long)Math.floor(end.to.eastNorth.east()      * 10000);
+        y1 = (long)Math.floor(end.to.eastNorth.north()     * 10000);
 
         // Start of the way
@@ -327,3 +327,57 @@
         return cells;
     }    
+    
+    /**
+	 * Returns the coordinates of all cells in a grid that a segment goes through.
+	 * 
+	 * @param s The segment
+	 * @param gridDetail The detail of the grid. Bigger values give smaller cells, but a bigger number of them.
+	 * @return A list with the coordinates of all cells
+	 */
+	public static List<Point2D> getSegmentCells(Segment s, int gridDetail) 
+	{
+		List<Point2D> cells = new ArrayList<Point2D>();
+		double x0 = s.from.eastNorth.east() * gridDetail;
+		double x1 = s.to.eastNorth.east()   * gridDetail;
+        double y0 = s.from.eastNorth.north()* gridDetail + 1;
+        double y1 = s.to.eastNorth.north()  * gridDetail + 1;
+
+        if( x0 > x1 )
+        {
+        	// Move to 1st-4th cuadrants
+            double aux;
+            aux = x0; x0 = x1; x1 = aux;
+            aux = y0; y0 = y1; y1 = aux;
+        }
+        
+        double dx  = x1 - x0;
+        double dy  = y1 - y0;
+        long stepY = y0 <= y1 ? 1 : -1;
+        long gridX0 = (long)Math.floor(x0);
+        long gridX1 = (long)Math.floor(x1);
+        long gridY0 = (long)Math.floor(y0);
+        long gridY1 = (long)Math.floor(y1);
+        
+        long maxSteps = (gridX1 - gridX0) + Math.abs(gridY1 - gridY0) + 1;
+		while( (gridX0 <= gridX1 && (gridY0 - gridY1)*stepY <= 0) && maxSteps-- > 0)
+        {
+			cells.add( new Point2D.Double(gridX0, gridY0) );
+			
+    		// Is the cross between the segment and next vertical line nearer than the cross with next horizontal line? 
+        	// Note: segment line formula: y=dy/dx(x-x1)+y1
+			// Note: if dy < 0, must use *bottom* line. If dy > 0, must use upper line 
+        	double scanY = dy/dx * (gridX0 + 1 - x1) + y1 + (dy < 0 ? -1 : 0);
+        	double scanX = dx/dy * (gridY0 + (dy < 0 ? 0 : 1)*stepY - y1) + x1;
+    		
+        	double distX = Math.pow(gridX0 + 1 - x0, 2) + Math.pow(scanY - y0, 2);
+			double distY = Math.pow(scanX - x0, 2) + Math.pow(gridY0 + stepY - y0, 2);
+			
+			if( distX < distY)
+    			gridX0 += 1;
+    		else
+        		gridY0 += stepY;
+        }
+		
+		return cells;
+	}   
 }
