diff --git a/DataExtractionOSM/.classpath b/DataExtractionOSM/.classpath index ca43d9b9db..96b722cc37 100644 --- a/DataExtractionOSM/.classpath +++ b/DataExtractionOSM/.classpath @@ -4,6 +4,5 @@ - diff --git a/DataExtractionOSM/lib/jpf.jar b/DataExtractionOSM/lib/jpf.jar deleted file mode 100644 index 6d46124c5c..0000000000 Binary files a/DataExtractionOSM/lib/jpf.jar and /dev/null differ diff --git a/DataExtractionOSM/lib/osmosis-0.32.jar b/DataExtractionOSM/lib/osmosis-0.32.jar deleted file mode 100644 index d4d05d1b72..0000000000 Binary files a/DataExtractionOSM/lib/osmosis-0.32.jar and /dev/null differ diff --git a/DataExtractionOSM/src/com/osmand/Constants.java b/DataExtractionOSM/src/com/osmand/Constants.java index 95b4ee06a9..536c061d18 100644 --- a/DataExtractionOSM/src/com/osmand/Constants.java +++ b/DataExtractionOSM/src/com/osmand/Constants.java @@ -3,7 +3,7 @@ package com.osmand; public interface Constants { // TODO externalize proper way - public String pathToTestDataDir = "E:\\Information\\gps\\OpenMap\\"; + public String pathToTestDataDir = "E:\\Information\\OSM maps\\"; public String ADDR_HOUSE_NUMBER = "addr:housenumber"; public String ADDR_STREET = "addr:street"; diff --git a/DataExtractionOSM/src/com/osmand/DataExtraction.java b/DataExtractionOSM/src/com/osmand/DataExtraction.java index b95754b315..164bae5134 100644 --- a/DataExtractionOSM/src/com/osmand/DataExtraction.java +++ b/DataExtractionOSM/src/com/osmand/DataExtraction.java @@ -15,8 +15,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -40,27 +38,23 @@ import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; import javax.xml.stream.XMLStreamException; import org.apache.tools.bzip2.CBZip2InputStream; -import org.openstreetmap.osmosis.core.container.v0_6.EntityContainer; -import org.openstreetmap.osmosis.core.container.v0_6.NodeContainer; -import org.openstreetmap.osmosis.core.domain.v0_6.Entity; -import org.openstreetmap.osmosis.core.domain.v0_6.Node; -import org.openstreetmap.osmosis.core.domain.v0_6.Tag; -import org.openstreetmap.osmosis.core.domain.v0_6.Way; -import org.openstreetmap.osmosis.core.task.v0_6.Sink; -import org.openstreetmap.osmosis.core.xml.v0_6.impl.OsmHandler; import org.xml.sax.SAXException; import com.osmand.MapPanel.IMapLocationListener; -import com.osmand.NodeUtil.LatLon; import com.osmand.data.City; +import com.osmand.data.DataTileManager; import com.osmand.data.Region; import com.osmand.data.Street; 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; +import com.osmand.osm.io.OsmBaseStorage; // TO implement @@ -104,7 +98,7 @@ public class DataExtraction implements IMapLocationListener { } - private static boolean parseMinsk = true; + private static boolean parseMinsk = false; private static boolean parseOSM = true; /////////////////////////////////////////// @@ -113,11 +107,10 @@ public class DataExtraction implements IMapLocationListener { InputStream stream ; if(parseMinsk){ - stream = new FileInputStream(Constants.pathToTestDataDir+"minsk_old.osm"); + stream = new FileInputStream(Constants.pathToTestDataDir+"minsk.osm"); } else { -// stream = new FileInputStream(Constants.pathToTestDataDir+"belarus_2010_04_01.osm.bz2"); -// stream = new FileInputStream(Constants.pathToTestDataDir+"minsk_old.osm"); - stream = new FileInputStream(Constants.pathToTestDataDir+"minsk_2010_04_26.osm.bz2"); + stream = new FileInputStream(Constants.pathToTestDataDir+"belarus_2010_04_01.osm.bz2"); +// stream = new FileInputStream(Constants.pathToTestDataDir+"minsk_2010_04_26.osm.bz2"); if (stream.read() != 66 || stream.read() != 90) throw new RuntimeException( "The source stream must start with the characters BZ if it is to be read as a BZip2 stream."); @@ -132,75 +125,66 @@ public class DataExtraction implements IMapLocationListener { // preloaded data final List places = new ArrayList(); - final Map nodes = new HashMap(); final List buildings = new ArrayList(); final List amenities = new ArrayList(); - - // highways count - final Map mapWays = new LinkedHashMap(); - - if (parseOSM) { - SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); - parser.parse(stream, new OsmHandler(new Sink() { - @Override - public void process(EntityContainer entityContainer) { - if (entityContainer instanceof NodeContainer) { - NodeContainer rc = (NodeContainer) entityContainer; - if (NodeUtil.getTag(rc.getEntity(), "place") != null) { - places.add(rc.getEntity()); - if (places.size() % 500 == 0) { - System.out.println(); - } - System.out.print("-"); - } - nodes.put(rc.getEntity().getId(), new LatLon(rc.getEntity().getLatitude(), - rc.getEntity().getLongitude())); - if (NodeUtil.getTag(entityContainer.getEntity(), "amenity") != null) { - amenities.add((Node) entityContainer.getEntity()); - } else if (NodeUtil.getTag(entityContainer.getEntity(), "shop") != null) { - Entity n = entityContainer.getEntity(); - n.getTags().add(new Tag("amenity", "shop")); - amenities.add((Node) n); - } - - - } else { - if (NodeUtil.tag(entityContainer.getEntity(), "building", "yes")) { - Entity e = entityContainer.getEntity(); - if (NodeUtil.getTag(e, Constants.ADDR_HOUSE_NUMBER) != null - && NodeUtil.getTag(e, Constants.ADDR_STREET) != null) { - buildings.add(e); - } - } - if (NodeUtil.getTag(entityContainer.getEntity(), "highway") != null) { - String h = NodeUtil.getTag(entityContainer.getEntity(), "highway"); - if(!mapWays.containsKey(h)){ - mapWays.put(h, 0); - } - mapWays.put(h, mapWays.get(h) + 1); - - } + final List mapWays = new ArrayList(); + + OsmBaseStorage storage = new OsmBaseStorage(){ + @Override + public boolean acceptEntityToLoad(Entity e) { + if ("yes".equals(e.getTag("building"))) { + if (e.getTag(Constants.ADDR_HOUSE_NUMBER) != null && e.getTag(Constants.ADDR_STREET) != null) { + buildings.add(e); + return true; } } - - @Override - public void complete() { + return super.acceptEntityToLoad(e); + } + + @Override + public boolean acceptNodeToLoad(Node n) { + if (n.getTag("amenity") != null) { + amenities.add(n); + } else if (n.getTag("shop") != null) { + n.putTag("amenity", "shop"); + amenities.add(n); } - - @Override - public void release() { + if (n.getTag("place") != null) { + places.add(n); + if (places.size() % 500 == 0) System.out.println(); + System.out.print("-"); } - }, false)); + + return true; + } + + @Override + public boolean acceptRelationToLoad(Relation w) { + return false; + } + @Override + public boolean acceptWayToLoad(Way w) { + if (WayUtil.wayForCar(w.getTag("highway"))) { + mapWays.add(w); + return true; + } + return false; + } + }; + + + + if (parseOSM) { + storage.parseOSM(stream); } - System.out.println("\n"+mapWays); System.out.println(System.currentTimeMillis() - st); // 1. found towns ! Region country = new Region(null); for (Node s : places) { - String place = NodeUtil.getTag(s, "place"); + String place = s.getTag("place"); if(place == null){ continue; } @@ -209,29 +193,40 @@ public class DataExtraction implements IMapLocationListener { } else { City registerCity = country.registerCity(s); if(registerCity == null){ - System.out.println(place + " - " + NodeUtil.getTag(s, "name")); + System.out.println(place + " - " + s.getTag("name")); } } } // 2. found buildings (index addresses) for(Entity b : buildings){ - LatLon center ; - if(b instanceof Node){ - center = NodeUtil.getLatLon((Node) b); - } else { - center = NodeUtil.getWeightCenter((Way) b, nodes); - } + LatLon center = b.getLatLon(); // TODO first of all tag could be checked NodeUtil.getTag(e, "addr:city") - City city = country.getClosestCity(center); - if(city != null){ - city.registerBuilding(center, b); - } + if(center == null){ + // no nodes where loaded for this way + } else { + City city = country.getClosestCity(center); + if (city != null) { + city.registerBuilding(center, b); + } + } } for(Node node : amenities){ country.registerAmenity(node); } + + + DataTileManager waysManager = new DataTileManager(); + for (Way w : mapWays) { + for (Node n : w.getNodes()) { + if(n != null){ + LatLon latLon = n.getLatLon(); + waysManager.registerObject(latLon.getLatitude(), latLon.getLongitude(), latLon); + } + } + } + mapPanel.setPoints(waysManager); runUI(country); @@ -274,7 +269,7 @@ public class DataExtraction implements IMapLocationListener { DefaultMutableTreeNode strTree = new DataExtractionTreeNode(str.getName(), str); cityNodeTree.add(strTree); for(Entity e : str.getBuildings()){ - DefaultMutableTreeNode building = new DataExtractionTreeNode(NodeUtil.getTag(e, Constants.ADDR_HOUSE_NUMBER), e); + DefaultMutableTreeNode building = new DataExtractionTreeNode(e.getTag(Constants.ADDR_HOUSE_NUMBER), e); strTree.add(building); } @@ -421,7 +416,7 @@ public class DataExtraction implements IMapLocationListener { Map> filter = new TreeMap>(); for(Node n : closestAmenities){ - String type = NodeUtil.getTag(n, "amenity"); + String type = n.getTag("amenity"); if(!filter.containsKey(type)){ filter.put(type, new ArrayList()); } @@ -440,8 +435,8 @@ public class DataExtraction implements IMapLocationListener { for(int i=0; i<15 && i < closestAmenities.size(); i++){ Node n = closestAmenities.get(i); - String type = NodeUtil.getTag(n, "amenity"); - String name = NodeUtil.getTag(n, "name"); + String type = n.getTag("amenity"); + String name = n.getTag("name"); int dist = (int) (NodeUtil.getDistance(n, newLatitude, newLongitude)); String str = type +" "+(name == null ? n.getId() : name) +" [" +dist+" m ]"; ((DefaultMutableTreeNode)amenitiesTree.getChildAt(0)).add( @@ -459,31 +454,14 @@ public class DataExtraction implements IMapLocationListener { if (p == null) { p = new DefaultMutableTreeNode(s); } -// Map consists = new LinkedHashMap(); -// for(Node n : filter.get(s)){ -// consists.put(n, null); -// } -// for(int i=0; i points; + + // zoom levle private int zoom = 15; // degree measurements (-180, 180) @@ -72,7 +81,15 @@ public class MapPanel extends JPanel { private List listeners = new ArrayList(); - private String map = "Mapnik"; + + + // cached data to draw image + private BufferedImage[][] images; + private int xStartingImage = 0; + private int yStartingImage = 0; + private List pointsToDraw = new ArrayList(); + + public MapPanel(File fileWithTiles) { this.fileWithTiles = fileWithTiles; @@ -91,12 +108,11 @@ public class MapPanel extends JPanel { @Override protected void paintComponent(Graphics g) { - System.out.println("draw"); if (images != null) { for (int i = 0; i < images.length; i++) { for (int j = 0; j < images[i].length; j++) { if(images[i][j] == null){ - if((i+j + (int)getXTile() + (int)getYTile()) % 2 == 0){ + if ((i + j + (int) getXTile() + (int) getYTile()) % 2 == 0) { g.setColor(Color.gray); } else { g.setColor(Color.white); @@ -109,6 +125,12 @@ public class MapPanel extends JPanel { } } g.setColor(Color.black); + // draw user points + for(Point p : pointsToDraw){ + g.drawOval(p.x, p.y, 3, 3); + g.fillOval(p.x, p.y, 3, 3); + } + g.fillOval(getWidth()/2 - 2, getHeight()/2 -2, 4, 4); g.drawOval(getWidth()/2 - 2, getHeight()/2 -2, 4, 4); @@ -176,6 +198,31 @@ public class MapPanel extends JPanel { images[i][j]= getImageFor(xStartInd + i, yStartInd + j); } } + + if(points != null){ + double latDown = NodeUtil.getLatitudeFromTile(zoom, + NodeUtil.getTileNumberY(zoom, latitude) + ((double)getHeight()/tileSize)); + double longDown = NodeUtil.getLongitudeFromTile(zoom, + NodeUtil.getTileNumberX(zoom, longitude) + ((double)getWidth()/tileSize)); + double latUp = NodeUtil.getLatitudeFromTile(zoom, + NodeUtil.getTileNumberY(zoom, latitude) - ((double)getHeight()/tileSize)); + double longUp = NodeUtil.getLongitudeFromTile(zoom, + NodeUtil.getTileNumberX(zoom, longitude) - ((double)getWidth()/tileSize)); + List objects = points.getObjects(latUp, longUp, latDown, longDown); + pointsToDraw.clear(); + for(LatLon n : objects){ + int pixX = NodeUtil.getPixelShiftX(zoom, n.getLongitude(), this.longitude, tileSize) + + getWidth() / 2; + int pixY = NodeUtil.getPixelShiftY(zoom, n.getLatitude(), this.latitude, tileSize) + + getHeight() / 2; + if(pixX >= 0 && pixY >= 0){ + pointsToDraw.add(new Point(pixX, pixY)); + } + } + + + } + repaint(); } catch (IOException e) { e.printStackTrace(); @@ -249,17 +296,20 @@ public class MapPanel extends JPanel { protected void processKeyEvent(KeyEvent e) { boolean processed = false; if (e.getID() == KeyEvent.KEY_RELEASED) { - if (e.getKeyCode() == 37) { + // LEFT button longitude = NodeUtil.getLongitudeFromTile(zoom, getXTile()-0.5); processed = true; } else if (e.getKeyCode() == 39) { + // RIGHT button longitude = NodeUtil.getLongitudeFromTile(zoom, getXTile()+0.5); processed = true; } else if (e.getKeyCode() == 38) { + // UP button latitude = NodeUtil.getLatitudeFromTile(zoom, getYTile()-0.5); processed = true; } else if (e.getKeyCode() == 40) { + // DOWN button latitude = NodeUtil.getLatitudeFromTile(zoom, getYTile()+0.5); processed = true; } @@ -282,6 +332,14 @@ public class MapPanel extends JPanel { super.processKeyEvent(e); } + public DataTileManager getPoints() { + return points; + } + + public void setPoints(DataTileManager points) { + this.points = points; + } + public class MapMouseAdapter extends MouseAdapter { private Point startDragging = null; diff --git a/DataExtractionOSM/src/com/osmand/NodeUtil.java b/DataExtractionOSM/src/com/osmand/NodeUtil.java index 7db4507960..10e980ce4b 100644 --- a/DataExtractionOSM/src/com/osmand/NodeUtil.java +++ b/DataExtractionOSM/src/com/osmand/NodeUtil.java @@ -1,80 +1,15 @@ package com.osmand; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; -import java.util.Map; -import org.openstreetmap.osmosis.core.domain.v0_6.Entity; -import org.openstreetmap.osmosis.core.domain.v0_6.Node; -import org.openstreetmap.osmosis.core.domain.v0_6.Tag; -import org.openstreetmap.osmosis.core.domain.v0_6.Way; -import org.openstreetmap.osmosis.core.domain.v0_6.WayNode; +import com.osmand.osm.Entity; +import com.osmand.osm.LatLon; +import com.osmand.osm.Node; public class NodeUtil { - public static class LatLon { - private final double longitude; - private final double latitude; - public LatLon(double latitude, double longitude){ - this.latitude = latitude; - this.longitude = longitude; - } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(latitude); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(longitude); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - LatLon other = (LatLon) obj; - if (Double.doubleToLongBits(latitude) != Double - .doubleToLongBits(other.latitude)) - return false; - if (Double.doubleToLongBits(longitude) != Double - .doubleToLongBits(other.longitude)) - return false; - return true; - } - @Override - public String toString() { - return "Lat " + latitude +" Lon "+ longitude; - } - - public double getLatitude() { - return latitude; - } - - public double getLongitude() { - return longitude; - } - - } - - - public static String getTag(Entity e, String name){ - for(Tag t : e.getTags()){ - if(name.equals(t.getKey())){ - return t.getValue(); - } - } - return null; - } - public static double getDistance(Node e1, Node e2){ return getDistance(e1.getLatitude(), e1.getLongitude(), e2.getLatitude(), e2.getLongitude()); } @@ -131,28 +66,6 @@ public class NodeUtil { return new LatLon(n.getLatitude(), n.getLongitude()); } - public static LatLon getWeightCenter(Way way, Map nodes){ - List wayNodes = way.getWayNodes(); - ArrayList arrayList = new ArrayList(wayNodes.size()); - for(WayNode n : wayNodes){ - if(nodes.containsKey(n.getNodeId())){ - arrayList.add(nodes.get(n.getNodeId())); - } - } - return getWeightCenter(arrayList); - } - - public static LatLon getWeightCenterForNodes(Way way, Map nodes){ - List wayNodes = way.getWayNodes(); - ArrayList arrayList = new ArrayList(wayNodes.size()); - for(WayNode n : wayNodes){ - if(nodes.containsKey(n.getNodeId())){ - arrayList.add(nodes.get(n.getNodeId())); - } - } - return getWeightCenterForNodes(arrayList); - } - /** @@ -191,13 +104,22 @@ public class NodeUtil { return Math.atan(Math.sinh(Math.PI * (1 - 2 * y / (1 << zoom)))) * 180d / Math.PI; } - public static boolean isEmpty(String s){ - return s == null || s.length() == 0; + public static int getPixelShiftX(int zoom, double long1, double long2, int tileSize){ + return (int) ((NodeUtil.getTileNumberX(zoom, long1) - NodeUtil.getTileNumberX(zoom, long2)) * tileSize); + } + + public static int getPixelShiftY(int zoom, double lat1, double lat2, int tileSize){ + return (int) ((NodeUtil.getTileNumberY(zoom, lat1) - NodeUtil.getTileNumberY(zoom, lat2)) * tileSize); } + public static boolean isEmpty(String s){ + return s == null || s.length() == 0; + } + + public static boolean objectEquals(Object a, Object b){ if(a == null){ return b == null; @@ -207,7 +129,7 @@ public class NodeUtil { } public static boolean tag(Entity e, String name, String value){ - String tag = getTag(e, name); + String tag = e.getTag(name); return value.equals(tag); } } diff --git a/DataExtractionOSM/src/com/osmand/WayUtil.java b/DataExtractionOSM/src/com/osmand/WayUtil.java new file mode 100644 index 0000000000..3ce46e8573 --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/WayUtil.java @@ -0,0 +1,19 @@ +package com.osmand; + +public class WayUtil { + + + public static boolean wayForCar(String tagHighway){ + if(tagHighway != null){ + String[] cars = new String[]{"trunk", "motorway", "primary", "secondary", "tertiary", "service", "residential", + "trunk_link", "motorway_link", "primary_link", "secondary_link", "residential_link", + "tertiary_link" }; + for(String c : cars){ + if(c.equals(tagHighway)){ + return true; + } + } + } + return false; + } +} diff --git a/DataExtractionOSM/src/com/osmand/data/City.java b/DataExtractionOSM/src/com/osmand/data/City.java index 8d59307a89..08fe3a816f 100644 --- a/DataExtractionOSM/src/com/osmand/data/City.java +++ b/DataExtractionOSM/src/com/osmand/data/City.java @@ -4,11 +4,10 @@ import java.util.Collection; import java.util.Map; import java.util.TreeMap; -import org.openstreetmap.osmosis.core.domain.v0_6.Entity; -import org.openstreetmap.osmosis.core.domain.v0_6.Node; - import com.osmand.NodeUtil; -import com.osmand.NodeUtil.LatLon; +import com.osmand.osm.Entity; +import com.osmand.osm.LatLon; +import com.osmand.osm.Node; public class City { @@ -31,7 +30,7 @@ public class City { public City(Node el){ this.el = el; - String place = NodeUtil.getTag(el, "place"); + String place = el.getTag("place"); for(CityType t : CityType.values()){ if(t.name().equalsIgnoreCase(place)){ type = t; @@ -41,8 +40,8 @@ public class City { } public Street registerBuilding(LatLon point, Entity e){ - String number = NodeUtil.getTag(e, "addr:housenumber"); - String street = NodeUtil.getTag(e, "addr:street"); + String number = e.getTag("addr:housenumber"); + String street = e.getTag("addr:street"); if( street != null && number != null){ if(!streets.containsKey(street)){ streets.put(street, new Street(street)); @@ -55,7 +54,7 @@ public class City { public String getName(){ - return NodeUtil.getTag(el, "name"); + return el.getTag("name"); } public CityType getType(){ diff --git a/DataExtractionOSM/src/com/osmand/data/DataTileManager.java b/DataExtractionOSM/src/com/osmand/data/DataTileManager.java index 0166ed5b61..9ef783b2f1 100644 --- a/DataExtractionOSM/src/com/osmand/data/DataTileManager.java +++ b/DataExtractionOSM/src/com/osmand/data/DataTileManager.java @@ -38,6 +38,20 @@ public class DataTileManager { } } + public List getObjects(double latitudeUp, double longitudeUp, double latitudeDown, double longitudeDown) { + int tileXUp = (int) NodeUtil.getTileNumberX(zoom, longitudeUp); + int tileYUp = (int) NodeUtil.getTileNumberY(zoom, latitudeUp); + int tileXDown = (int) NodeUtil.getTileNumberX(zoom, longitudeDown); + int tileYDown = (int) NodeUtil.getTileNumberY(zoom, latitudeDown); + List result = new ArrayList(); + for (int i = tileXUp; i <= tileXDown; i++) { + for (int j = tileYUp; j <= tileYDown; j++) { + putObjects(i, j, result); + } + } + return result; + } + /** * @depth of the neighbor tile to visit * returns not exactly sorted list, @@ -52,8 +66,8 @@ public class DataTileManager { putObjects(tileX, tileY, result); // that's very difficult way visiting node : - // similar to visit like spiral - // however the simplest way could visit by matrix & after that sort tiles by distance (that's less efficient) + // similar to visit by spiral + // however the simplest way could be to visit row by row & after sort tiles by distance (that's less efficient) // go through circle for (int i = 1; i <= depth; i++) { diff --git a/DataExtractionOSM/src/com/osmand/data/Region.java b/DataExtractionOSM/src/com/osmand/data/Region.java index 9eb23ac691..8a250d75b6 100644 --- a/DataExtractionOSM/src/com/osmand/data/Region.java +++ b/DataExtractionOSM/src/com/osmand/data/Region.java @@ -6,12 +6,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.openstreetmap.osmosis.core.domain.v0_6.Entity; -import org.openstreetmap.osmosis.core.domain.v0_6.Node; - import com.osmand.NodeUtil; -import com.osmand.NodeUtil.LatLon; import com.osmand.data.City.CityType; +import com.osmand.osm.Entity; +import com.osmand.osm.LatLon; +import com.osmand.osm.Node; public class Region { private Entity entity; @@ -36,7 +35,7 @@ public class Region { } public String getName(){ - return entity == null ? "" : NodeUtil.getTag(entity, "name"); + return entity == null ? "" : entity.getTag("name"); } public Collection getCitiesByType(CityType type){ diff --git a/DataExtractionOSM/src/com/osmand/data/Street.java b/DataExtractionOSM/src/com/osmand/data/Street.java index b9072ea539..637c6bc264 100644 --- a/DataExtractionOSM/src/com/osmand/data/Street.java +++ b/DataExtractionOSM/src/com/osmand/data/Street.java @@ -4,9 +4,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import org.openstreetmap.osmosis.core.domain.v0_6.Entity; - -import com.osmand.NodeUtil.LatLon; +import com.osmand.osm.Entity; +import com.osmand.osm.LatLon; public class Street { diff --git a/DataExtractionOSM/src/com/osmand/osm/Entity.java b/DataExtractionOSM/src/com/osmand/osm/Entity.java new file mode 100644 index 0000000000..8703609511 --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/osm/Entity.java @@ -0,0 +1,74 @@ +package com.osmand.osm; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +public abstract class Entity { + // lazy initializing + private Map tags = null; + private final long id; + + public Entity(long id) { + this.id = id; + } + + public long getId() { + return id; + } + + public String putTag(String key, String value){ + if(tags == null){ + tags = new LinkedHashMap(); + } + return tags.put(key, value); + } + + public String getTag(String key){ + if(tags == null){ + return null; + } + return tags.get(key); + } + + public Map getTags() { + return Collections.unmodifiableMap(tags); + } + + + public Collection getTagKeySet(){ + if(tags == null){ + return Collections.emptyList(); + } + return tags.keySet(); + } + + public abstract void initializeLinks(Map entities); + + + /** + * @return middle point for entity + */ + public abstract LatLon getLatLon(); + + + @Override + public int hashCode() { + return (int) id; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Entity other = (Entity) obj; + if (id != other.id) + return false; + return true; + } +} diff --git a/DataExtractionOSM/src/com/osmand/osm/LatLon.java b/DataExtractionOSM/src/com/osmand/osm/LatLon.java new file mode 100644 index 0000000000..6f63d64ada --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/osm/LatLon.java @@ -0,0 +1,52 @@ +package com.osmand.osm; + +public class LatLon { + private final double longitude; + private final double latitude; + + public LatLon(double latitude, double longitude){ + this.latitude = latitude; + this.longitude = longitude; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(latitude); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(longitude); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + LatLon other = (LatLon) obj; + if (Double.doubleToLongBits(latitude) != Double + .doubleToLongBits(other.latitude)) + return false; + if (Double.doubleToLongBits(longitude) != Double + .doubleToLongBits(other.longitude)) + return false; + return true; + } + @Override + public String toString() { + return "Lat " + latitude +" Lon "+ longitude; + } + + public double getLatitude() { + return latitude; + } + + public double getLongitude() { + return longitude; + } + + } \ No newline at end of file diff --git a/DataExtractionOSM/src/com/osmand/osm/Node.java b/DataExtractionOSM/src/com/osmand/osm/Node.java new file mode 100644 index 0000000000..b580f6d4c9 --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/osm/Node.java @@ -0,0 +1,45 @@ +package com.osmand.osm; + +import java.util.Map; + +public class Node extends Entity { + + private double latitude; + private double longitude; + // currently not used +// private boolean visible = true; + + public Node(double latitude, double longitude, long id){ + super(id); + this.latitude = latitude; + this.longitude = longitude; + } + + public double getLatitude() { + return latitude; + } + + public double getLongitude() { + return longitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + @Override + public LatLon getLatLon() { + return new LatLon(latitude, longitude); + } + + @Override + public void initializeLinks(Map entities) { + // nothing to initialize + + } + +} diff --git a/DataExtractionOSM/src/com/osmand/osm/Relation.java b/DataExtractionOSM/src/com/osmand/osm/Relation.java new file mode 100644 index 0000000000..10f188105a --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/osm/Relation.java @@ -0,0 +1,98 @@ +package com.osmand.osm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class Relation extends Entity { + + // lazyLoading + Map members = null; + Map memberEntities = null; + + + + public Relation(long id) { + super(id); + } + + public void addMember(Long id, String role){ + if(members == null){ + members = new LinkedHashMap(); + } + members.put(id, role); + } + + public String removeMember(Long id){ + if(members == null){ + return null; + } + return members.remove(id); + } + + public String getRole(Entity e){ + return members.get(e.getId()); + } + + public String getRole(Long id){ + return members.get(id); + } + + public Collection getMemberIds(String role) { + if (members == null) { + return Collections.emptyList(); + } + if (role == null) { + return members.keySet(); + } + List l = new ArrayList(); + for (Long m : members.keySet()) { + if (role.equals(members.get(m))) { + l.add(m); + } + } + return l; + } + + public Collection getMembers(String role) { + if (memberEntities == null) { + return Collections.emptyList(); + } + if (role == null) { + return memberEntities.keySet(); + } + List l = new ArrayList(); + for (Entity m : memberEntities.keySet()) { + if (role.equals(memberEntities.get(m))) { + l.add(m); + } + } + return l; + } + + @Override + public void initializeLinks(Map entities){ + if (members != null) { + if(memberEntities == null){ + memberEntities = new LinkedHashMap(); + } else { + memberEntities.clear(); + } + for(Long l : members.keySet()){ + if(l != null && entities.get(l) != null){ + memberEntities.put(entities.get(l), members.get(l)); + } + } + } + } + + + @Override + public LatLon getLatLon() { + return null; + } + +} diff --git a/DataExtractionOSM/src/com/osmand/osm/Way.java b/DataExtractionOSM/src/com/osmand/osm/Way.java new file mode 100644 index 0000000000..25657c7815 --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/osm/Way.java @@ -0,0 +1,76 @@ +package com.osmand.osm; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.osmand.NodeUtil; + +public class Way extends Entity { + + // lazy loading + private List nodeIds = null; + private List nodes = null; + + public Way(long id) { + super(id); + } + + public void addNode(long id){ + if(nodeIds == null){ + nodeIds = new ArrayList(); + } + nodeIds.add(id); + } + + public Long removeNodeByIndex(int i){ + if(nodeIds == null){ + return null; + } + return nodeIds.remove(i); + } + + public List getNodeIds(){ + return nodeIds; + } + + public List getNodes() { + return nodes; + } + + @Override + public void initializeLinks(Map entities) { + if (nodeIds != null) { + if(nodes == null){ + nodes = new ArrayList(); + } else { + nodes.clear(); + } + for (int i = 0; i < nodeIds.size(); i++) { + if(entities.get(nodeIds.get(i)) instanceof Node){ + nodes.add((Node) entities.get(nodeIds.get(i))); + } else { + nodes.add(null); + } + } + } + + } + + @Override + public LatLon getLatLon() { + if(nodes == null){ + return null; + } + List list = new ArrayList(nodes.size()); + for(Node n : nodes){ + if(n != null){ + list.add(n.getLatLon()); + } + } + return NodeUtil.getWeightCenter(list); + } + + + +} diff --git a/DataExtractionOSM/src/com/osmand/osm/io/OsmBaseStorage.java b/DataExtractionOSM/src/com/osmand/osm/io/OsmBaseStorage.java new file mode 100644 index 0000000000..93c4d8c8e2 --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/osm/io/OsmBaseStorage.java @@ -0,0 +1,188 @@ +package com.osmand.osm.io; + +import java.io.IOException; +import java.io.InputStream; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.osmand.osm.Entity; +import com.osmand.osm.Node; +import com.osmand.osm.Relation; +import com.osmand.osm.Way; + +public class OsmBaseStorage extends DefaultHandler { + + protected static final String ELEM_OSM = "osm"; + protected static final String ELEM_NODE = "node"; + protected static final String ELEM_TAG = "tag"; + protected static final String ELEM_WAY = "way"; + protected static final String ELEM_ND = "nd"; + protected static final String ELEM_RELATION = "relation"; + protected static final String ELEM_MEMBER = "member"; + + + protected static final String ATTR_VERSION = "version"; + protected static final String ATTR_ID = "id"; + protected static final String ATTR_LAT = "lat"; + protected static final String ATTR_LON = "lon"; + protected static final String ATTR_K = "k"; + protected static final String ATTR_V = "v"; + + protected static final String ATTR_TYPE = "type"; + protected static final String ATTR_REF = "ref"; + protected static final String ATTR_ROLE = "role"; + + protected Entity currentParsedEntity = null; + + private boolean parseStarted; + + protected Map entities = new LinkedHashMap(); + + + + /** + * @param stream + * @throws IOException + * @throws SAXException - could be + */ + public synchronized void parseOSM(InputStream stream) throws IOException, SAXException { + SAXParser parser = initSaxParser(); + parseStarted = false; + entities.clear(); + parser.parse(stream, this); + completeReading(); + } + + private SAXParser saxParser; + public SAXParser initSaxParser(){ + if(saxParser != null){ + return saxParser; + } + SAXParserFactory factory = SAXParserFactory.newInstance(); + try { + return saxParser = factory.newSAXParser(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException(e); + } catch (SAXException e) { + throw new IllegalStateException(e); + } + } + + protected Long parseId(Attributes a, String name, long defId){ + long id = defId; + String value = a.getValue(name); + try { + id = Long.parseLong(value); + } catch (NumberFormatException e) { + } + return id; + } + + protected double parseDouble(Attributes a, String name, double defVal){ + double ret = defVal; + String value = a.getValue(name); + try { + ret = Double.parseDouble(value); + } catch (NumberFormatException e) { + } + return ret; + } + + @Override + public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { + if(!parseStarted){ + if(!ELEM_OSM.equals(name) || !"0.6".equals(attributes.getValue(ATTR_VERSION))){ + throw new OsmVersionNotSupported(); + } + parseStarted = true; + } + if (currentParsedEntity == null) { + if (ELEM_NODE.equals(name)) { + currentParsedEntity = new Node(parseDouble(attributes, ATTR_LAT, 0), parseDouble(attributes, ATTR_LON, 0), + parseId(attributes, ATTR_ID, -1)); + } else if (ELEM_WAY.equals(name)) { + currentParsedEntity = new Way(parseId(attributes, ATTR_ID, -1)); + } else if (ELEM_RELATION.equals(name)) { + currentParsedEntity = new Relation(parseId(attributes, ATTR_ID, -1)); + } else { + // this situation could be logged as unhandled + } + } else { + if (ELEM_TAG.equals(name)) { + String key = attributes.getValue(ATTR_K); + if(key != null){ + currentParsedEntity.putTag(key, attributes.getValue(ATTR_V)); + } + } else if (ELEM_ND.equals(name)) { + Long id = parseId(attributes, ATTR_REF, -1); + if(id != -1 && currentParsedEntity instanceof Way){ + ((Way)currentParsedEntity).addNode(id); + } + } else if (ELEM_MEMBER.equals(name)) { + Long id = parseId(attributes, ATTR_REF, -1); + if(id != -1 && currentParsedEntity instanceof Relation){ + ((Relation)currentParsedEntity).addMember(id, attributes.getValue(ATTR_ROLE)); + } + + } else { + // this situation could be logged as unhandled + } + } + } + + @Override + public void endElement(String uri, String localName, String name) throws SAXException { + if (ELEM_NODE.equals(name) || ELEM_WAY.equals(name) || ELEM_RELATION.equals(name)) { + if(currentParsedEntity != null){ + if(acceptEntityToLoad(currentParsedEntity)){ + Entity oldEntity = entities.put(currentParsedEntity.getId(), currentParsedEntity); + if(oldEntity!= null){ + throw new UnsupportedOperationException("Entity with id=" + oldEntity.getId() +" is duplicated in osm map"); + } + } + currentParsedEntity = null; + } + } + super.endElement(uri, localName, name); + } + + + public void completeReading(){ + for(Entity e : entities.values()){ + e.initializeLinks(entities); + } + } + + public boolean acceptEntityToLoad(Entity e){ + if(e instanceof Way){ + return acceptWayToLoad((Way) e); + } else if(e instanceof Relation){ + return acceptRelationToLoad((Relation) e); + } else if(e instanceof Node){ + return acceptNodeToLoad((Node) e); + } + return false; + } + + public boolean acceptWayToLoad(Way w){ + return true; + } + + public boolean acceptRelationToLoad(Relation w){ + return true; + } + + public boolean acceptNodeToLoad(Node n){ + return true; + } + + +} diff --git a/DataExtractionOSM/src/com/osmand/osm/io/OsmVersionNotSupported.java b/DataExtractionOSM/src/com/osmand/osm/io/OsmVersionNotSupported.java new file mode 100644 index 0000000000..6aa28aabf1 --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/osm/io/OsmVersionNotSupported.java @@ -0,0 +1,11 @@ +package com.osmand.osm.io; + +import org.xml.sax.SAXException; + +/** + * Thrown when version is not supported + */ +public class OsmVersionNotSupported extends SAXException { + private static final long serialVersionUID = -127558215143984838L; + +}