Index: trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java	(revision 8693)
+++ trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java	(revision 8696)
@@ -62,4 +62,12 @@
     };
 
+    /*
+     * Constant taken from OGC WMTS Implementation Specification (http://www.opengeospatial.org/standards/wmts)
+     * From table E.4 - Definition of Well-known scale set GoogleMapsCompatibile
+     *
+     *  As higher zoom levels have denominator divided by 2, we keep only zoom level 1 in the code
+     */
+    private static final float SCALE_DENOMINATOR_ZOOM_LEVEL_1 = 559082264.0287178f;
+
     /**
      * Creates a tile source based on imagery info
@@ -72,5 +80,5 @@
         initProjection();
         // FIXME: remove in September 2015, when ImageryPreferenceEntry.tileSize will be initialized to -1 instead to 256
-        // need to leave it as it is to keep compatiblity between tested and latest JOSM versions
+        // need to leave it as it is to keep compatibility between tested and latest JOSM versions
         tileSize = WMSLayer.PROP_IMAGE_SIZE.get();
     }
@@ -94,17 +102,18 @@
 
         LatLon bottomRight = new LatLon(worldBounds.getMinLat(), worldBounds.getMaxLon());
+
+        // use 256 as "tile size" to keep the scale in line with default tiles in Mercator projection
+        double crsScale = 256 * 0.28e-03 / proj.getMetersPerUnit();
         tileXMax = new int[getMaxZoom() + 1];
         tileYMax = new int[getMaxZoom() + 1];
-        degreesPerTile = new double[getMaxZoom() +1];
+        degreesPerTile = new double[getMaxZoom() + 1];
+
         for (int zoom = getMinZoom(); zoom <= getMaxZoom(); zoom++) {
             TileXY maxTileIndex = latLonToTileXY(bottomRight.toCoordinate(), zoom);
             tileXMax[zoom] = maxTileIndex.getXIndex();
             tileYMax[zoom] = maxTileIndex.getYIndex();
-            int tilesPerZoom = (int) Math.pow(2d, zoom - 1);
-            degreesPerTile[zoom] = Math.max(
-                    Math.abs(max.getY() - min.getY()) / tilesPerZoom,
-                    Math.abs(max.getX() - min.getX()) / tilesPerZoom
-                    );
-
+            // use well known scale set "GoogleCompatibile" from OGC WMTS spec to calculate number of tiles per zoom level
+            // this makes the zoom levels "glued" to standard TMS zoom levels
+            degreesPerTile[zoom] = (SCALE_DENOMINATOR_ZOOM_LEVEL_1 / Math.pow(2, zoom - 1)) * crsScale;
         }
 
