Add region info structure

This commit is contained in:
Victor Shcherb 2012-12-08 13:44:39 +01:00
parent efa02a4a8d
commit d080cb056c
16 changed files with 1694 additions and 54 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,104 @@
package net.osmand.map;
import gnu.trove.list.array.TLongArrayList;
import gnu.trove.set.hash.TLongHashSet;
import java.util.ArrayList;
import java.util.List;
import net.osmand.Algoritms;
import net.osmand.map.OsmandRegionInfo.OsmAndRegion;
import net.osmand.osm.MapUtils;
public class RegionCountry {
public String continentName;
public TLongArrayList tiles = new TLongArrayList();
public int left, right, top, bottom;
public String name;
public RegionCountry parent;
private List<RegionCountry> regions = new ArrayList<RegionCountry>();
private final static int SHIFT = 5;
public void add(int xdeg, int ydeg) {
if (tiles.size() == 0) {
left = right = xdeg;
top = bottom = ydeg;
}
left = Math.min(xdeg, left);
right = Math.max(xdeg, right);
bottom = Math.min(ydeg, bottom);
top = Math.max(ydeg, top);
tiles.add((xdeg << SHIFT) + ydeg);
}
public int getLon(int i) {
return (int) (tiles.get(i) >> SHIFT);
}
public int getLat(int i) {
return (int) (tiles.get(i) - ((tiles.get(i) >> SHIFT) << SHIFT));
}
public void addSubregion(RegionCountry c) {
c.parent = this;
regions.add(c);
}
public List<RegionCountry> getSubRegions() {
return regions;
}
public TLongHashSet calculateTileSet(TLongHashSet t, int z) {
for (int j = 0; j < tiles.size(); j++) {
int kx = (int) MapUtils.getTileNumberX(z, getLon(j));
int ex = (int) MapUtils.getTileNumberX(z, getLon(j) + 0.9999f);
int ky = (int) MapUtils.getTileNumberY(z, getLat(j));
int ey = (int) MapUtils.getTileNumberY(z, getLat(j) - 0.9999f);
for (int x = kx; x <= ex; x++) {
for (int y = ky; y <= ey; y++) {
long v = (((long) y) << 31) + x;
t.add(v);
}
}
}
return t;
}
public static RegionCountry construct(OsmAndRegion reg) {
RegionCountry rc = new RegionCountry();
if (reg.hasContinentName()) {
rc.continentName = reg.getContinentName();
}
rc.name = reg.getName();
for (int i = 0; i < reg.getDegXCount(); i++) {
rc.add(reg.getDegX(i), reg.getDegY(i));
}
for (int i = 0; i < reg.getSubregionsCount(); i++) {
rc.addSubregion(construct(reg.getSubregions(i)));
}
return rc;
}
public OsmAndRegion convert() {
OsmAndRegion.Builder reg = OsmAndRegion.newBuilder();
// System.out.println(r.name + " " + r.tiles.size() + " ?= " + r.calculateTileSet(new TLongHashSet(), 8).size());
int px = 0;
int py = 0;
for (int i = 0; i < this.tiles.size(); i++) {
reg.addDegX(this.getLon(i) - px);
reg.addDegY(this.getLat(i) - py);
px = this.getLon(i);
py = this.getLat(i);
}
String n = Algoritms.capitalizeFirstLetterAndLowercase(this.name.replace('_', ' '));
reg.setName(n);
if(this.continentName != null) {
reg.setContinentName(Algoritms.capitalizeFirstLetterAndLowercase(this.continentName));
}
for (RegionCountry c : this.regions) {
reg.addSubregions(c.convert());
}
return reg.build();
}
}

View file

@ -0,0 +1,45 @@
package net.osmand.map;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import net.osmand.LogUtil;
import net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo;
public class RegionRegistry {
public static final String fileName = "countries.reginfo";
private static final Log log = LogUtil.getLog(RegionRegistry.class);
private static RegionRegistry r = null;
private List<RegionCountry> countries = new ArrayList<RegionCountry>();
public static RegionRegistry getRegionRegistry(){
if(r == null) {
try {
long t = -System.currentTimeMillis();
r = new RegionRegistry();
InputStream in = RegionsRegistryConverter.class.getResourceAsStream(RegionRegistry.fileName);
OsmAndRegionInfo regInfo = OsmAndRegionInfo.newBuilder().mergeFrom(in).build();
for(int j = 0; j < regInfo.getRegionInfo().getRegionsCount(); j++) {
r.countries.add(RegionCountry.construct(regInfo.getRegionInfo().getRegions(j)));
}
t += System.currentTimeMillis();
log.info("Initialize regions from file" + t + " ms");
} catch (IOException e) {
log.error("IO exception reading regions", e);
}
}
return r;
}
public List<RegionCountry> getCountries() {
return countries;
}
}

