001 // License: GPL. Copyright 2007 by Immanuel Scholz and others 002 package org.openstreetmap.josm.data.projection; 003 004 import java.io.BufferedReader; 005 import java.io.IOException; 006 import java.io.InputStream; 007 import java.io.InputStreamReader; 008 import java.util.HashMap; 009 import java.util.Map; 010 import java.util.regex.Matcher; 011 import java.util.regex.Pattern; 012 013 import org.openstreetmap.josm.Main; 014 import org.openstreetmap.josm.data.coor.EastNorth; 015 import org.openstreetmap.josm.data.coor.LatLon; 016 import org.openstreetmap.josm.data.projection.datum.Datum; 017 import org.openstreetmap.josm.data.projection.datum.NTV2GridShiftFileWrapper; 018 import org.openstreetmap.josm.data.projection.datum.WGS84Datum; 019 import org.openstreetmap.josm.data.projection.proj.ClassProjFactory; 020 import org.openstreetmap.josm.data.projection.proj.LambertConformalConic; 021 import org.openstreetmap.josm.data.projection.proj.LonLat; 022 import org.openstreetmap.josm.data.projection.proj.Proj; 023 import org.openstreetmap.josm.data.projection.proj.ProjFactory; 024 import org.openstreetmap.josm.data.projection.proj.SwissObliqueMercator; 025 import org.openstreetmap.josm.data.projection.proj.TransverseMercator; 026 import org.openstreetmap.josm.io.MirroredInputStream; 027 028 /** 029 * Class to handle projections 030 * 031 */ 032 public class Projections { 033 034 public static EastNorth project(LatLon ll) { 035 if (ll == null) return null; 036 return Main.getProjection().latlon2eastNorth(ll); 037 } 038 039 public static LatLon inverseProject(EastNorth en) { 040 if (en == null) return null; 041 return Main.getProjection().eastNorth2latlon(en); 042 } 043 044 /********************************* 045 * Registry for custom projection 046 * 047 * should be compatible to PROJ.4 048 */ 049 public static Map<String, ProjFactory> projs = new HashMap<String, ProjFactory>(); 050 public static Map<String, Ellipsoid> ellipsoids = new HashMap<String, Ellipsoid>(); 051 public static Map<String, Datum> datums = new HashMap<String, Datum>(); 052 public static Map<String, NTV2GridShiftFileWrapper> nadgrids = new HashMap<String, NTV2GridShiftFileWrapper>(); 053 public static Map<String, String> inits = new HashMap<String, String>(); 054 055 static { 056 registerBaseProjection("lonlat", LonLat.class, "core"); 057 registerBaseProjection("josm:smerc", org.openstreetmap.josm.data.projection.proj.Mercator.class, "core"); 058 registerBaseProjection("lcc", LambertConformalConic.class, "core"); 059 registerBaseProjection("somerc", SwissObliqueMercator.class, "core"); 060 registerBaseProjection("tmerc", TransverseMercator.class, "core"); 061 062 ellipsoids.put("intl", Ellipsoid.hayford); 063 ellipsoids.put("GRS80", Ellipsoid.GRS80); 064 ellipsoids.put("WGS84", Ellipsoid.WGS84); 065 ellipsoids.put("bessel", Ellipsoid.Bessel1841); 066 067 datums.put("WGS84", WGS84Datum.INSTANCE); 068 069 nadgrids.put("BETA2007.gsb", NTV2GridShiftFileWrapper.BETA2007); 070 nadgrids.put("ntf_r93_b.gsb", NTV2GridShiftFileWrapper.ntf_rgf93); 071 072 loadInits(); 073 } 074 075 /** 076 * Plugins can register additional base projections. 077 * 078 * @param id The "official" PROJ.4 id. In case the projection is not supported 079 * by PROJ.4, use some prefix, e.g. josm:myproj or gdal:otherproj. 080 * @param fac The base projection factory. 081 * @param origin Multiple plugins may implement the same base projection. 082 * Provide plugin name or similar string, so it be differentiated. 083 */ 084 public static void registerBaseProjection(String id, ProjFactory fac, String origin) { 085 projs.put(id, fac); 086 } 087 088 public static void registerBaseProjection(String id, Class<? extends Proj> projClass, String origin) { 089 registerBaseProjection(id, new ClassProjFactory(projClass), origin); 090 } 091 092 public static Proj getBaseProjection(String id) { 093 ProjFactory fac = projs.get(id); 094 if (fac == null) return null; 095 return fac.createInstance(); 096 } 097 098 public static Ellipsoid getEllipsoid(String id) { 099 return ellipsoids.get(id); 100 } 101 102 public static Datum getDatum(String id) { 103 return datums.get(id); 104 } 105 106 public static NTV2GridShiftFileWrapper getNTV2Grid(String id) { 107 return nadgrids.get(id); 108 } 109 110 public static String getInit(String id) { 111 return inits.get(id); 112 } 113 114 /** 115 * Load +init "presets" from file 116 */ 117 private static void loadInits() { 118 Pattern epsgPattern = Pattern.compile("\\A<(\\d+)>(.*)<>\\Z"); 119 try { 120 InputStream in = new MirroredInputStream("resource://data/epsg"); 121 BufferedReader r = new BufferedReader(new InputStreamReader(in)); 122 String line; 123 while ((line = r.readLine()) != null) { 124 line = line.trim(); 125 if (!line.startsWith("#") && !line.isEmpty()) { 126 Matcher m = epsgPattern.matcher(line); 127 if (m.matches()) { 128 inits.put("epsg:" + m.group(1), m.group(2).trim()); 129 } else { 130 System.err.println("Warning: failed to parse line from the epsg projection definition: "+line); 131 } 132 } 133 } 134 } catch (IOException ex) { 135 throw new RuntimeException(); 136 } 137 } 138 }