implement index functionality

git-svn-id: https://osmand.googlecode.com/svn/trunk@61 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-05-16 21:49:11 +00:00
parent c845cd9175
commit 2060618cb8
13 changed files with 351 additions and 72 deletions

View file

@ -24,6 +24,7 @@ public class ToDoConstants {
// TODO see all calculations x, y for layers & for MapView
// 0. Minimize memory used for index & improve time for read index
//// TODO for releasing version
// 1. POI SEARCH NEAR TO YOU
// 2. FIX BACK TO your location & gps & point of view (may be compass)
@ -45,5 +46,6 @@ public class ToDoConstants {
// 4. Config file log & see log from file
// 6. Predefine what should be extracted from osm (building, poi or roads)
// 7. Fix TODO in files (accept amenity - way)
// 8. add progress for data generation process
}

View file

@ -21,6 +21,15 @@ public class Amenity extends MapObject<Node> {
SHOP, // convenience (product), clothes...
LEISURE, // sport
OTHER, // grave-yard, police, post-office
;
public static AmenityType fromString(String s){
return AmenityType.valueOf(s.toUpperCase());
}
public static String valueToString(AmenityType t){
return t.toString().toLowerCase();
}
}
private static Map<String, AmenityType> prebuiltMap = new LinkedHashMap<String, AmenityType>();
static {
@ -78,12 +87,25 @@ public class Amenity extends MapObject<Node> {
private final Node node;
private String subType;
private AmenityType type;
public Amenity(Node node){
this.node = node;
this.type = getType(node);
this.subType = getSubType(node);
}
public String getSubType(){
public Amenity(){
this.node = null;
}
@Override
public Node getEntity() {
return node;
}
protected String getSubType(Node node){
if(node.getTag(OSMTagKey.AMENITY) != null){
return node.getTag(OSMTagKey.AMENITY);
} else if(node.getTag(OSMTagKey.SHOP) != null){
@ -96,7 +118,7 @@ public class Amenity extends MapObject<Node> {
return "";
}
public AmenityType getType(){
protected AmenityType getType(Node node){
if(node.getTag(OSMTagKey.SHOP) != null){
return AmenityType.SHOP;
} else if(node.getTag(OSMTagKey.TOURISM) != null){
@ -109,6 +131,22 @@ public class Amenity extends MapObject<Node> {
return AmenityType.OTHER;
}
public AmenityType getType(){
return type;
}
public String getSubType(){
return subType;
}
public void setType(AmenityType type) {
this.type = type;
}
public void setSubType(String subType) {
this.subType = subType;
}
public static boolean isAmenity(Entity n){
if(!(n instanceof Node)){
return false;
@ -125,20 +163,15 @@ public class Amenity extends MapObject<Node> {
return false;
}
@Override
public Node getEntity() {
return node;
}
public String getSimpleFormat(){
String name = node.getTag(OSMTagKey.NAME);
String name = getName();
return Algoritms.capitalizeFirstLetterAndLowercase(getType().toString()) +
" : " + getSubType() + " " +(name == null ? node.getId() : name);
}
public String getStringWithoutType(){
String name = node.getTag(OSMTagKey.NAME);
return getSubType() + " " +(name == null ? node.getId() : name);
return getSubType() + " " +getName();
}
@Override

View file

@ -4,12 +4,14 @@ import com.osmand.osm.Entity;
public class Building extends MapObject<Entity> {
private final Entity e;
private Entity e;
public Building(Entity e){
this.e = e;
}
public Building(){}
@Override
public Entity getEntity() {
return e;

View file

@ -4,6 +4,7 @@ import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
import com.osmand.Algoritms;
import com.osmand.osm.Entity;
import com.osmand.osm.Node;
import com.osmand.osm.OSMSettings.OSMTagKey;
@ -14,6 +15,7 @@ public class City extends MapObject<Node> {
CITY(10000), TOWN(5000), VILLAGE(1000), HAMLET(300), SUBURB(300);
private double radius;
private CityType(double radius) {
this.radius = radius;
}
@ -22,21 +24,34 @@ public class City extends MapObject<Node> {
return radius;
}
public static String valueToString(CityType t) {
return t.toString().toLowerCase();
}
private final Node el;
public static CityType valueFromString(String place) {
if (place == null) {
return null;
}
for (CityType t : CityType.values()) {
if (t.name().equalsIgnoreCase(place)) {
return t;
}
}
return null;
}
}
private Node el;
private CityType type = null;
private Map<String, Street> streets = new TreeMap<String, Street>();
public City(Node el){
this.el = el;
String place = el.getTag(OSMTagKey.PLACE);
for(CityType t : CityType.values()){
if(t.name().equalsIgnoreCase(place)){
type = t;
break;
}
type = CityType.valueFromString(el.getTag(OSMTagKey.PLACE));
}
public City(CityType type){
this.type = type;
}
public Street registerStreet(String street){
@ -46,6 +61,13 @@ public class City extends MapObject<Node> {
return streets.get(street);
}
public Street registerStreet(Street street){
if(!Algoritms.isEmpty(street.getName())){
return streets.put(street.getName(), street);
}
return null;
}
public Street registerBuilding(Entity e){
String number = e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER);
String street = e.getTag(OSMTagKey.ADDR_STREET);

View file

@ -9,9 +9,26 @@ public abstract class MapObject<T extends Entity> implements Comparable<MapObjec
protected String name = null;
protected LatLon location = null;
protected Long id = null;
// could be null
public abstract T getEntity();
public void setId(Long id) {
this.id = id;
}
public Long getId() {
if(id != null){
return id;
}
T e = getEntity();
if(e != null){
return e.getId();
}
return null;
}
public String getName() {
if (this.name != null) {
return this.name;

View file

@ -133,6 +133,13 @@ public class Region {
amenities.registerObject(location.getLatitude(), location.getLongitude(), a);
}
public void registerCity(City city){
if(city.getType() != null && !Algoritms.isEmpty(city.getName()) && city.getLocation() != null){
LatLon l = city.getLocation();
cityManager.registerObject(l.getLatitude(), l.getLongitude(), city);
cities.get(city.getType()).add(city);
}
}
public City registerCity(Node c){
City city = new City(c);

View file

@ -12,7 +12,6 @@ import com.osmand.osm.OSMSettings.OSMTagKey;
public class Street extends MapObject<Entity> {
private final String name;
private List<Building> buildings = new ArrayList<Building>();
private List<Node> wayNodes = new ArrayList<Node>();
private Node center = null;
@ -21,21 +20,22 @@ public class Street extends MapObject<Entity> {
this.name = name;
}
public Street(){}
public void registerBuilding(Entity e){
Building building = new Building(e);
building.setName(e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER));
buildings.add(building);
}
public void registerBuilding(Building building){
buildings.add(building);
}
public List<Building> getBuildings() {
return buildings;
}
public String getName() {
return name;
}
public LatLon getLocation(){
if(center == null){
calculateCenter();

View file

@ -115,7 +115,7 @@ public class DataExtraction {
// TODO add interested objects
List<Long> interestedObjects = new ArrayList<Long>();
if (writeTestOsmFile != null) {
OSMStorageWriter writer = new OSMStorageWriter(country.getStorage().getRegisteredEntities());
OSMStorageWriter writer = new OSMStorageWriter();
OutputStream output = new FileOutputStream(writeTestOsmFile);
if (writeTestOsmFile.endsWith(".bz2")) {
output.write('B');
@ -123,7 +123,7 @@ public class DataExtraction {
output = new CBZip2OutputStream(output);
}
writer.saveStorage(output, interestedObjects, false);
writer.saveStorage(output, country.getStorage(), interestedObjects, false);
output.close();
}

View file

@ -64,8 +64,26 @@ public class DataIndexBuilder {
}
OutputStream output = checkFile("POI/"+region.getName()+".osm");
try {
OSMStorageWriter writer = new OSMStorageWriter(region.getStorage().getRegisteredEntities());
writer.saveStorage(output, interestedObjects, false);
OSMStorageWriter writer = new OSMStorageWriter();
writer.saveStorage(output, region.getStorage(), interestedObjects, false);
} finally {
output.close();
}
output = checkFile("POI/"+region.getName()+".osmand");
try {
OSMStorageWriter writer = new OSMStorageWriter();
writer.savePOIIndex(output, region);
} finally {
output.close();
}
return this;
}
public DataIndexBuilder buildAddress() throws XMLStreamException, IOException{
OutputStream output = checkFile("Address/"+region.getName()+".osmand");
try {
OSMStorageWriter writer = new OSMStorageWriter();
writer.saveAddressIndex(output, region);
} finally {
output.close();
}

View file

@ -3,7 +3,15 @@ package com.osmand.osm.io;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.osmand.data.Amenity;
import com.osmand.data.Building;
import com.osmand.data.City;
import com.osmand.data.MapObject;
import com.osmand.data.Region;
import com.osmand.data.Street;
import com.osmand.data.Amenity.AmenityType;
import com.osmand.data.City.CityType;
import com.osmand.osm.Entity;
public class OSMIndexStorage extends OsmBaseStorage {
protected static final String ELEM_OSMAND = "osmand";
@ -11,6 +19,12 @@ public class OSMIndexStorage extends OsmBaseStorage {
protected static final String ELEM_CITY = "city";
protected static final String ELEM_STREET = "street";
protected static final String ELEM_BUILDING = "building";
protected static final String ELEM_AMENITY = "amenity";
protected static final String ATTR_CITYTYPE = "citytype";
protected static final String ATTR_TYPE = "type";
protected static final String ATTR_SUBTYPE = "subtype";
protected static final String ATTR_NAME = "name";
public static final String OSMAND_VERSION = "0.1";
@ -21,6 +35,9 @@ public class OSMIndexStorage extends OsmBaseStorage {
this.region = region;
}
protected City currentParsedCity = null;
protected Street currentParsedStreet = null;
@Override
protected void initRootElement(String uri, String localName, String name, Attributes attributes) throws OsmVersionNotSupported {
if(ELEM_OSM.equals(name)){
@ -37,6 +54,17 @@ public class OSMIndexStorage extends OsmBaseStorage {
parseStarted = true;
}
public void parseMapObject(MapObject<? extends Entity> c, Attributes attributes){
double lat = parseDouble(attributes, ATTR_LAT, 0);
double lon = parseDouble(attributes, ATTR_LON, 0);
long id = parseId(attributes, ATTR_ID, -1);
c.setId(id);
if(lat != 0 || lon != 0){
c.setLocation(lat, lon);
}
c.setName(attributes.getValue(ATTR_NAME));
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
name = saxParser.isNamespaceAware() ? localName : name;
@ -44,6 +72,28 @@ public class OSMIndexStorage extends OsmBaseStorage {
initRootElement(uri, localName, name, attributes);
} else if(ELEM_INDEX.equals(name)){
} else if(ELEM_CITY.equals(name)){
CityType t = CityType.valueOf(attributes.getValue(ATTR_CITYTYPE));
City c = new City(t);
parseMapObject(c, attributes);
region.registerCity(c);
currentParsedCity = c;
} else if(ELEM_STREET.equals(name)){
assert currentParsedCity != null;
Street street = new Street();
parseMapObject(street, attributes);
currentParsedCity.registerStreet(street);
currentParsedStreet = street;
} else if(ELEM_BUILDING.equals(name)){
assert currentParsedStreet != null;
Building building = new Building();
parseMapObject(building, attributes);
currentParsedStreet.registerBuilding(building);
} else if(ELEM_AMENITY.equals(name)){
Amenity a = new Amenity();
a.setType(AmenityType.fromString(attributes.getValue(ATTR_TYPE)));
a.setSubType(attributes.getValue(ATTR_SUBTYPE));
parseMapObject(a, attributes);
region.registerAmenity(a);
} else {
super.startElement(uri, localName, name, attributes);
}

View file

@ -16,6 +16,7 @@ import static com.osmand.osm.io.OsmBaseStorage.ELEM_OSM;
import static com.osmand.osm.io.OsmBaseStorage.ELEM_RELATION;
import static com.osmand.osm.io.OsmBaseStorage.ELEM_TAG;
import static com.osmand.osm.io.OsmBaseStorage.ELEM_WAY;
import static com.osmand.osm.io.OSMIndexStorage.*;
import java.io.IOException;
import java.io.OutputStream;
@ -29,7 +30,17 @@ import java.util.Map.Entry;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import com.osmand.Algoritms;
import com.osmand.data.Amenity;
import com.osmand.data.Building;
import com.osmand.data.City;
import com.osmand.data.MapObject;
import com.osmand.data.Region;
import com.osmand.data.Street;
import com.osmand.data.Amenity.AmenityType;
import com.osmand.data.City.CityType;
import com.osmand.osm.Entity;
import com.osmand.osm.LatLon;
import com.osmand.osm.Node;
import com.osmand.osm.Relation;
import com.osmand.osm.Way;
@ -38,17 +49,17 @@ import com.sun.xml.internal.stream.writers.XMLStreamWriterImpl;
public class OSMStorageWriter {
private final Map<Long, Entity> entities;
private final String INDENT = " ";
private final String INDENT2 = INDENT + INDENT;
private final String INDENT3 = INDENT + INDENT + INDENT;
public OSMStorageWriter(Map<Long, Entity> entities){
this.entities = entities;
public OSMStorageWriter(){
}
public void saveStorage(OutputStream output, Collection<Long> interestedObjects, boolean includeLinks) throws XMLStreamException, IOException {
public void saveStorage(OutputStream output, OsmBaseStorage storage, Collection<Long> interestedObjects, boolean includeLinks) throws XMLStreamException, IOException {
Map<Long, Entity> entities = storage.getRegisteredEntities();
PropertyManager propertyManager = new PropertyManager(PropertyManager.CONTEXT_WRITER);
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// String indent = "{http://xml.apache.org/xslt}indent-amount";
@ -92,7 +103,7 @@ public class OSMStorageWriter {
streamWriter.writeAttribute(ATTR_LON, n.getLongitude()+"");
streamWriter.writeAttribute(ATTR_ID, n.getId()+"");
writeTags(streamWriter, n);
streamWriter.writeEndElement();
writeEndElement(streamWriter, INDENT);
}
for(Way w : ways){
@ -101,10 +112,10 @@ public class OSMStorageWriter {
for(Long r : w.getNodeIds()){
writeStartElement(streamWriter, ELEM_ND, INDENT2);
streamWriter.writeAttribute(ATTR_REF, r+"");
streamWriter.writeEndElement();
writeEndElement(streamWriter, INDENT2);
}
writeTags(streamWriter, w);
streamWriter.writeEndElement();
writeEndElement(streamWriter, INDENT);
}
for(Relation r : relations){
@ -118,19 +129,19 @@ public class OSMStorageWriter {
s = "";
}
streamWriter.writeAttribute(ATTR_ROLE, s);
streamWriter.writeAttribute(ATTR_TYPE, getEntityType(e.getKey()));
streamWriter.writeEndElement();
streamWriter.writeAttribute(ATTR_TYPE, getEntityType(entities, e.getKey()));
writeEndElement(streamWriter, INDENT2);
}
writeTags(streamWriter, r);
streamWriter.writeEndElement();
writeEndElement(streamWriter, INDENT);
}
streamWriter.writeEndElement(); // osm
writeEndElement(streamWriter, ""); // osm
streamWriter.writeEndDocument();
streamWriter.flush();
}
private String getEntityType(Long id){
private String getEntityType(Map<Long, Entity> entities , Long id){
Entity e = entities.get(id);
if(e instanceof Way){
return "way";
@ -140,11 +151,96 @@ public class OSMStorageWriter {
return "node";
}
public void savePOIIndex(OutputStream output, Region region) throws XMLStreamException, IOException {
PropertyManager propertyManager = new PropertyManager(PropertyManager.CONTEXT_WRITER);
XMLStreamWriter streamWriter = new XMLStreamWriterImpl(output, propertyManager);
writeStartElement(streamWriter, ELEM_OSMAND, "");
streamWriter.writeAttribute(ATTR_VERSION, OSMAND_VERSION);
List<Amenity> amenities = region.getAmenityManager().getAllObjects();
for(Amenity n : amenities){
if (couldBeWrited(n)) {
writeStartElement(streamWriter, ELEM_AMENITY, INDENT);
writeAttributesMapObject(streamWriter, n);
streamWriter.writeAttribute(ATTR_TYPE, AmenityType.valueToString(n.getType()));
streamWriter.writeAttribute(ATTR_SUBTYPE, n.getSubType());
writeEndElement(streamWriter, INDENT);
}
}
writeEndElement(streamWriter, ""); // osmand
streamWriter.writeEndDocument();
streamWriter.flush();
}
private void writeCity(XMLStreamWriter streamWriter, City c) throws XMLStreamException{
writeStartElement(streamWriter, ELEM_CITY, INDENT);
writeAttributesMapObject(streamWriter, c);
streamWriter.writeAttribute(ATTR_CITYTYPE, CityType.valueToString(c.getType()));
for(Street s : c.getStreets()){
if (couldBeWrited(s)) {
writeStartElement(streamWriter, ELEM_STREET, INDENT2);
writeAttributesMapObject(streamWriter, s);
for(Building b : s.getBuildings()) {
if (couldBeWrited(b)) {
writeStartElement(streamWriter, ELEM_BUILDING, INDENT3);
writeAttributesMapObject(streamWriter, b);
writeEndElement(streamWriter, INDENT3);
}
}
writeEndElement(streamWriter, INDENT2);
}
}
writeEndElement(streamWriter, INDENT);
}
public void saveAddressIndex(OutputStream output, Region region) throws XMLStreamException, IOException {
PropertyManager propertyManager = new PropertyManager(PropertyManager.CONTEXT_WRITER);
XMLStreamWriter streamWriter = new XMLStreamWriterImpl(output, propertyManager);
writeStartElement(streamWriter, ELEM_OSMAND, "");
streamWriter.writeAttribute(ATTR_VERSION, OSMAND_VERSION);
for(CityType t : CityType.values()){
Collection<City> cities = region.getCitiesByType(t);
if(cities != null){
for(City c : cities){
if (couldBeWrited(c)) {
writeCity(streamWriter, c);
}
}
}
}
writeEndElement(streamWriter, ""); // osmand
streamWriter.writeEndDocument();
streamWriter.flush();
}
public boolean couldBeWrited(MapObject<? extends Entity> e){
if(!Algoritms.isEmpty(e.getName()) && e.getLocation() != null){
return true;
}
return false;
}
public void writeAttributesMapObject(XMLStreamWriter streamWriter, MapObject<? extends Entity> e) throws XMLStreamException{
LatLon location = e.getLocation();
streamWriter.writeAttribute(ATTR_LAT, location.getLatitude()+"");
streamWriter.writeAttribute(ATTR_LON, location.getLongitude()+"");
streamWriter.writeAttribute(ATTR_NAME, e.getName());
streamWriter.writeAttribute(ATTR_ID, e.getId()+"");
}
private void writeStartElement(XMLStreamWriter writer, String name, String indent) throws XMLStreamException{
writer.writeCharacters("\n"+indent);
writer.writeStartElement(name);
}
private void writeEndElement(XMLStreamWriter writer, String indent) throws XMLStreamException{
writer.writeCharacters("\n"+indent);
writer.writeEndElement();
}
private void writeTags(XMLStreamWriter writer, Entity e) throws XMLStreamException{
for(Entry<String, String> en : e.getTags().entrySet()){

View file

@ -65,7 +65,7 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
public static final int divNonLoadedImage = 16;
public static JMenu getMenuToChooseSource(final MapPanel panel){
final JMenu tiles = new JMenu("Source tile");
final JMenu tiles = new JMenu("Source of tiles");
final List<TileSourceTemplate> list = TileSourceManager.getKnownSourceTemplates();
for(final TileSourceTemplate l : list){
JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(l.getName());

View file

@ -110,6 +110,7 @@ public class OsmExtractionUI implements IMapLocationListener {
private JCheckBox buildPoiIndex;
private JCheckBox buildAddressIndex;
private TreeModelListener treeModelListener;
private JCheckBox zipIndexFiles;
@ -279,6 +280,7 @@ public class OsmExtractionUI implements IMapLocationListener {
generateDataButton.setEnabled(region != null);
buildAddressIndex.setEnabled(generateDataButton.isEnabled() && region.getCitiesCount(null) > 0);
buildPoiIndex.setEnabled(generateDataButton.isEnabled() && !region.getAmenityManager().isEmpty());
zipIndexFiles.setEnabled(generateDataButton.isEnabled());
}
public void createButtonsBar(Container content){
@ -295,26 +297,8 @@ public class OsmExtractionUI implements IMapLocationListener {
@Override
public void actionPerformed(ActionEvent e) {
DataIndexBuilder builder = new DataIndexBuilder(DataExtractionSettings.getSettings().getDefaultWorkingDir(), region);
StringBuilder msg = new StringBuilder();
try {
msg.append("Indices checked for ").append(region.getName());
if(buildPoiIndex.isEnabled()){
builder.buildPOI();
msg.append(", POI index ").append("successfully created");
generateData();
}
msg.append(".");
JOptionPane pane = new JOptionPane(msg);
JDialog dialog = pane.createDialog(frame, "Generation data");
dialog.setVisible(true);
} catch (XMLStreamException e1) {
ExceptionHandler.handle(e1);
} catch (IOException e1) {
ExceptionHandler.handle(e1);
}
}
});
buildPoiIndex = new JCheckBox();
@ -327,9 +311,57 @@ public class OsmExtractionUI implements IMapLocationListener {
panel.add(buildAddressIndex);
buildAddressIndex.setSelected(true);
zipIndexFiles = new JCheckBox();
zipIndexFiles.setText("Zip index files");
panel.add(zipIndexFiles);
zipIndexFiles.setSelected(true);
updateButtonsBar();
}
protected void generateData() {
try {
final ProgressDialog dlg = new ProgressDialog(frame, "Generating data");
dlg.setRunnable(new Runnable(){
@Override
public void run() {
dlg.startTask("Generating indices...", -1);
DataIndexBuilder builder = new DataIndexBuilder(DataExtractionSettings.getSettings().getDefaultWorkingDir(), region);
StringBuilder msg = new StringBuilder();
try {
builder.setZipped(zipIndexFiles.isSelected());
msg.append("Indices checked for ").append(region.getName());
if(buildPoiIndex.isEnabled()){
dlg.startTask("Generating POI index...", -1);
builder.buildPOI();
msg.append(", POI index ").append("successfully created");
}
if(buildAddressIndex.isEnabled()){
dlg.startTask("Generating address index...", -1);
builder.buildAddress();
msg.append(", Address index ").append("successfully created");
}
msg.append(".");
JOptionPane pane = new JOptionPane(msg);
JDialog dialog = pane.createDialog(frame, "Generation data");
dialog.setVisible(true);
} catch (XMLStreamException e1) {
throw new IllegalArgumentException(e1);
} catch (IOException e1) {
throw new IllegalArgumentException(e1);
}
}
});
dlg.run();
} catch (InterruptedException e1) {
log.error("Interrupted", e1);
} catch (InvocationTargetException e1) {
ExceptionHandler.handle((Exception) e1.getCause());
}
}
public void createCitySearchPanel(Container content){
JPanel panel = new JPanel(new BorderLayout());
searchTextField = new JTextField();
@ -564,7 +596,7 @@ public class OsmExtractionUI implements IMapLocationListener {
}
public void saveCountry(final File f){
final OSMStorageWriter writer = new OSMStorageWriter(region.getStorage().getRegisteredEntities());
final OSMStorageWriter writer = new OSMStorageWriter();
try {
final ProgressDialog dlg = new ProgressDialog(frame, "Saving osm file");
dlg.setRunnable(new Runnable() {
@ -578,7 +610,7 @@ public class OsmExtractionUI implements IMapLocationListener {
output.write('Z');
output = new CBZip2OutputStream(output);
}
writer.saveStorage(output, null, false);
writer.saveStorage(output, region.getStorage(), null, false);
} finally {
output.close();
}