View file

@ -0,0 +1,122 @@
package net.osmand.map;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo;
import net.osmand.map.OsmandRegionInfo.OsmAndRegions;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class RegionsRegistryConverter {
public static List<RegionCountry> parseRegions() throws IllegalStateException {
InputStream is = RegionsRegistryConverter.class.getResourceAsStream("countries.xml");
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
RegionsHandler h = new RegionsHandler(parser);
parser.parse(new InputSource(is), h);
return h.getCountries();
} catch (SAXException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
} catch (ParserConfigurationException e) {
throw new IllegalStateException(e);
}
}
private static class RegionsHandler extends DefaultHandler {
private SAXParser parser;
private String continentName;
private RegionCountry current;
private RegionCountry currentRegion;
private List<RegionCountry> countries = new ArrayList<RegionCountry>();
private StringBuilder txt = new StringBuilder();
public RegionsHandler(SAXParser parser) {
this.parser = parser;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
String tagName = parser.isNamespaceAware() ? localName : qName;
if(tagName.equals("continent")) {
continentName = attributes.getValue("name");
} else if(tagName.equals("country")) {
RegionCountry c = new RegionCountry();
c.continentName = continentName;
c.name = attributes.getValue("name");
current = c;
countries.add(c);
} else if(tagName.equals("tiles")) {
txt.setLength(0);
} else if(tagName.equals("region")) {
RegionCountry c = new RegionCountry();
c.name = attributes.getValue("name");
currentRegion = c;
current.addSubregion(c);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
txt.append(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
String tagName = parser.isNamespaceAware() ? localName : qName;
if(tagName.equals("region")) {
currentRegion = null;
} else if(tagName.equals("tiles")) {
String[] s = txt.toString().split("( |;)");
RegionCountry a = currentRegion == null ? current : currentRegion;
for(int i =0; i < s.length; i+=2) {
a.add(Integer.parseInt(s[i]), Integer.parseInt(s[i+1]));
}
}
}
public List<RegionCountry> getCountries() {
return countries;
}
}
public static void main(String[] args) throws IOException {
List<RegionCountry> countries = parseRegions();
OsmAndRegions.Builder regions= OsmAndRegions.newBuilder();
for(RegionCountry c : countries){
regions.addRegions(c.convert());
}
String filePath = "src/net/osmand/map/"+RegionRegistry.fileName;
long t = -System.currentTimeMillis();
FileOutputStream out = new FileOutputStream(filePath);
OsmAndRegionInfo.newBuilder().setRegionInfo(regions)
.build().writeTo(out);
out.close();
InputStream in = RegionsRegistryConverter.class.getResourceAsStream(RegionRegistry.fileName);
OsmAndRegionInfo regInfo = OsmAndRegionInfo.newBuilder().mergeFrom(in).build();
t += System.currentTimeMillis();
System.out.println("Read countries " + regInfo.getRegionInfo().getRegionsCount() + " " + countries.size() );
System.out.println("Timing " + t);
}
}

Binary file not shown.

View file

@ -42,7 +42,7 @@ public class IndexItem {
this.type = type;
}
public String getVisibleDescription(ClientContext ctx, DownloadActivityType type) {
public String getVisibleDescription(ClientContext ctx) {
String s = ""; //$NON-NLS-1$
if (type == DownloadActivityType.ROADS_FILE) {
return ctx.getString(R.string.download_roads_only_item);
@ -101,6 +101,10 @@ public class IndexItem {
return date;
}
public String getSizeDescription() {
return size + " MB";
}
public String getSize() {
return size;
}
@ -203,6 +207,9 @@ public class IndexItem {
if (getType() == DownloadActivityType.ROADS_FILE) {
s = "-roads" + s;
}
if(l == -1) {
l = e.length();
}
return e.substring(0, l) + s;
}
}

View file

@ -38,37 +38,39 @@ public class IndexItemCategory implements Comparable<IndexItemCategory> {
} else if (lc.contains(".ttsvoice.zip")) {
nameId = R.string.index_name_tts_voice;
order = 2;
} else if (lc.startsWith("us")) {
} else if (lc.startsWith("us") ||
(lc.contains("united states") && lc.startsWith("north-america")) ) {
nameId = R.string.index_name_us;
order = 31;
} else if (lc.contains("_northamerica_")) {
} else if (lc.contains("northamerica") || lc.contains("north-america")) {
nameId = R.string.index_name_north_america;
order = 30;
} else if (lc.contains("_centralamerica_") || lc.contains("central-america")) {
} else if (lc.contains("centralamerica") || lc.contains("central-america")
|| lc.contains("caribbean")) {
nameId = R.string.index_name_central_america;
order = 40;
} else if (lc.contains("_southamerica_") || lc.contains("south-america")) {
} else if (lc.contains("southamerica") || lc.contains("south-america")) {
nameId = R.string.index_name_south_america;
order = 45;
} else if (lc.startsWith("france_")) {
nameId = R.string.index_name_france;
order = 17;
} else if (lc.startsWith("germany_")) {
} else if (lc.startsWith("germany_") || lc.contains("germany")) {
nameId = R.string.index_name_germany;
order = 16;
} else if (lc.contains("_europe_")) {
} else if (lc.contains("_europe_") || lc.startsWith("europe")) {
nameId = R.string.index_name_europe;
order = 15;
} else if (lc.startsWith("russia_")) {
} else if (lc.startsWith("russia")) {
nameId = R.string.index_name_russia;
order = 18;
} else if (lc.contains("africa")) {
nameId = R.string.index_name_africa;
order = 80;
} else if (lc.contains("_asia_")) {
} else if (lc.contains("_asia_")|| lc.startsWith("asia")) {
nameId = R.string.index_name_asia;
order = 50;
} else if (lc.contains("_oceania_") || lc.contains("australia")) {
} else if (lc.contains("oceania") || lc.contains("australia")) {
nameId = R.string.index_name_oceania;
order = 70;
} else if (lc.contains("_wiki_")) {

View file

@ -1,24 +1,28 @@
package net.osmand.plus.download;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import net.osmand.LogUtil;
import net.osmand.map.RegionCountry;
import net.osmand.plus.ClientContext;
import net.osmand.plus.R;
import org.apache.commons.logging.Log;
public class SrtmIndexItem extends IndexItem {
private static final Log log = LogUtil.getLog(SrtmIndexItem.class);
public SrtmIndexItem(String fileName, String description, String date, String size) {
super(fileName, description, date, size, null);
private RegionCountry item;
public SrtmIndexItem(RegionCountry item) {
super(fileName(item), "Elevation lines", "", item.tiles.size()+"", null);
this.item = item;
type = DownloadActivityType.SRTM_FILE;
}
private static String fileName(RegionCountry r) {
if(r.parent == null) {
return r.continentName + " " + r.name;
} else {
return r.parent.continentName + " " + r.parent.name + " " + r.name;
}
}
@Override
public boolean isAccepted() {
return true;
@ -37,24 +41,34 @@ public class SrtmIndexItem extends IndexItem {
entry.baseName = getBasename();
// entry.fileToSave = new File(parent, entry.baseName + toSavePostfix);
// entry.unzip = unzipDir;
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy"); //$NON-NLS-1$
try {
Date d = format.parse(date);
entry.dateModified = d.getTime();
} catch (ParseException e1) {
log.error("ParseException", e1);
}
try {
entry.sizeMB = Double.parseDouble(size);
} catch (NumberFormatException e1) {
log.error("ParseException", e1);
}
entry.parts = 1;
if (parts != null) {
entry.parts = Integer.parseInt(parts);
}
entry.dateModified = System.currentTimeMillis();
entry.parts = Integer.parseInt(size);
// entry.fileToUnzip = new File(parent, entry.baseName + toCheckPostfix);
}
return entry;
}
@Override
public String convertServerFileNameToLocal() {
return fileName+".nonexistent";
}
@Override
public String getBasename() {
return fileName;
}
@Override
public String getSizeDescription() {
return size + " parts";
}
@Override
public String getVisibleName() {
if(item.parent == null) {
return item.name + "\n";
} else {
return item.parent.name +"\n"+item.name;
}
}
}

View file

@ -0,0 +1,24 @@
// Highly coupled with protobuf 2.3.0
option java_package = "net.osmand.map";
//protoc --java_out=DataExtractionOSM/src DataExtractionOSM/src/osmand_region_info.proto
// C++ # cd OsmAnd-Kernel
// # protoc --proto_path=../DataExtractionOSM/src --cpp_out=osmand/src/proto ../DataExtractionOSM/src/osmand_region_info.proto
option optimize_for = LITE_RUNTIME;
message OsmAndRegionInfo {
optional OsmAndRegions regionInfo = 1;
}
message OsmAndRegions {
repeated OsmAndRegion regions = 3;
}
message OsmAndRegion {
optional string continentName = 1;
required string name = 2;
repeated int32 degX = 4 [packed = true];
repeated int32 degY = 5 [packed = true];
repeated OsmAndRegion subregions = 8;
}

View file

@ -9,6 +9,14 @@
1. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
-->
<string name="srtm_plugin_description">SRTM plugin (TODO description)</string>
<string name="srtm_plugin_name">SRTM plugin</string>
<string name="download_select_map_types">Other maps</string>
<string name="download_roads_only_item">Roads </string>
<string name="download_srtm_maps">SRTM maps</string>
<string name="download_regular_maps">Regular maps</string>
<string name="download_roads_only_maps">Roads-only maps</string>
<string name="rendering_attr_noAdminboundaries_name">Hide boundaries</string>
<string name="rendering_attr_noAdminboundaries_description">Suppress display of regional boundaries (admin levels 5-9)</string>
<string name="osmodroid_plugin_old_ver_not_supported">OsMoDroid plugin has an old version and needs to be updated.</string>
@ -30,9 +38,6 @@
<string name="search_villages_and_postcodes">Search villages/postcode</string>
<string name="rendering_attr_showRoadMaps_description">Select when to display roads-only maps:</string>
<string name="rendering_attr_showRoadMaps_name">Roads-only maps</string>
<string name="download_roads_only_item">Roads </string>
<string name="download_regular_maps">Regular maps</string>
<string name="download_roads_only_maps">Roads-only maps</string>
<string name="safe_mode_description">Run the application in safe mode (using slower Android instead of native code).</string>
<string name="safe_mode">Safe mode</string>
<string name="native_library_not_running">The application is running in safe mode (disable it in the Settings).</string>

View file

@ -17,6 +17,7 @@ import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.osmodroid.OsMoDroidPlugin;
import net.osmand.plus.parkingpoint.ParkingPositionPlugin;
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.plus.views.OsmandMapTileView;
import org.apache.commons.logging.Log;
@ -67,6 +68,7 @@ public abstract class OsmandPlugin {
installedPlugins.add(new AccessibilityPlugin(app));
installedPlugins.add(new OsmEditingPlugin(app));
installedPlugins.add(new OsmandDevelopmentPlugin(app));
installedPlugins.add(new SRTMPlugin(app));
installParkingPlugin(app);
installOsmodroidPlugin(app);

View file

@ -27,8 +27,11 @@ import net.osmand.LogUtil;
import net.osmand.Version;
import net.osmand.access.AccessibleToast;
import net.osmand.data.IndexConstants;
import net.osmand.map.RegionCountry;
import net.osmand.map.RegionRegistry;
import net.osmand.plus.ClientContext;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.OsmandPreference;
import net.osmand.plus.ProgressDialogImplementation;
@ -42,6 +45,8 @@ import net.osmand.plus.download.DownloadIndexAdapter;
import net.osmand.plus.download.DownloadIndexListThread;
import net.osmand.plus.download.DownloadTracker;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.download.SrtmIndexItem;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
@ -185,8 +190,7 @@ public class DownloadIndexActivity extends OsmandExpandableListActivity {
menu.add(0, SELECT_ALL_ID, 0, R.string.select_all);
menu.add(0, DESELECT_ALL_ID, 0, R.string.deselect_all);
menu.add(0, FILTER_EXISTING_REGIONS, 0, R.string.filter_existing_indexes);
menu.add(0, DOWNLOAD_FILES_TYPE, 0, getType() == DownloadActivityType.NORMAL_FILE ?
R.string.download_roads_only_maps : R.string.download_regular_maps );
menu.add(0, DOWNLOAD_FILES_TYPE, 0, R.string.download_select_map_types);
}
return true;
}
@ -233,12 +237,7 @@ public class DownloadIndexActivity extends OsmandExpandableListActivity {
}
listAdapter.setIndexFiles(filtered);
} else if (item.getItemId() == DOWNLOAD_FILES_TYPE) {
if(type == DownloadActivityType.ROADS_FILE){
changeType(DownloadActivityType.NORMAL_FILE);
} else {
changeType(DownloadActivityType.ROADS_FILE);
}
selectDownloadType();
} else if(item.getItemId() == DESELECT_ALL_ID){
entriesToDownload.clear();
listAdapter.notifyDataSetInvalidated();
@ -251,6 +250,35 @@ public class DownloadIndexActivity extends OsmandExpandableListActivity {
}
private void selectDownloadType() {
Builder bld = new AlertDialog.Builder(this);
String[] items;
if(OsmandPlugin.getEnabledPlugin(SRTMPlugin.class) != null){
items = new String[]{
getString(R.string.download_regular_maps),
getString(R.string.download_roads_only_maps),
getString(R.string.download_srtm_maps)};
} else {
items = new String[]{
getString(R.string.download_regular_maps),
getString(R.string.download_roads_only_maps)};
}
bld.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 0){
changeType(DownloadActivityType.NORMAL_FILE);
} else if(which == 1){
changeType(DownloadActivityType.ROADS_FILE);
} else if(which == 2){
changeType(DownloadActivityType.SRTM_FILE);
}
}
});
bld.show();
}
public void changeType(final DownloadActivityType tp) {
if (downloadListIndexThread != null) {
type = tp;
@ -266,6 +294,18 @@ public class DownloadIndexActivity extends OsmandExpandableListActivity {
public List<IndexItem> getFilteredByType() {
final List<IndexItem> filtered = new ArrayList<IndexItem>();
if(type == DownloadActivityType.SRTM_FILE){
List<RegionCountry> countries = RegionRegistry.getRegionRegistry().getCountries();
for(RegionCountry rc : countries){
if(rc.tiles.size() > 50){
for(RegionCountry ch : rc.getSubRegions()) {
filtered.add(new SrtmIndexItem(ch));
}
} else {
filtered.add(new SrtmIndexItem(rc));
}
}
}
for (IndexItem file : downloadListIndexThread.getCachedIndexFiles()) {
if (file.getType() == type) {
filtered.add(file);

View file

@ -209,8 +209,10 @@ public class DownloadIndexAdapter extends OsmandBaseExpandableListAdapter implem
TextView item = (TextView) row.findViewById(R.id.download_item);
TextView description = (TextView) row.findViewById(R.id.download_descr);
IndexItem e = (IndexItem) getChild(groupPosition, childPosition);
item.setText((e.getVisibleDescription(downloadActivity.getClientContext(), downloadActivity.getType()) + "\n" + e.getVisibleName()).trim()); //$NON-NLS-1$
description.setText(e.getDate() + "\n" + e.getSize() + " MB");
String eName = e.getVisibleDescription(downloadActivity.getClientContext()) + "\n" + e.getVisibleName();
item.setText(eName.trim()); //$NON-NLS-1$
String d = e.getDate() + "\n" + e.getSizeDescription();
description.setText(d.trim());
CheckBox ch = (CheckBox) row.findViewById(R.id.check_download_item);
ch.setChecked(downloadActivity.getEntriesToDownload().containsKey(e.getFileName()));

View file

@ -4,8 +4,11 @@ package net.osmand.plus.download;
import java.util.List;
import net.osmand.access.AccessibleToast;
import net.osmand.map.RegionRegistry;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.DownloadIndexActivity;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import android.content.Context;
import android.view.View;
import android.widget.Toast;
@ -36,6 +39,10 @@ public class DownloadIndexListThread extends Thread {
@Override
public void run() {
indexFiles = DownloadOsmandIndexesHelper.getIndexesList(ctx);
if(OsmandPlugin.getEnabledPlugin(SRTMPlugin.class) != null){
// init
RegionRegistry.getRegionRegistry();
}
if (uiActivity != null) {
uiActivity.removeDialog(DownloadIndexActivity.DIALOG_PROGRESS_LIST);
uiActivity.runOnUiThread(new Runnable() {

View file

@ -0,0 +1,51 @@
package net.osmand.plus.srtmplugin;
import net.osmand.LogUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import org.apache.commons.logging.Log;
public class SRTMPlugin extends OsmandPlugin {
public static final String ID = "osmand.srtm";
private static final Log log = LogUtil.getLog(SRTMPlugin.class);
private OsmandApplication app;
@Override
public String getId() {
return ID;
}
public SRTMPlugin(OsmandApplication app) {
this.app = app;
}
@Override
public String getDescription() {
return app.getString(R.string.srtm_plugin_description);
}
@Override
public String getName() {
return app.getString(R.string.srtm_plugin_name);
}
@Override
public boolean init(final OsmandApplication app) {
return true;
}
@Override
public void registerLayers(MapActivity activity) {
}
@Override
public void disable(OsmandApplication app) {
}
}