1 | // License: GPL. See LICENSE file for details.
|
---|
2 | package org.openstreetmap.josm.gui.download;
|
---|
3 |
|
---|
4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
5 |
|
---|
6 | import java.awt.Dimension;
|
---|
7 | import java.awt.GridBagLayout;
|
---|
8 | import java.awt.event.FocusAdapter;
|
---|
9 | import java.awt.event.FocusEvent;
|
---|
10 | import java.awt.event.FocusListener;
|
---|
11 |
|
---|
12 | import javax.swing.JLabel;
|
---|
13 | import javax.swing.JPanel;
|
---|
14 | import javax.swing.JSpinner;
|
---|
15 | import javax.swing.JTextField;
|
---|
16 | import javax.swing.SpinnerNumberModel;
|
---|
17 |
|
---|
18 | import org.openstreetmap.josm.data.Bounds;
|
---|
19 | import org.openstreetmap.josm.data.coor.LatLon;
|
---|
20 | import org.openstreetmap.josm.tools.GBC;
|
---|
21 | /**
|
---|
22 | * Tile selector.
|
---|
23 | *
|
---|
24 | * Provides a tile coordinate input field.
|
---|
25 | *
|
---|
26 | * @author Frederik Ramm <frederik@remote.org>
|
---|
27 | *
|
---|
28 | */
|
---|
29 | public class TileSelection implements DownloadSelection {
|
---|
30 |
|
---|
31 | private JTextField tileX0 = new JTextField(7);
|
---|
32 | private JTextField tileY0 = new JTextField(7);
|
---|
33 | private JTextField tileX1 = new JTextField(7);
|
---|
34 | private JTextField tileY1 = new JTextField(7);
|
---|
35 | private JSpinner tileZ = new JSpinner(new SpinnerNumberModel(12, 10, 18, 1));
|
---|
36 |
|
---|
37 | public void addGui(final DownloadDialog gui) {
|
---|
38 |
|
---|
39 | JPanel smpanel = new JPanel(new GridBagLayout());
|
---|
40 | smpanel.add(new JLabel(tr("zoom level")), GBC.std().insets(0,0,10,0));
|
---|
41 | smpanel.add(new JLabel(tr("x from")), GBC.std().insets(10,0,5,0));
|
---|
42 | smpanel.add(tileX0, GBC.std());
|
---|
43 | smpanel.add(new JLabel(tr("to")), GBC.std().insets(10,0,5,0));
|
---|
44 | smpanel.add(tileX1, GBC.eol());
|
---|
45 | smpanel.add(tileZ, GBC.std().insets(0,0,10,0));
|
---|
46 | smpanel.add(new JLabel(tr("y from")), GBC.std().insets(10,0,5,0));
|
---|
47 | smpanel.add(tileY0, GBC.std());
|
---|
48 | smpanel.add(new JLabel(tr("to")), GBC.std().insets(10,0,5,0));
|
---|
49 | smpanel.add(tileY1, GBC.eol());
|
---|
50 |
|
---|
51 | final FocusListener dialogUpdater = new FocusAdapter() {
|
---|
52 | @Override public void focusLost(FocusEvent e) {
|
---|
53 | try {
|
---|
54 | int zoomlvl = (Integer) tileZ.getValue();
|
---|
55 | int fromx = Integer.parseInt(tileX0.getText());
|
---|
56 | int tox = fromx;
|
---|
57 | if (tileX1.getText().length()>0) {
|
---|
58 | tox = Integer.parseInt(tileX1.getText());
|
---|
59 | }
|
---|
60 | if (tox<fromx) { int i = fromx; fromx=tox; tox=i; }
|
---|
61 |
|
---|
62 | int fromy = Integer.parseInt(tileY0.getText());
|
---|
63 | int toy = fromy;
|
---|
64 | if (tileY1.getText().length()>0) {
|
---|
65 | toy = Integer.parseInt(tileY1.getText());
|
---|
66 | }
|
---|
67 | if (toy<fromy) { int i = fromy; fromy=toy; toy=i; }
|
---|
68 |
|
---|
69 | Bounds b = new Bounds(
|
---|
70 | new LatLon(tileYToLat(zoomlvl, toy + 1), tileXToLon(zoomlvl, fromx)),
|
---|
71 | new LatLon(tileYToLat(zoomlvl, fromy), tileXToLon(zoomlvl, tox + 1))
|
---|
72 | );
|
---|
73 | gui.boundingBoxChanged(b, TileSelection.this);
|
---|
74 | //repaint();
|
---|
75 | } catch (NumberFormatException x) {
|
---|
76 | // ignore
|
---|
77 | }
|
---|
78 | }
|
---|
79 | };
|
---|
80 |
|
---|
81 | for (JTextField f : new JTextField[] { tileX0, tileX1, tileY0, tileY1 }) {
|
---|
82 | f.setMinimumSize(new Dimension(100,new JTextField().getMinimumSize().height));
|
---|
83 | f.addFocusListener(dialogUpdater);
|
---|
84 | }
|
---|
85 |
|
---|
86 | gui.addDownloadAreaSelector(smpanel, tr("Tile Numbers"));
|
---|
87 | }
|
---|
88 |
|
---|
89 | /**
|
---|
90 | * Called when bounding box is changed by one of the other download dialog tabs.
|
---|
91 | */
|
---|
92 | public void boundingBoxChanged(DownloadDialog gui) {
|
---|
93 | updateBboxFields(gui);
|
---|
94 | }
|
---|
95 |
|
---|
96 | private void updateBboxFields(DownloadDialog gui) {
|
---|
97 | int z = ((Integer) tileZ.getValue()).intValue();
|
---|
98 | Bounds b = gui.getSelectedDownloadArea();
|
---|
99 | if (b == null)
|
---|
100 | return;
|
---|
101 | tileX0.setText(Integer.toString(lonToTileX(z, b.getMin().lon())));
|
---|
102 | tileX1.setText(Integer.toString(lonToTileX(z, b.getMax().lon()-.00001)));
|
---|
103 | tileY0.setText(Integer.toString(latToTileY(z, b.getMax().lat()-.00001)));
|
---|
104 | tileY1.setText(Integer.toString(latToTileY(z, b.getMin().lat())));
|
---|
105 | }
|
---|
106 |
|
---|
107 | public static int latToTileY(int zoom, double lat) {
|
---|
108 | if ((zoom < 3) || (zoom > 18)) return -1;
|
---|
109 | double l = lat / 180 * Math.PI;
|
---|
110 | double pf = Math.log(Math.tan(l) + (1/Math.cos(l)));
|
---|
111 | return (int) ((1<<(zoom-1)) * (Math.PI - pf) / Math.PI);
|
---|
112 | }
|
---|
113 |
|
---|
114 | public static int lonToTileX(int zoom, double lon) {
|
---|
115 | if ((zoom < 3) || (zoom > 18)) return -1;
|
---|
116 | return (int) ((1<<(zoom-3)) * (lon + 180.0) / 45.0);
|
---|
117 | }
|
---|
118 |
|
---|
119 | public static double tileYToLat(int zoom, int y) {
|
---|
120 | if ((zoom < 3) || (zoom > 18)) return Double.MIN_VALUE;
|
---|
121 | return Math.atan(Math.sinh(Math.PI - (Math.PI*y / (1<<(zoom-1))))) * 180 / Math.PI;
|
---|
122 | }
|
---|
123 |
|
---|
124 | public static double tileXToLon(int zoom, int x) {
|
---|
125 | if ((zoom < 3) || (zoom > 18)) return Double.MIN_VALUE;
|
---|
126 | return x * 45.0 / (1<<(zoom-3)) - 180.0;
|
---|
127 |
|
---|
128 | }
|
---|
129 | }
|
---|