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; |