OSMap 0.1.0をリリース
@@ -0,0 +1,228 @@ | ||
1 | +import java.awt.BorderLayout; | |
2 | +import java.awt.Dimension; | |
3 | +import java.awt.Graphics; | |
4 | +import java.awt.Graphics2D; | |
5 | +import java.awt.Image; | |
6 | +import java.awt.RenderingHints; | |
7 | +import java.awt.event.MouseAdapter; | |
8 | +import java.awt.event.MouseEvent; | |
9 | +import java.awt.event.MouseMotionListener; | |
10 | +import java.awt.event.MouseWheelEvent; | |
11 | +import java.awt.event.MouseWheelListener; | |
12 | +import java.io.File; | |
13 | +import java.io.FileOutputStream; | |
14 | +import java.io.IOException; | |
15 | +import java.net.MalformedURLException; | |
16 | +import java.net.URL; | |
17 | +import java.util.Formatter; | |
18 | +import java.util.HashMap; | |
19 | +import java.util.Map; | |
20 | +import java.util.TimerTask; | |
21 | + | |
22 | +import javax.imageio.IIOException; | |
23 | +import javax.imageio.ImageIO; | |
24 | +import javax.swing.JFrame; | |
25 | +import javax.swing.JLabel; | |
26 | +import javax.swing.JPanel; | |
27 | +import javax.swing.WindowConstants; | |
28 | + | |
29 | +/** | |
30 | + * OpenStreetMapのビューア | |
31 | + */ | |
32 | +public class Main { | |
33 | + /** | |
34 | + * タイルの大きさ[px] | |
35 | + */ | |
36 | + public static int TILE_SIZE = 256; | |
37 | + /** | |
38 | + * キャッシュファイルを置くディレクトリ | |
39 | + */ | |
40 | + public static String CACHE_DIRECTORY = "cache"; | |
41 | + /** | |
42 | + * 縮尺 | |
43 | + */ | |
44 | + static int zoom = 5; | |
45 | + /** | |
46 | + * 列 | |
47 | + */ | |
48 | + static int col = 27; | |
49 | + /** | |
50 | + * 行 | |
51 | + */ | |
52 | + static int row = 12; | |
53 | + /** | |
54 | + * x座標 | |
55 | + */ | |
56 | + static int offsetX = 20; | |
57 | + /** | |
58 | + * y座標 | |
59 | + */ | |
60 | + static int offsetY = 150; | |
61 | + /** | |
62 | + * マウスドラッグが開始されたx座標 | |
63 | + */ | |
64 | + static int lastX = 0; | |
65 | + /** | |
66 | + * マウスドラッグが開始されたy座標 | |
67 | + */ | |
68 | + static int lastY = 0; | |
69 | + | |
70 | + /** | |
71 | + * メインメソッド | |
72 | + * @param args コマンドライン引数 | |
73 | + * @throws IOException 入出力例外 | |
74 | + */ | |
75 | + public static void main(final String[] args) throws IOException { | |
76 | + final Map<String, Image> images = new HashMap<String, Image>(); | |
77 | + final JFrame frame = new JFrame("OSMap"); | |
78 | + frame.setLayout(new BorderLayout()); | |
79 | + final JLabel label = new JLabel(" "); | |
80 | + final JPanel panel = new JPanel() { | |
81 | + @Override | |
82 | + protected void paintComponent(final Graphics graphics) { | |
83 | + super.paintComponent(graphics); | |
84 | + final Graphics2D g = (Graphics2D) graphics; | |
85 | + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); | |
86 | + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); | |
87 | + for (int i = -1; TILE_SIZE * i + offsetY < this.getHeight(); i++) { | |
88 | + if (row + i < 0 || row + i >= 1 << zoom) { | |
89 | + continue; | |
90 | + } | |
91 | + for (int j = -1; TILE_SIZE * j + offsetX < this.getWidth(); j++) { | |
92 | + if (col + j < 0 || col + j >= 1 << zoom) { | |
93 | + continue; | |
94 | + } | |
95 | + g.drawImage(images.get(zoom + "_" + (col + j) + "_" + (row + i)), TILE_SIZE * j + offsetX, | |
96 | + TILE_SIZE * i + offsetY, this); | |
97 | + g.drawRect(TILE_SIZE * j + offsetX, TILE_SIZE * i + offsetY, TILE_SIZE, TILE_SIZE); | |
98 | + g.drawString(zoom + "_" + (col + j) + "_" + (row + i), TILE_SIZE * j + offsetX, TILE_SIZE * i | |
99 | + + offsetY + TILE_SIZE - 2); | |
100 | + } | |
101 | + } | |
102 | + label.setText(new Formatter().format("zoom = %d, col = %d, row = %d, offsetX = %d, offsetY = %d\n", | |
103 | + zoom, col, row, offsetX, offsetY).toString()); | |
104 | + } | |
105 | + }; | |
106 | + panel.setPreferredSize(new Dimension(640, 480)); | |
107 | + frame.add(panel, BorderLayout.CENTER); | |
108 | + frame.add(label, BorderLayout.SOUTH); | |
109 | + panel.addMouseWheelListener(new MouseWheelListener() { | |
110 | + @Override | |
111 | + public void mouseWheelMoved(final MouseWheelEvent event) { | |
112 | + final int clickedCol = (event.getX() - offsetX + TILE_SIZE) / TILE_SIZE - 1; | |
113 | + final int clickedRow = (event.getY() - offsetY + TILE_SIZE) / TILE_SIZE - 1; | |
114 | + final int diffX = (event.getX() - offsetX + TILE_SIZE) % TILE_SIZE; | |
115 | + final int diffY = (event.getY() - offsetY + TILE_SIZE) % TILE_SIZE; | |
116 | + if (event.getWheelRotation() < 0) { | |
117 | + if (zoom < 18) { | |
118 | + zoom++; | |
119 | + col = col * 2 + clickedCol + (diffX < TILE_SIZE / 2 ? 0 : 1); | |
120 | + row = row * 2 + clickedRow + (diffY < TILE_SIZE / 2 ? 0 : 1); | |
121 | + offsetX = offsetX - diffX % TILE_SIZE + (diffX < TILE_SIZE / 2 ? 0 : TILE_SIZE); | |
122 | + offsetY = offsetY - diffY % TILE_SIZE + (diffY < TILE_SIZE / 2 ? 0 : TILE_SIZE); | |
123 | + } | |
124 | + } else { | |
125 | + if (zoom > 0) { | |
126 | + zoom--; | |
127 | + offsetX = offsetX + diffX / 2 - (col % 2 == 0 ? 0 : TILE_SIZE / 2) + clickedCol * TILE_SIZE / 2; | |
128 | + offsetY = offsetY + diffY / 2 - (row % 2 == 0 ? 0 : TILE_SIZE / 2) + clickedRow * TILE_SIZE / 2; | |
129 | + col /= 2; | |
130 | + row /= 2; | |
131 | + } | |
132 | + } | |
133 | + panel.repaint(); | |
134 | + } | |
135 | + }); | |
136 | + panel.addMouseListener(new MouseAdapter() { | |
137 | + @Override | |
138 | + public void mouseClicked(final MouseEvent event) { | |
139 | + if (event.getButton() == MouseEvent.BUTTON1) { | |
140 | + } else if (event.getButton() == MouseEvent.BUTTON3) { | |
141 | + } | |
142 | + panel.repaint(); | |
143 | + } | |
144 | + | |
145 | + @Override | |
146 | + public void mousePressed(final MouseEvent event) { | |
147 | + lastX = event.getX(); | |
148 | + lastY = event.getY(); | |
149 | + } | |
150 | + }); | |
151 | + panel.addMouseMotionListener(new MouseMotionListener() { | |
152 | + @Override | |
153 | + public void mouseMoved(final MouseEvent event) { | |
154 | + } | |
155 | + | |
156 | + @Override | |
157 | + public void mouseDragged(final MouseEvent event) { | |
158 | + offsetX += event.getX() - lastX; | |
159 | + offsetY += event.getY() - lastY; | |
160 | + lastX = event.getX(); | |
161 | + lastY = event.getY(); | |
162 | + panel.repaint(); | |
163 | + } | |
164 | + }); | |
165 | + frame.pack(); | |
166 | + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); | |
167 | + JFrame.setDefaultLookAndFeelDecorated(true); | |
168 | + frame.setLocationByPlatform(true); | |
169 | + frame.setVisible(true); | |
170 | + new java.util.Timer().scheduleAtFixedRate(new TimerTask() { | |
171 | + @Override | |
172 | + public void run() { | |
173 | + if (offsetX < 0) { | |
174 | + offsetX += TILE_SIZE; | |
175 | + col++; | |
176 | + } else if (offsetX >= TILE_SIZE) { | |
177 | + offsetX -= TILE_SIZE; | |
178 | + col--; | |
179 | + } | |
180 | + if (offsetY < 0) { | |
181 | + offsetY += TILE_SIZE; | |
182 | + row++; | |
183 | + } else if (offsetY >= TILE_SIZE) { | |
184 | + offsetY -= TILE_SIZE; | |
185 | + row--; | |
186 | + } | |
187 | + final int zoom = Main.zoom; | |
188 | + final int col = Main.col; | |
189 | + final int row = Main.row; | |
190 | + final File cacheDirectory = new File(CACHE_DIRECTORY); | |
191 | + if (!cacheDirectory.isDirectory()) { | |
192 | + cacheDirectory.mkdir(); | |
193 | + } | |
194 | + for (int i = -1; TILE_SIZE * i + offsetY < panel.getHeight(); i++) { | |
195 | + if (row + i < 0 || row + i >= 1 << zoom) { | |
196 | + continue; | |
197 | + } | |
198 | + for (int j = -1; TILE_SIZE * j + offsetX < panel.getWidth(); j++) { | |
199 | + if (col + j < 0 || col + j >= 1 << zoom) { | |
200 | + continue; | |
201 | + } | |
202 | + if (!images.containsKey(zoom + "_" + (col + j) + "_" + (row + i))) { | |
203 | + final File file = new File(new Formatter().format("%s%s%d_%d_%d.png", CACHE_DIRECTORY, | |
204 | + File.separator, zoom, col + j, row + i).toString()); | |
205 | + try { | |
206 | + if (!file.isFile()) { | |
207 | + WebUtilities.copy( | |
208 | + new URL(new Formatter().format( | |
209 | + "http://tile.openstreetmap.org/%d/%d/%d.png", zoom, col + j, | |
210 | + row + i).toString()).openStream(), new FileOutputStream(file)); | |
211 | + } | |
212 | + images.put(zoom + "_" + (col + j) + "_" + (row + i), ImageIO.read(file)); | |
213 | + panel.repaint(); | |
214 | + } catch (final IIOException exception) { | |
215 | + file.delete(); | |
216 | + } catch (final MalformedURLException exception) { | |
217 | + exception.printStackTrace(); | |
218 | + } catch (final IOException exception) { | |
219 | + exception.printStackTrace(); | |
220 | + } | |
221 | + } | |
222 | + } | |
223 | + } | |
224 | + panel.repaint(); | |
225 | + } | |
226 | + }, 200, 200); | |
227 | + } | |
228 | +} |
@@ -0,0 +1,23 @@ | ||
1 | +import java.io.IOException; | |
2 | +import java.io.InputStream; | |
3 | +import java.io.OutputStream; | |
4 | + | |
5 | +/** | |
6 | + * ネットワーク関係のユーティリティクラス | |
7 | + */ | |
8 | +public class WebUtilities { | |
9 | + /** | |
10 | + * ストリームを使ってファイルをコピーします。 | |
11 | + * @param in 入力ストリーム | |
12 | + * @param out 出力ストリーム | |
13 | + * @throws IOException 入出力例外 | |
14 | + */ | |
15 | + public static void copy(final InputStream in, final OutputStream out) throws IOException { | |
16 | + final byte buf[] = new byte[1024]; | |
17 | + int size; | |
18 | + while ((size = in.read(buf)) != -1) { | |
19 | + out.write(buf, 0, size); | |
20 | + } | |
21 | + out.close(); | |
22 | + } | |
23 | +} |