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

Last change on this file since 3734 was 3083, checked in by bastiK, 14 years ago

added svn:eol-style=native to source files

  • Property svn:eol-style set to native
File size: 5.7 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 final String shortLink = url.substring(SHORTLINK_PREFIX.length());
86
87 final Map<Character, Integer> array = new HashMap<Character, Integer>();
88
89 for (int i=0; i<SHORTLINK_CHARS.length; ++i) {
90 array.put(SHORTLINK_CHARS[i], i);
91 }
92
93 // long is necessary (need 32 bit positive value is needed)
94 long x = 0;
95 long y = 0;
96 int zoom = 0;
97 int zoomOffset = 0;
98
99 for (final char ch : shortLink.toCharArray()) {
100 if (array.containsKey(ch)) {
101 int val = array.get(ch);
102 for (int i=0; i<3; ++i) {
103 x <<= 1;
104 if ((val & 32) != 0) {
105 x |= 1;
106 }
107 val <<= 1;
108
109 y <<= 1;
110 if ((val & 32) != 0) {
111 y |= 1;
112 }
113 val <<= 1;
114 }
115 zoom += 3;
116 } else {
117 zoomOffset--;
118 }
119 }
120
121 x <<= 32 - zoom;
122 y <<= 32 - zoom;
123
124 // 2**32 == 4294967296
125 return positionToBounds(y * 180.0 / 4294967296.0 - 90.0,
126 x * 360.0 / 4294967296.0 - 180.0,
127 // TODO: -2 was not in ruby code
128 zoom - 8 - (zoomOffset % 3) - 2);
129 }
130
131 public static Bounds positionToBounds(final double lat, final double lon, final int zoom) {
132 final double size = 180.0 / Math.pow(2, zoom);
133 return new Bounds(
134 new LatLon(lat - size/2, lon - size),
135 new LatLon(lat + size/2, lon + size));
136 }
137
138 static public int getZoom(Bounds b) {
139 // convert to mercator (for calculation of zoom only)
140 double latMin = Math.log(Math.tan(Math.PI/4.0+b.getMin().lat()/180.0*Math.PI/2.0))*180.0/Math.PI;
141 double latMax = Math.log(Math.tan(Math.PI/4.0+b.getMax().lat()/180.0*Math.PI/2.0))*180.0/Math.PI;
142 double size = Math.max(Math.abs(latMax-latMin), Math.abs(b.getMax().lon()-b.getMin().lon()));
143 int zoom = 0;
144 while (zoom <= 20) {
145 if (size >= 180) {
146 break;
147 }
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 "http://www.openstreetmap.org/?lat="+lat+"&lon="+lon+"&zoom="+zoom;
166 }
167}
Note: See TracBrowser for help on using the repository browser.