From 85d16a6bf990f282f3eea80443dcf3fb1455a989 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Wed, 2 Jun 2010 07:25:06 +0000 Subject: [PATCH] implement search intersected street git-svn-id: https://osmand.googlecode.com/svn/trunk@114 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8 --- .../src/com/osmand/ToDoConstants.java | 4 +- .../src/com/osmand/data/MapObject.java | 3 + .../com/osmand/data/index/IndexConstants.java | 2 +- .../data/preparation/DataExtraction.java | 2 +- .../src/com/osmand/osm/OSMSettings.java | 1 + DataExtractionOSM/src/com/osmand/osm/Way.java | 11 +++ OsmAnd/AndroidManifest.xml | 1 + OsmAnd/res/layout/search_address.xml | 4 +- OsmAnd/res/values/strings.xml | 5 +- OsmAnd/src/com/osmand/OsmandSettings.java | 5 + .../com/osmand/RegionAddressRepository.java | 57 ++++++++++++ .../osmand/activities/MainMenuActivity.java | 1 - .../search/SearchAddressActivity.java | 91 +++++++++++++++++-- .../search/SearchStreet2ByNameActivity.java | 91 +++++++++++++++++++ 14 files changed, 260 insertions(+), 18 deletions(-) create mode 100644 OsmAnd/src/com/osmand/activities/search/SearchStreet2ByNameActivity.java diff --git a/DataExtractionOSM/src/com/osmand/ToDoConstants.java b/DataExtractionOSM/src/com/osmand/ToDoConstants.java index e491e82da5..a23e573658 100644 --- a/DataExtractionOSM/src/com/osmand/ToDoConstants.java +++ b/DataExtractionOSM/src/com/osmand/ToDoConstants.java @@ -17,11 +17,9 @@ public class ToDoConstants { // 29. Show opened/closed amenities (in search poi). // 13. Save point as favorite & introduce favorite points dialog - // 3. Revise osmand UI. Preparing new icons (revise UI 18, 2, ). Main application icon, back to location icon. // 14. Show zoom level on map -// 27. Search intersection of streets (+) // NOT in release 0.1 // 8. Enable change POI directly on map (requires OSM login) @@ -32,6 +30,7 @@ public class ToDoConstants { // FIXME Bugs Android : + // Investigate good transliterate // 6. Understand concept of application where to save/restore global setting. // (for example reset navigate to point, reset link map with location). It should be reset after user call exit. // Call ResourceManager.close when it is needed. @@ -52,6 +51,7 @@ public class ToDoConstants { // DONE ANDROID : +// 27. Search intersection of streets // 24. Implement ResourceManager, load cities/streets/buildings on Low memory (clear previous all addresses cities). // 28. Implement transliteration search for android version // 5. Search for city/streets/buildings diff --git a/DataExtractionOSM/src/com/osmand/data/MapObject.java b/DataExtractionOSM/src/com/osmand/data/MapObject.java index 437b6d7fc6..52084a9c87 100644 --- a/DataExtractionOSM/src/com/osmand/data/MapObject.java +++ b/DataExtractionOSM/src/com/osmand/data/MapObject.java @@ -26,6 +26,9 @@ public abstract class MapObject implements Comparable { if(this.name == null){ this.name = e.getTag(OSMTagKey.NAME); } + if(this.enName == null){ + this.enName = e.getTag(OSMTagKey.NAME_EN); + } if(this.location == null){ this.location = MapUtils.getCenter(e); } diff --git a/DataExtractionOSM/src/com/osmand/data/index/IndexConstants.java b/DataExtractionOSM/src/com/osmand/data/index/IndexConstants.java index c928c92a28..07a32310a0 100644 --- a/DataExtractionOSM/src/com/osmand/data/index/IndexConstants.java +++ b/DataExtractionOSM/src/com/osmand/data/index/IndexConstants.java @@ -207,7 +207,7 @@ public class IndexConstants { } public enum IndexStreetNodeTable implements IndexColumn { - ID("long"), LATITUDE("double"), LONGITUDE("double"), STREET("long", true), WAY("long", true); + ID("long", true), LATITUDE("double"), LONGITUDE("double"), STREET("long", true), WAY("long", true); boolean index = false; String type = null; diff --git a/DataExtractionOSM/src/com/osmand/data/preparation/DataExtraction.java b/DataExtractionOSM/src/com/osmand/data/preparation/DataExtraction.java index 0b2bee1920..1ff8d45e5d 100644 --- a/DataExtractionOSM/src/com/osmand/data/preparation/DataExtraction.java +++ b/DataExtractionOSM/src/com/osmand/data/preparation/DataExtraction.java @@ -329,7 +329,7 @@ public class DataExtraction { private void convertEnglishName(MapObject o, Transliterator transliterator){ String name = o.getName(); - if(name != null){ + if(name != null && o.getEnName() == null){ o.setEnName(transliterator.transliterate(name)); } } diff --git a/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java b/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java index ee8ca1862f..8c3cbc7c45 100644 --- a/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java +++ b/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java @@ -4,6 +4,7 @@ public class OSMSettings { public enum OSMTagKey { NAME("name"), + NAME_EN("name:en"), // ways HIGHWAY("highway"), BUILDING("building"), diff --git a/DataExtractionOSM/src/com/osmand/osm/Way.java b/DataExtractionOSM/src/com/osmand/osm/Way.java index 352210aa5a..181040db97 100644 --- a/DataExtractionOSM/src/com/osmand/osm/Way.java +++ b/DataExtractionOSM/src/com/osmand/osm/Way.java @@ -22,6 +22,17 @@ public class Way extends Entity { nodeIds.add(id); } + public void addNode(Node n){ + if(nodeIds == null){ + nodeIds = new ArrayList(); + } + if(nodes == null){ + nodes = new ArrayList(); + } + nodeIds.add(n.getId()); + nodes.add(n); + } + public Long removeNodeByIndex(int i){ if(nodeIds == null){ return null; diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index 6e2e4f8e83..de1f974057 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -21,6 +21,7 @@ + diff --git a/OsmAnd/res/layout/search_address.xml b/OsmAnd/res/layout/search_address.xml index 00d2396ef1..734a1b388e 100644 --- a/OsmAnd/res/layout/search_address.xml +++ b/OsmAnd/res/layout/search_address.xml @@ -35,7 +35,7 @@ - + @@ -43,7 +43,7 @@ - + diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index ce51777e3b..ae5afe838f 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -38,13 +38,14 @@ Settings Search #CFFACD -search +Search #FFFFFF #FF0000 -searchpoi_activity +Choose poi Find more Search city incrementally. In order to find villages input more than 3 first symbols. Search street incrementally Search building incrementally Choose region +Choose intersected street diff --git a/OsmAnd/src/com/osmand/OsmandSettings.java b/OsmAnd/src/com/osmand/OsmandSettings.java index 6a7f3a9678..6495700315 100644 --- a/OsmAnd/src/com/osmand/OsmandSettings.java +++ b/OsmAnd/src/com/osmand/OsmandSettings.java @@ -191,6 +191,11 @@ public class OsmandSettings { SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); return prefs.edit().putString(LAST_SEARCHED_INTERSECTED_STREET, street).commit(); } + + public static boolean removeLastSearchedIntersectedStreet(Context ctx){ + SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); + return prefs.edit().remove(LAST_SEARCHED_INTERSECTED_STREET).commit(); + } } diff --git a/OsmAnd/src/com/osmand/RegionAddressRepository.java b/OsmAnd/src/com/osmand/RegionAddressRepository.java index b33b66c85f..003e6ae6da 100644 --- a/OsmAnd/src/com/osmand/RegionAddressRepository.java +++ b/OsmAnd/src/com/osmand/RegionAddressRepository.java @@ -9,6 +9,8 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; import org.apache.commons.logging.Log; @@ -23,7 +25,10 @@ import com.osmand.data.City.CityType; import com.osmand.data.index.IndexConstants; import com.osmand.data.index.IndexConstants.IndexBuildingTable; import com.osmand.data.index.IndexConstants.IndexCityTable; +import com.osmand.data.index.IndexConstants.IndexStreetNodeTable; import com.osmand.data.index.IndexConstants.IndexStreetTable; +import com.osmand.osm.Node; +import com.osmand.osm.Way; public class RegionAddressRepository { @@ -143,6 +148,31 @@ public class RegionAddressRepository { } } + public void fillWithSuggestedStreetsIntersectStreets(City city, Street st, List streetsToFill) { + if (st != null) { + Set strIds = new TreeSet(); + log.debug("Start loading instersection streets for " + city.getName()); + Cursor query = db.rawQuery("SELECT B.STREET FROM street_node A JOIN street_node B ON A.ID = B.ID WHERE A.STREET = ?", + new String[] { st.getId() + "" }); + if (query.moveToFirst()) { + do { + if (st.getId() != query.getLong(0)) { + strIds.add(query.getLong(0)); + } + } while (query.moveToNext()); + } + query.close(); + for (Street s : city.getStreets()) { + if (strIds.contains(s.getId())) { + streetsToFill.add(s); + } + } + log.debug("Loaded " + strIds.size() + " streets"); + preloadWayNodes(st); + } + } + + public void fillWithSuggestedStreets(City c, String name, List streetsToFill){ preloadStreets(c); name = name.toLowerCase(); @@ -220,6 +250,33 @@ public class RegionAddressRepository { } } + public void preloadWayNodes(Street street){ + if(street.getWayNodes().isEmpty()){ + Cursor query = db.query(IndexStreetNodeTable.getTable(), IndexConstants.generateColumnNames(IndexStreetNodeTable.values()), "? = street", + new String[] { street.getId() + "" }, null, null, null); + log.debug("Start loading waynodes for " + street.getName()); + Map ways = new LinkedHashMap(); + if (query.moveToFirst()) { + do { + Node n = new Node(query.getDouble(IndexStreetNodeTable.LATITUDE.ordinal()), + query.getDouble(IndexBuildingTable.LONGITUDE.ordinal()), + query.getLong(IndexStreetNodeTable.ID.ordinal())); + long way = query.getLong(IndexStreetNodeTable.WAY.ordinal()); + if(!ways.containsKey(way)){ + ways.put(way, new Way(way)); + } + ways.get(way).addNode(n); + } while (query.moveToNext()); + } + query.close(); + for(Way w : ways.values()){ + street.getWayNodes().add(w); + } + log.debug("Loaded " + ways.size() + " ways"); + } + + } + public void preloadBuildings(Street street){ if (street.getBuildings().isEmpty()) { Cursor query = db.query(IndexBuildingTable.getTable(), IndexConstants.generateColumnNames(IndexBuildingTable.values()), "? = street", diff --git a/OsmAnd/src/com/osmand/activities/MainMenuActivity.java b/OsmAnd/src/com/osmand/activities/MainMenuActivity.java index 38beb84eea..2ffa0dbe9c 100644 --- a/OsmAnd/src/com/osmand/activities/MainMenuActivity.java +++ b/OsmAnd/src/com/osmand/activities/MainMenuActivity.java @@ -139,7 +139,6 @@ public class MainMenuActivity extends Activity { public void onClick(View v) { mNotificationManager.cancel(APP_NOTIFICATION_ID); MainMenuActivity.this.finish(); - System.exit(0); } }); diff --git a/OsmAnd/src/com/osmand/activities/search/SearchAddressActivity.java b/OsmAnd/src/com/osmand/activities/search/SearchAddressActivity.java index c19bef5dc1..61317702f0 100644 --- a/OsmAnd/src/com/osmand/activities/search/SearchAddressActivity.java +++ b/OsmAnd/src/com/osmand/activities/search/SearchAddressActivity.java @@ -8,6 +8,9 @@ import android.os.Bundle; import android.view.View; import android.view.Window; import android.widget.Button; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; import com.osmand.OsmandSettings; import com.osmand.R; @@ -18,6 +21,8 @@ import com.osmand.data.Building; import com.osmand.data.City; import com.osmand.data.Street; import com.osmand.osm.LatLon; +import com.osmand.osm.Node; +import com.osmand.osm.Way; public class SearchAddressActivity extends Activity { @@ -31,6 +36,8 @@ public class SearchAddressActivity extends Activity { private City city = null; private Street street = null; private Building building = null; + private Street street2 = null; + private boolean radioBuilding = true; @Override protected void onCreate(Bundle savedInstanceState) { @@ -68,7 +75,13 @@ public class SearchAddressActivity extends Activity { buildingButton.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { - startActivity(new Intent(SearchAddressActivity.this, SearchBuildingByNameActivity.class)); + if(radioBuilding){ + OsmandSettings.removeLastSearchedIntersectedStreet(SearchAddressActivity.this); + startActivity(new Intent(SearchAddressActivity.this, SearchBuildingByNameActivity.class)); + } else { + OsmandSettings.setLastSearchedIntersectedStreet(SearchAddressActivity.this, ""); + startActivity(new Intent(SearchAddressActivity.this, SearchStreet2ByNameActivity.class)); + } } }); showOnMap.setOnClickListener(new View.OnClickListener() { @@ -76,7 +89,27 @@ public class SearchAddressActivity extends Activity { public void onClick(View v) { LatLon l = null; int zoom = 12; - if (building != null) { + if (street2 != null && street != null) { + region.preloadWayNodes(street2); + region.preloadWayNodes(street); + Node inters = null; + for(Way w : street2.getWayNodes()){ + for(Way w2 : street.getWayNodes()){ + for(Node n : w.getNodes()){ + for(Node n2 : w2.getNodes()){ + if(n.getId() == n2.getId()){ + inters = n; + break; + } + } + } + } + } + if(inters != null){ + l = inters.getLatLon(); + zoom = 16; + } + } else if (building != null) { l = building.getLocation(); zoom = 16; } else if (street != null) { @@ -128,7 +161,39 @@ public class SearchAddressActivity extends Activity { updateUI(); } }); - + ((RadioGroup)findViewById(R.id.RadioGroup)).setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){ + + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + SearchAddressActivity.this.radioBuilding = checkedId == R.id.RadioBuilding; + if(radioBuilding){ + SearchAddressActivity.this.street2 = null; + } else { + SearchAddressActivity.this.building = null; + } + updateBuildingSection(); + } + + }); + } + + protected void updateBuildingSection(){ + if(radioBuilding){ + ((TextView)findViewById(R.id.BuildingText)).setText("Building"); + if(building == null){ + ((TextView)findViewById(R.id.BuildingButton)).setText(R.string.choose_building); + } else { + ((TextView)findViewById(R.id.BuildingButton)).setText(building.getName(region.useEnglishNames())); + } + } else { + ((TextView)findViewById(R.id.BuildingText)).setText("Street 2"); + if(street2 == null){ + ((TextView)findViewById(R.id.BuildingButton)).setText(R.string.choose_intersected_street); + } else { + ((TextView)findViewById(R.id.BuildingButton)).setText(street2.getName(region.useEnglishNames())); + } + } + findViewById(R.id.ResetBuilding).setEnabled(building != null || street2 != null); } protected void updateUI(){ @@ -154,13 +219,15 @@ public class SearchAddressActivity extends Activity { } streetButton.setEnabled(city != null); - findViewById(R.id.ResetBuilding).setEnabled(building != null); - if(building == null){ - buildingButton.setText(R.string.choose_building); + if(radioBuilding){ + ((RadioButton)findViewById(R.id.RadioBuilding)).setChecked(true); } else { - buildingButton.setText(building.getName(region.useEnglishNames())); + ((RadioButton)findViewById(R.id.RadioIntersStreet)).setChecked(true); } + updateBuildingSection(); + buildingButton.setEnabled(street != null); + showOnMap.setEnabled(building != null || city != null || street != null); } @@ -173,8 +240,14 @@ public class SearchAddressActivity extends Activity { if (city != null) { street = region.getStreetByName(city, OsmandSettings.getLastSearchedStreet(SearchAddressActivity.this)); if (street != null) { - building = region.getBuildingByName(street, OsmandSettings - .getLastSearchedBuilding(SearchAddressActivity.this)); + String str = OsmandSettings.getLastSearchedIntersectedStreet(SearchAddressActivity.this); + radioBuilding = str == null; + if(str != null){ + street2 = region.getStreetByName(city, str); + } else { + building = region.getBuildingByName(street, OsmandSettings + .getLastSearchedBuilding(SearchAddressActivity.this)); + } } } } diff --git a/OsmAnd/src/com/osmand/activities/search/SearchStreet2ByNameActivity.java b/OsmAnd/src/com/osmand/activities/search/SearchStreet2ByNameActivity.java new file mode 100644 index 0000000000..b11a04d0a2 --- /dev/null +++ b/OsmAnd/src/com/osmand/activities/search/SearchStreet2ByNameActivity.java @@ -0,0 +1,91 @@ +package com.osmand.activities.search; + +import java.util.ArrayList; +import java.util.List; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.widget.TextView; + +import com.osmand.OsmandSettings; +import com.osmand.R; +import com.osmand.RegionAddressRepository; +import com.osmand.ResourceManager; +import com.osmand.data.City; +import com.osmand.data.Street; + +public class SearchStreet2ByNameActivity extends SearchByNameAbstractActivity { + private RegionAddressRepository region; + private City city; + private Street street1; + volatile private List initialList = new ArrayList(); + private List filterList = new ArrayList(); + @Override + protected void onCreate(Bundle savedInstanceState) { + region = ResourceManager.getResourceManager().getRegionRepository(OsmandSettings.getLastSearchedRegion(this)); + if(region != null){ + city = region.getCityById(OsmandSettings.getLastSearchedCity(this)); + if(city != null){ + street1 = region.getStreetByName(city, (OsmandSettings.getLastSearchedStreet(this))); + startLoadDataInThread("Finding streets..."); + } + } + + super.onCreate(savedInstanceState); + ((TextView)findViewById(R.id.Label)).setText(R.string.incremental_search_street); + } + + + protected void startLoadDataInThread(String progressMsg){ + final ProgressDialog dlg = ProgressDialog.show(this, "Loading", progressMsg, true); + new Thread("Loader search data") { + @Override + public void run() { + try { + List t = new ArrayList(); + region.fillWithSuggestedStreetsIntersectStreets(city, street1, t); + initialList = t; + } finally { + dlg.dismiss(); + runOnUiThread(new Runnable() { + @Override + public void run() { + setText(getFilter().toString()); + } + }); + } + } + }.start(); + } + @Override + public List getObjects(String filter) { + int ind = 0; + filter = filter.toLowerCase(); + if(filter.length() == 0){ + return initialList; + } + filterList.clear(); + for (Street s : initialList) { + String lowerCase = s.getName(region.useEnglishNames()).toLowerCase(); + if (lowerCase.startsWith(filter)) { + filterList.add(ind, s); + ind++; + } else if (lowerCase.contains(filter)) { + filterList.add(s); + } + } + return filterList; + } + + @Override + public void updateTextView(Street obj, TextView txt) { + txt.setText(obj.getName(region.useEnglishNames())); + } + + @Override + public void itemSelected(Street obj) { + OsmandSettings.setLastSearchedIntersectedStreet(this, obj.getName(region.useEnglishNames())); + finish(); + + } +}