[josm-dev] [PATCH] Tile Box download tab plugin

Robert Fitzsimons robfitz at 273k.net
Sun Nov 11 18:46:08 GMT 2007


New plugin which adds a Tile Box tab to the OSM data download dialog.
The user enters a tile zoom level and tile coordinates and a suitable
bounding box is used to download the OSM data.

Signed-off-by: Robert Fitzsimons <robfitz at 273k.net>

---

Thanks for the comments, heres a new patch to adds the code as a plugin.

Robert


Index: plugins/tilebox/src/tilebox/TileBoxPlugin.java
===================================================================
--- plugins/tilebox/src/tilebox/TileBoxPlugin.java	(revision 0)
+++ plugins/tilebox/src/tilebox/TileBoxPlugin.java	(revision 0)
@@ -0,0 +1,17 @@
+package tilebox;
+
+import java.util.List;
+
+import org.openstreetmap.josm.gui.download.DownloadSelection;
+import org.openstreetmap.josm.plugins.Plugin;
+
+public class TileBoxPlugin extends Plugin {
+	public TileBoxPlugin() {
+	}
+	
+	@Override
+	public void addDownloadSelection(final List<DownloadSelection> list) {
+		list.add(new TileBoxSelection());
+	}
+}
+
Index: plugins/tilebox/src/tilebox/TileBoxSelection.java
===================================================================
--- plugins/tilebox/src/tilebox/TileBoxSelection.java	(revision 0)
+++ plugins/tilebox/src/tilebox/TileBoxSelection.java	(revision 0)
@@ -0,0 +1,154 @@
+// License: GPL. Copyright 2007 by Robert Fitzsimons, Immanuel Scholz and others
+package tilebox;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.GridBagLayout;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.josm.gui.download.DownloadDialog;
+import org.openstreetmap.josm.gui.download.DownloadSelection;
+import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.tools.GBC;
+
+/**
+ * Tile box selector.
+ * 
+ * @author Robert Fitzsimons <robfitz at 273k.net>
+ *
+ */
+public class TileBoxSelection implements DownloadSelection {
+	private final JTextField xField = new JTextField(8);
+	private final JTextField yField = new JTextField(8);
+	private final JTextField zoomField = new JTextField(4);
+
+	public void addGui(final DownloadDialog gui) {
+		final JPanel dlg = new JPanel(new GridBagLayout());
+
+		final FocusListener dialogUpdater = new FocusAdapter() {
+			@Override public void focusLost(final FocusEvent e) {
+				SwingUtilities.invokeLater(new Runnable() {
+					public void run() {
+						try {
+							final int zoom = TileBoxSelection.this.getZoom();
+							final int tileCount = tileCount(zoom);
+							final int x = Integer.parseInt(TileBoxSelection.this.xField.getText());
+							final int y = Integer.parseInt(TileBoxSelection.this.yField.getText());
+
+							if ((x < 0) || (x > tileCount) || (y < 0) || (x > tileCount)) {
+								return;
+							}
+
+							final double minlon = tileXToLongitude(x, zoom);
+							final double maxlon = minlon + tileXSize(zoom);
+
+							final double minlat = tileYToLatitude(y + 1, zoom);
+							final double maxlat = tileYToLatitude(y, zoom);
+
+							if (minlat != gui.minlat || minlon != gui.minlon || maxlat != gui.maxlat || maxlon != gui.maxlon) {
+								gui.minlat = minlat; gui.minlon = minlon; 
+								gui.maxlat = maxlat; gui.maxlon = maxlon;
+								gui.boundingBoxChanged(TileBoxSelection.this);
+							}
+						} catch (final NumberFormatException x) {
+							// ignore
+						}
+					}
+				});
+			}
+		};
+
+		this.zoomField.addFocusListener(dialogUpdater);
+		this.zoomField.setText("12");
+		this.xField.addFocusListener(dialogUpdater);
+		this.yField.addFocusListener(dialogUpdater);
+
+		dlg.add(new JLabel(tr("Enter the Zoom level, and X & Y coordinates for a tile image.")), GBC.eol().insets(10, 5, 5, 0));
+		dlg.add(new JLabel(tr("Zoom")), GBC.std().insets(10, 5, 5, 0));
+		dlg.add(this.zoomField, GBC.eol().insets(10, 5, 5, 0));
+		dlg.add(new JLabel(tr("X")), GBC.std().insets(10, 5, 5, 0));
+		dlg.add(this.xField, GBC.eol().insets(10, 5, 5, 0));
+		dlg.add(new JLabel(tr("Y")), GBC.std().insets(10, 5, 5, 0));
+		dlg.add(this.yField, GBC.eol().insets(10, 5, 5, 0));
+
+		gui.tabpane.addTab("Tile Box", dlg);
+	}
+
+	public void boundingBoxChanged(final DownloadDialog gui) {
+		final int zoom = this.getZoom();
+		final double clon = (gui.minlon + gui.maxlon) / 2;
+		final double clat = (gui.minlat + gui.maxlat) / 2;
+
+		final int x = longitudeToTileX(clon, zoom);
+		final int y = latitudeToTileY(clat, zoom);
+
+		this.xField.setText(Integer.toString(x));
+		this.yField.setText(Integer.toString(y));
+	}
+
+	private int getZoom() {
+		try {
+			final int zoom = Integer.parseInt(this.zoomField.getText());
+			if ((zoom >= 10) && (zoom <= 20)) {
+				return zoom;
+			}
+		} catch (final NumberFormatException x) {
+			// ignore
+		}
+		return 12;
+	}
+
+	private static int tileCount(final int zoom) {
+		return (int)Math.pow(2.0d, zoom);
+	}
+
+	private static double tileXSize(final int zoom) {
+		return 360.0d / tileCount(zoom);
+	}
+
+	private static double mercatorProjectionYToLatitude(final double mpy) {
+		return Math.atan(Math.sinh(mpy));
+	}
+	private static double tileYToLatitude(final int y, final int zoom) {
+		double mpy = y * (1.0d / tileCount(zoom)); // Value from 0 to 1
+		mpy = Math.PI * 2 * mpy;                   // Value from 0 to 2pi
+		mpy = Math.PI - mpy;                       // Value from -pi to +pi
+		return Math.toDegrees(mercatorProjectionYToLatitude(mpy));
+	}
+
+	private static double latitudeToMercatorProjectionY(final double radlat) {
+		return Math.log(Math.tan((Math.PI / 4) + (radlat / 2)));
+	}
+	private static int latitudeToTileY(final double lat, final int zoom) {
+		double mpy = latitudeToMercatorProjectionY(Math.toRadians(lat));
+		mpy = mpy / Math.PI;         // Values from +1 to -1
+		mpy = (1.0d - mpy) / 2.0d;   // Values from 0 to 1
+		mpy = mpy * tileCount(zoom); // Scale up to zoom level
+		return (int)Math.floor(mpy); // Round to integer value
+	}
+
+	private static double mercatorProjectionXToLongitude(final double mpx) {
+		return mpx - 180.0d; // Values from -180 to 180
+	}
+	private static double tileXToLongitude(final int x, final int zoom) {
+		return mercatorProjectionXToLongitude(x * tileXSize(zoom));
+	}
+
+	private static double longitudeToMercatorProjectionX(final double lon) {
+		return lon + 180.0d; // Values from 0 to 360
+	}
+	private static int longitudeToTileX(final double lon, final int zoom) {
+		double mpx = longitudeToMercatorProjectionX(lon);
+		mpx = mpx / 360.0d;          // Values from 0 to 1
+		mpx = mpx * tileCount(zoom); // Scale up to zoom level
+		return (int)Math.floor(mpx); // Round to integer value
+	}
+}
+
Index: plugins/tilebox/build.xml
===================================================================
--- plugins/tilebox/build.xml	(revision 0)
+++ plugins/tilebox/build.xml	(revision 0)
@@ -0,0 +1,48 @@
+<project name="tilebox" default="dist" basedir=".">
+  <!-- josm "user home" directory depends on the platform used (windows has a different place than unix/linux) -->
+  <property environment="env"/>
+  <condition property="josm.home.dir" value="${env.APPDATA}/JOSM" else="${user.home}/.josm">
+    <and>
+      <os family="windows"/>
+    </and>
+  </condition>
+
+  <!-- compilation properties -->
+  <property name="josm.build.dir"	value="../../core"/>
+  <property name="josm.plugins.dir"	value="${josm.home.dir}/plugins"/>
+  <property name="josm"			location="../../core/dist/josm-custom.jar" />
+  <property name="plugin.build.dir"	value="build"/>
+  <property name="plugin.dist.dir"	value="../dist"/>
+  <property name="plugin.name"		value="${ant.project.name}"/>
+  <property name="plugin.jar"		value="../dist/${plugin.name}.jar"/>
+
+  <property name="ant.build.javac.target" value="1.5"/>
+
+  <target name="init">
+    <mkdir dir="build"/>
+  </target>
+
+  <target name="compile" depends="init">
+    <javac srcdir="src" classpath="${josm}" destdir="build" debug="true"/>
+  </target>
+
+  <target name="dist" depends="clean, compile">
+    <jar destfile="${plugin.jar}" basedir="build">
+      <manifest>
+	<attribute name="Plugin-Class" value="tilebox.TileBoxPlugin"/>
+	<attribute name="Plugin-Description" value="Tile Box adds a new tab which allows the user to download date from OSM database based on the entered tile coordinates and zoom level."/>
+	<attribute name="Plugin-Version" value="0.1"/>
+	<attribute name="Author" value="Robert Fitzsimons <robfitz at 273k.net>"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="clean">
+    <delete dir="${plugin.build.dir}" />
+    <delete file="${plugin.jar}" />
+  </target>
+
+  <target name="install" depends="dist">
+    <copy file="${plugin.jar}" todir="${josm.plugins.dir}"/>
+  </target>
+</project>




More information about the josm-dev mailing list