source: josm/trunk/src/org/openstreetmap/josm/tools/OsmUrlToBounds.java@ 2610

Last change on this file since 2610 was 2540, checked in by stoecker, 14 years ago

applied #2892 - patch by plaicy - added osmgo shortlink support to url decoder

File size: 5.8 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.tools;
3
4import java.util.HashMap;
5import java.util.Map;
6
7import org.openstreetmap.josm.data.Bounds;
8import org.openstreetmap.josm.data.coor.LatLon;
9
10public class OsmUrlToBounds {
11 private static final String SHORTLINK_PREFIX = "http://osm.org/go/";
12
13 public static Bounds parse(String url) {
14 Bounds b = parseShortLink(url);
15 if (b != null)
16 return b;
17 int i = url.indexOf('?');
18 if (i == -1)
19 return null;
20 String[] args = url.substring(i+1).split("&");
21 HashMap<String, String> map = new HashMap<String, String>();
22 for (String arg : args) {
23 int eq = arg.indexOf('=');
24 if (eq != -1) {
25 map.put(arg.substring(0, eq), arg.substring(eq + 1));
26 }
27 }
28
29 try {
30 if (map.containsKey("bbox")) {
31 String bbox[] = map.get("bbox").split(",");
32 b = new Bounds(
33 new LatLon(Double.parseDouble(bbox[1]), Double.parseDouble(bbox[0])),
34 new LatLon(Double.parseDouble(bbox[3]), Double.parseDouble(bbox[2])));
35 } else if (map.containsKey("minlat")) {
36 String s = map.get("minlat");
37 Double minlat = Double.parseDouble(s);
38 s = map.get("minlon");
39 Double minlon = Double.parseDouble(s);
40 s = map.get("maxlat");
41 Double maxlat = Double.parseDouble(s);
42 s = map.get("maxlon");
43 Double maxlon = Double.parseDouble(s);
44 b = new Bounds(new LatLon(minlat, minlon), new LatLon(maxlat, maxlon));
45 } else {
46 b = positionToBounds(parseDouble(map, "lat"),
47 parseDouble(map, "lon"),
48 Integer.parseInt(map.get("zoom")));
49 }
50 } catch (NumberFormatException x) {
51 } catch (NullPointerException x) {
52 }
53 return b;
54 }
55
56 private static double parseDouble(HashMap<String, String> map, String key) {
57 if (map.containsKey(key))
58 return Double.parseDouble(map.get(key));
59 return Double.parseDouble(map.get("m"+key));
60 }
61
62 private static final char[] SHORTLINK_CHARS = {
63 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
64 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
65 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
66 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
67 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
68 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
69 'w', 'x', 'y', 'z', '0', '1', '2', '3',
70 '4', '5', '6', '7', '8', '9', '_', '@'
71 };
72
73 /**
74 * p
75 *
76 * @param url string for parsing
77 *
78 * @return Bounds if shortlink, null otherwise
79 *
80 * @see http://trac.openstreetmap.org/browser/sites/rails_port/lib/short_link.rb
81 */
82 private static Bounds parseShortLink(final String url) {
83 if (!url.startsWith(SHORTLINK_PREFIX)) {
84 return null;
85 }
86 final String shortLink = url.substring(SHORTLINK_PREFIX.length());
87
88 final Map<Character, Integer> array = new HashMap<Character, Integer>();
89
90 for (int i=0; i<SHORTLINK_CHARS.length; ++i) {
91 array.put(SHORTLINK_CHARS[i], i);
92 }
93
94 // long is necessary (need 32 bit positive value is needed)
95 long x = 0;
96 long y = 0;
97 int zoom = 0;
98 int zoomOffset = 0;
99
100 for (final char ch : shortLink.toCharArray()) {
101 if (array.containsKey(ch)) {
102 int val = array.get(ch);
103 for (int i=0; i<3; ++i) {
104 x <<= 1;
105 if ((val & 32) != 0) {
106 x |= 1;
107 }
108 val <<= 1;
109
110 y <<= 1;
111 if ((val & 32) != 0) {
112 y |= 1;
113 }
114 val <<= 1;
115 }
116 zoom += 3;
117 } else {
118 zoomOffset--;
119 }
120 }
121
122 x <<= 32 - zoom;
123 y <<= 32 - zoom;
124
125 // 2**32 == 4294967296
126 return positionToBounds(y * 180.0 / 4294967296.0 - 90.0,
127 x * 360.0 / 4294967296.0 - 180.0,
128 // TODO: -2 was not in ruby code
129 zoom - 8 - (zoomOffset % 3) - 2);
130 }
131
132 private static Bounds positionToBounds(final double lat, final double lon, final int zoom) {
133 final double size = 180.0 / Math.pow(2, zoom);
134 return new Bounds(
135 new LatLon(lat - size/2, lon - size),
136 new LatLon(lat + size/2, lon + size));
137 }
138
139 static public int getZoom(Bounds b) {
140 // convert to mercator (for calculation of zoom only)
141 double latMin = Math.log(Math.tan(Math.PI/4.0+b.getMin().lat()/180.0*Math.PI/2.0))*180.0/Math.PI;
142 double latMax = Math.log(Math.tan(Math.PI/4.0+b.getMax().lat()/180.0*Math.PI/2.0))*180.0/Math.PI;
143 double size = Math.max(Math.abs(latMax-latMin), Math.abs(b.getMax().lon()-b.getMin().lon()));
144 int zoom = 0;
145 while (zoom <= 20) {
146 if (size >= 180)
147 break;
148 size *= 2;
149 zoom++;
150 }
151 return zoom;
152 }
153
154 static public String getURL(Bounds b) {
155 return getURL(b.getCenter(), getZoom(b));
156 }
157
158 static public String getURL(LatLon pos, int zoom) {
159 // Truncate lat and lon to something more sensible
160 int decimals = (int) Math.pow(10, (zoom / 3));
161 double lat = (Math.round(pos.lat() * decimals));
162 lat /= decimals;
163 double lon = (Math.round(pos.lon() * decimals));
164 lon /= decimals;
165 return new String("http://www.openstreetmap.org/?lat="+lat+"&lon="+lon+"&zoom="+zoom);
166 }
167}
Note: See TracBrowser for help on using the repository browser.