Index: trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java	(revision 8582)
+++ trunk/src/org/openstreetmap/josm/data/imagery/TemplatedWMSTileSource.java	(revision 8584)
@@ -139,6 +139,7 @@
         if (baseUrl.toLowerCase().contains("crs=epsg:4326")) {
             switchLatLon = true;
-        } else if (baseUrl.toLowerCase().contains("crs=") && "EPSG:4326".equals(myProjCode)) {
-            switchLatLon = true;
+        } else if (baseUrl.toLowerCase().contains("crs=")) {
+            // assume WMS 1.3.0
+            switchLatLon = Main.getProjection().switchXY();
         }
         String bbox;
Index: trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java	(revision 8582)
+++ trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java	(revision 8584)
@@ -47,4 +47,5 @@
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.data.projection.Projections;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.io.CachedFile;
@@ -66,5 +67,5 @@
     private static final String PATTERN_HEADER  = "\\{header\\(([^,]+),([^}]+)\\)\\}";
 
-    private static final String URL_GET_ENCODING_PARAMS = "SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER={layer}&STYLE={style}&"
+    private static final String URL_GET_ENCODING_PARAMS = "SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER={layer}&STYLE={Style}&"
             + "FORMAT={format}&tileMatrixSet={TileMatrixSet}&tileMatrix={TileMatrix}&tileRow={TileRow}&tileCol={TileCol}";
 
@@ -229,7 +230,6 @@
 
         } catch (Exception e) {
-            Main.error(e);
-        }
-        return null;
+            throw new IllegalArgumentException(e);
+        }
     }
 
@@ -268,4 +268,9 @@
             matrixSet.crs = crsToCode(getStringByXpath(matrixSetNode, "SupportedCRS"));
             NodeList tileMatrixList = getByXpath(matrixSetNode, "TileMatrix");
+            Projection matrixProj = Projections.getProjectionByCode(matrixSet.crs);
+            if (matrixProj == null) {
+                // use current projection if none found. Maybe user is using custom string
+                matrixProj = Main.getProjection();
+            }
             for (int matrixId = 0; matrixId < tileMatrixList.getLength(); matrixId++) {
                 Node tileMatrixNode = tileMatrixList.item(matrixId);
@@ -274,5 +279,10 @@
                 tileMatrix.scaleDenominator = Double.parseDouble(getStringByXpath(tileMatrixNode, "ScaleDenominator"));
                 String[] topLeftCorner = getStringByXpath(tileMatrixNode, "TopLeftCorner").split(" ");
-                tileMatrix.topLeftCorner = new EastNorth(Double.parseDouble(topLeftCorner[1]), Double.parseDouble(topLeftCorner[0]));
+
+                if(matrixProj.switchXY()) {
+                    tileMatrix.topLeftCorner = new EastNorth(Double.parseDouble(topLeftCorner[1]), Double.parseDouble(topLeftCorner[0]));
+                } else {
+                    tileMatrix.topLeftCorner = new EastNorth(Double.parseDouble(topLeftCorner[0]), Double.parseDouble(topLeftCorner[1]));
+                }
                 tileMatrix.tileHeight = Integer.parseInt(getStringByXpath(tileMatrixNode, "TileHeight"));
                 tileMatrix.tileWidth = Integer.parseInt(getStringByXpath(tileMatrixNode, "TileHeight"));
@@ -291,5 +301,5 @@
     private static String crsToCode(String crsIdentifier) {
         if (crsIdentifier.startsWith("urn:ogc:def:crs:")) {
-            return crsIdentifier.replaceFirst("urn:ogc:def:crs:([^:]*):[^:]*:(.*)$", "$1:$2");
+            return crsIdentifier.replaceFirst("urn:ogc:def:crs:([^:]*):.*:(.*)$", "$1:$2");
         }
         return crsIdentifier;
@@ -439,5 +449,5 @@
         }
         double scale = matrix.scaleDenominator * this.crsScale;
-        EastNorth ret = new EastNorth(matrix.topLeftCorner.getX() + x * scale, matrix.topLeftCorner.getY() - y * scale);
+        EastNorth ret = new EastNorth(matrix.topLeftCorner.east() + x * scale, matrix.topLeftCorner.north() - y * scale);
         return Main.getProjection().eastNorth2latlon(ret).toCoordinate();
     }
@@ -589,5 +599,5 @@
         EastNorth min = proj.latlon2eastNorth(bounds.getMin());
         EastNorth max = proj.latlon2eastNorth(bounds.getMax());
-        return (int) Math.ceil(Math.abs(max.getY() - min.getY()) / scale);
+        return (int) Math.ceil(Math.abs(max.north() - min.north()) / scale);
     }
 
@@ -601,5 +611,5 @@
         EastNorth min = proj.latlon2eastNorth(bounds.getMin());
         EastNorth max = proj.latlon2eastNorth(bounds.getMax());
-        return (int) Math.ceil(Math.abs(max.getX() - min.getX()) / scale);
+        return (int) Math.ceil(Math.abs(max.east() - min.east()) / scale);
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java	(revision 8582)
+++ trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java	(revision 8584)
@@ -50,4 +50,5 @@
     protected Bounds bounds;
     private double metersPerUnit = METER_PER_UNIT_DEGREE; // default to degrees
+    private String axis = "enu"; // default axis orientation is East, North, Up
 
     /**
@@ -98,5 +99,8 @@
         no_defs("no_defs", false),
         init("init", true),
+        /** crs units to meter multiplier */
         to_meter("to_meter", true),
+        /** definition of axis for projection */
+        axis("axis", true),
         // JOSM extensions, not present in PROJ.4
         wmssrs("wmssrs", true),
@@ -212,4 +216,8 @@
             if (s != null) {
                 this.metersPerUnit = parseDouble(s, Param.to_meter.key);
+            }
+            s = parameters.get(Param.axis.key);
+            if (s != null) {
+                this.axis  = s;
             }
         }
@@ -548,4 +556,10 @@
     }
 
+    @Override
+    public boolean switchXY() {
+        // TODO: support for other axis orientation such as West South, and Up Down
+        return this.axis.startsWith("ne");
+    }
+
     private static Map<String, Double> getUnitsToMeters() {
         Map<String, Double> ret = new ConcurrentHashMap<>();
Index: trunk/src/org/openstreetmap/josm/data/projection/Projection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/Projection.java	(revision 8582)
+++ trunk/src/org/openstreetmap/josm/data/projection/Projection.java	(revision 8584)
@@ -79,3 +79,11 @@
      */
     double getMetersPerUnit();
+
+    /**
+     * Does this projection natural order of coordinates is North East,
+     * instead of East North
+     *
+     * @return true if natural order of coordinates is North East, false if East North
+     */
+    boolean switchXY();
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/WMTSLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/WMTSLayer.java	(revision 8582)
+++ trunk/src/org/openstreetmap/josm/gui/layer/WMTSLayer.java	(revision 8584)
@@ -69,9 +69,9 @@
                 return tileSource;
             }
-        } catch (Exception e) {
-            Main.warn("Could not create imagery layer:");
+            return null;
+        } catch (IOException e) {
             Main.warn(e);
+            throw new IllegalArgumentException(e);
         }
-        return null;
     }
 
