diff options
| -rw-r--r-- | altosdroid/res/layout/map_preload.xml | 8 | ||||
| -rw-r--r-- | altosdroid/res/values/strings.xml | 2 | ||||
| -rw-r--r-- | altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java | 66 | ||||
| -rw-r--r-- | altoslib/AltosMapLoader.java | 99 | ||||
| -rw-r--r-- | altoslib/AltosMapLoaderListener.java | 2 | ||||
| -rw-r--r-- | altosuilib/AltosUIMapPreloadNew.java | 35 | 
6 files changed, 179 insertions, 33 deletions
| diff --git a/altosdroid/res/layout/map_preload.xml b/altosdroid/res/layout/map_preload.xml index 1d1fca32..dc613bf2 100644 --- a/altosdroid/res/layout/map_preload.xml +++ b/altosdroid/res/layout/map_preload.xml @@ -103,15 +103,15 @@  	       android:prompt="@string/preload_max_zoom"  	       android:spinnerMode="dropdown"  	       /> -      <TextView android:id="@+id/preload_tile_radius_label" +      <TextView android:id="@+id/preload_radius_label"  		android:layout_width="fill_parent"  		android:layout_height="wrap_content" -		android:text="@string/preload_tile_radius" +		android:text="@string/preload_radius"  		/> -      <Spinner android:id="@+id/preload_tile_radius" +      <Spinner android:id="@+id/preload_radius"  	       android:layout_width="fill_parent"  	       android:layout_height="wrap_content" -	       android:prompt="@string/preload_tile_radius" +	       android:prompt="@string/preload_radius"  	       android:spinnerMode="dropdown"  	       />        <Button android:id="@+id/preload_load" diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 8c299a35..36b07bc2 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -106,7 +106,7 @@  	<string name="preload_terrain">Terrain</string>  	<string name="preload_min_zoom">Minimum Zoom</string>  	<string name="preload_max_zoom">Maximum Zoom</string> -	<string name="preload_tile_radius">Tile Radius</string> +	<string name="preload_radius">Radius</string>  	<string name="preload_load">Load Map</string>  </resources> diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java index 1968edae..498b208e 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java @@ -61,7 +61,8 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe  	private Spinner		known_sites_spinner;  	private Spinner		min_zoom;  	private Spinner		max_zoom; -	private Spinner		tile_radius; +	private TextView	radius_label; +	private Spinner		radius;  	private EditText	latitude;  	private EditText	longitude; @@ -227,8 +228,17 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe  		return value(max_zoom);  	} -	private int radius() { -		return value(tile_radius); +	private double value_distance(Spinner spinner) { +		return (Double) spinner.getSelectedItem(); +	} + +	private double radius() { +		double r = value_distance(radius); +		if (AltosPreferences.imperial_units()) +			r = AltosConvert.distance.inverse(r); +		else +			r = r * 1000; +		return r;  	}  	private int bit(CheckBox box, int value) { @@ -250,11 +260,14 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe  			double	lon = longitude();  			int	min = min_z();  			int	max = max_z(); -			int	r = radius(); +			double	r = radius();  			int	t = types(); +			AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n", +					 lat, lon, min, max, r, t);  			loader.load(lat, lon, min, max, r, t);  		} catch (ParseException e) { +			AltosDebug.debug("PreloadMap load raised exception %s", e.toString());  		}  	} @@ -276,6 +289,37 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe  		spinner.setSelection(spinner_def);  	} + +	private void add_distance(Spinner spinner, double[] distances_km, double def_km, double[] distances_mi, double def_mi) { + +		ArrayAdapter<Double> adapter = new ArrayAdapter<Double>(this, android.R.layout.simple_spinner_item); + +		int	spinner_def = 0; +		int	pos = 0; + +		double[] distances; +		double	def; +		if (AltosPreferences.imperial_units()) { +			distances = distances_mi; +			def = def_mi; +		} else { +			distances = distances_km; +			def = def_km; +		} + +		for (int i = 0; i < distances.length; i++) { +			adapter.add(distances[i]); +			if (distances[i] == def) +				spinner_def = pos; +			pos++; +		} + +		spinner.setAdapter(adapter); +		spinner.setSelection(spinner_def); +	} + + +  	class SiteListListener implements OnItemSelectedListener {  		public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {  			AltosLaunchSite	site = (AltosLaunchSite) parent.getItemAtPosition(pos); @@ -289,6 +333,11 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe  		}  	} +	double[]	radius_mi = { 1, 2, 5, 10, 20 }; +	double		radius_def_mi = 2; +	double[]	radius_km = { 1, 2, 5, 10, 20, 30 }; +	double		radius_def_km = 2; +  	@Override  	protected void onCreate(Bundle savedInstanceState) {  		super.onCreate(savedInstanceState); @@ -326,8 +375,13 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe  		add_numbers(max_zoom,  			    AltosMap.min_zoom - AltosMap.default_zoom,  			    AltosMap.max_zoom - AltosMap.default_zoom, 2); -		tile_radius = (Spinner) findViewById(R.id.preload_tile_radius); -		add_numbers(tile_radius, 1, 5, 5); +		radius_label = (TextView) findViewById(R.id.preload_radius_label); +		radius = (Spinner) findViewById(R.id.preload_radius); +		if (AltosPreferences.imperial_units()) +			radius_label.setText("Radius (miles)"); +		else +			radius_label.setText("Radius (km)"); +		add_distance(radius, radius_km, radius_def_km, radius_mi, radius_def_mi);  		progress = (ProgressBar) findViewById(R.id.preload_progress); diff --git a/altoslib/AltosMapLoader.java b/altoslib/AltosMapLoader.java index cf7169ba..2cd5dbd3 100644 --- a/altoslib/AltosMapLoader.java +++ b/altoslib/AltosMapLoader.java @@ -24,7 +24,7 @@ import java.lang.Math;  import java.net.URL;  import java.net.URLConnection; -public class AltosMapLoader implements AltosMapTileListener { +public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListener {  	AltosMapLoaderListener	listener;  	double	latitude, longitude; @@ -33,17 +33,71 @@ public class AltosMapLoader implements AltosMapTileListener {  	int	cur_z;  	int	all_types;  	int	cur_type; -	int	radius; +	double	radius; -	int	tiles_per_layer; -	int	tiles_loaded; +	int	tiles_loaded_layer; +	int	tiles_loaded_total; +	int	tiles_this_layer; +	int	tiles_total;  	int	layers_total;  	int	layers_loaded;  	AltosMap	map; +	int tile_radius(int zoom) { +		double	delta_lon = AltosMapTransform.lon_from_distance(latitude, radius); + +		AltosMapTransform t = new AltosMapTransform(256, 256, zoom + AltosMap.default_zoom, new AltosLatLon(latitude, longitude)); + +		AltosPointDouble	center = t.point(new AltosLatLon(latitude, longitude)); +		AltosPointDouble	edge = t.point(new AltosLatLon(latitude, longitude + delta_lon)); + +		int tile_radius = (int) Math.ceil(Math.abs(center.x - edge.x) / AltosMap.px_size); + +		return tile_radius; +	} + +	int tiles_per_layer(int zoom) { +		int	tile_radius = tile_radius(zoom); +		return (tile_radius * 2 + 1) * (tile_radius * 2 + 1); +	} +  	public void do_load() { -		map.set_load_params(cur_z + AltosMap.default_zoom, cur_type, latitude, longitude, radius, this); +		tiles_this_layer = tiles_per_layer(cur_z); +		tiles_loaded_layer = 0; +		listener.debug("tiles_this_layer %d (zoom %d)\n", tiles_this_layer, cur_z); + +		int load_radius = tile_radius(cur_z); +		int zoom = cur_z + AltosMap.default_zoom; +		int maptype = cur_type; +		AltosLatLon load_centre = new AltosLatLon(latitude, longitude); +		AltosMapTransform transform = new AltosMapTransform(256, 256, zoom, load_centre); + +		map.centre(load_centre); + +		AltosPointInt	upper_left; +		AltosPointInt	lower_right; + +		AltosPointInt centre = AltosMap.floor(transform.point(load_centre)); + +		upper_left = new AltosPointInt(centre.x - load_radius * AltosMap.px_size, +					       centre.y - load_radius * AltosMap.px_size); +		lower_right = new AltosPointInt(centre.x + load_radius * AltosMap.px_size, +						centre.y + load_radius * AltosMap.px_size); + + +		for (int y = (int) upper_left.y; y <= lower_right.y; y += AltosMap.px_size) { +			for (int x = (int) upper_left.x; x <= lower_right.x; x += AltosMap.px_size) { +				listener.debug("Make tile at %d, %d\n", x, y); +				AltosPointInt	point = new AltosPointInt(x, y); +				AltosLatLon	ul = transform.lat_lon(point); +				AltosLatLon	center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2)); +				AltosMapTile	tile = map.map_interface.new_tile(this, ul, center, zoom, maptype, AltosMap.px_size); +				tile.add_store_listener(this); +				if (tile.store_status() != AltosMapTile.loading) +					notify_tile(tile, tile.store_status()); +			} +		}  	}  	public int next_type(int start) { @@ -84,16 +138,23 @@ public class AltosMapLoader implements AltosMapTileListener {  		}  		cur_type = next_type(0); -		tiles_per_layer = (radius * 2 + 1) * (radius * 2 + 1); + +		for (int z = min_z; z <= max_z; z++) +			tiles_total += tiles_per_layer(z); +  		layers_total = (max_z - min_z + 1) * ntype;  		layers_loaded = 0; -		tiles_loaded = 0; +		tiles_loaded_total = 0; + +		listener.debug("total tiles %d\n", tiles_total); -		listener.loader_start(layers_total * tiles_per_layer); +		listener.loader_start(tiles_total);  		do_load();  	} -	public void load(double latitude, double longitude, int min_z, int max_z, int radius, int all_types) { +	public void load(double latitude, double longitude, int min_z, int max_z, double radius, int all_types) { +		listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n", +			       latitude, longitude, min_z, max_z, radius, all_types);  		this.latitude = latitude;  		this.longitude = longitude;  		this.min_z = min_z; @@ -103,7 +164,7 @@ public class AltosMapLoader implements AltosMapTileListener {  		start_load();  	} -	public synchronized void notify_tile(AltosMapTile tile, int status) { +	public synchronized void notify_store(AltosMapStore store, int status) {  		boolean	do_next = false;  		if (status == AltosMapTile.loading)  			return; @@ -111,24 +172,30 @@ public class AltosMapLoader implements AltosMapTileListener {  		if (layers_loaded >= layers_total)  			return; -		++tiles_loaded; +		++tiles_loaded_total; +		++tiles_loaded_layer; +		listener.debug("total %d layer %d\n", tiles_loaded_total, tiles_loaded_layer); -		if (tiles_loaded == tiles_per_layer) { -			tiles_loaded = 0; +		if (tiles_loaded_layer == tiles_this_layer) {  			++layers_loaded; +			listener.debug("%d layers loaded\n", layers_loaded);  			if (layers_loaded == layers_total) { -				listener.loader_done(layers_total * tiles_per_layer); +				listener.loader_done(tiles_total);  				return;  			} else {  				do_next = true;  			}  		} -		listener.loader_notify(layers_loaded * tiles_per_layer + tiles_loaded, -				       layers_total * tiles_per_layer, tile.store.file.toString()); +		listener.loader_notify(tiles_loaded_total, +				       tiles_total, store.file.toString());  		if (do_next)  			next_load();  	} +	public synchronized void notify_tile(AltosMapTile tile, int status) { +		notify_store(tile.store, status); +	} +  	public AltosMapCache cache() { return map.cache(); }  	public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener) { diff --git a/altoslib/AltosMapLoaderListener.java b/altoslib/AltosMapLoaderListener.java index 79f8b9df..11f59b28 100644 --- a/altoslib/AltosMapLoaderListener.java +++ b/altoslib/AltosMapLoaderListener.java @@ -23,4 +23,6 @@ public interface AltosMapLoaderListener {  	public abstract void loader_notify(int cur, int max, String name);  	public abstract void loader_done(int max); + +	public abstract void debug(String format, Object ... arguments);  } diff --git a/altosuilib/AltosUIMapPreloadNew.java b/altosuilib/AltosUIMapPreloadNew.java index 4a5764c8..ba559534 100644 --- a/altosuilib/AltosUIMapPreloadNew.java +++ b/altosuilib/AltosUIMapPreloadNew.java @@ -140,10 +140,15 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener  	JComboBox<Integer>	min_zoom;  	JComboBox<Integer>	max_zoom; -	JComboBox<Integer>	radius; +	JComboBox<Double>	radius;  	Integer[]		zooms = { -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 }; -	Integer[]		radii = { 1, 2, 3, 4, 5 }; + +	Double[]	radius_mi = { 1.0, 2.0, 5.0, 10.0, 20.0 }; +	Double		radius_def_mi = 5.0; +	Double[]	radius_km = { 2.0, 5.0, 10.0, 20.0, 30.0 }; +	Double		radius_def_km = 10.0; +  	static final String[]	lat_hemi_names = { "N", "S" };  	static final String[]	lon_hemi_names = { "E", "W" }; @@ -183,6 +188,11 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener  			});  	} +	public void debug(String format, Object ... arguments) { +		System.out.printf(format, arguments); +	} + +  	private int all_types() {  		int all_types = 0;  		for (int t = AltosMap.maptype_hybrid; t <= AltosMap.maptype_terrain; t++) @@ -219,7 +229,12 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener  					int max_z = (Integer) max_zoom.getSelectedItem();  					if (max_z < min_z)  						max_z = min_z; -					int r = (Integer) radius.getSelectedItem(); +					Double r = (Double) radius.getSelectedItem(); + +					if (AltosPreferences.imperial_units()) +						r = AltosConvert.distance.inverse(r); +					else +						r = r * 1000;  					loading = true;  					loader.load(latitude, longitude, min_z, max_z, r, all_types()); @@ -430,13 +445,21 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener  		c.gridy = 3;  		pane.add(max_zoom, c); -		JLabel radius_label = new JLabel("Tile Radius"); +		JLabel radius_label = new JLabel(String.format("Map Radius (%s)", +							       AltosPreferences.imperial_units() ? "miles" : "km"));  		c.gridx = 4;  		c.gridy = 4;  		pane.add(radius_label, c); -		radius = new JComboBox<Integer>(radii); -		radius.setSelectedItem(radii[4]); +		Double[]	radii; +		Double		radius_default; + +		if (AltosPreferences.imperial_units()) +			radii = radius_mi; +		else +			radii = radius_km; +		radius = new JComboBox<Double>(radii); +		radius.setSelectedItem(radii[2]);  		radius.setEditable(true);  		c.gridx = 5;  		c.gridy = 4; | 
