From af58f7d915f7c79a0cfa95ccca0eeee30569ec02 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Mon, 6 May 2013 04:39:33 +0200 Subject: [PATCH] start of a OsmPbfReader --- src/org/oscim/utils/osmpbf/OsmPbfParser.java | 321 +++++++++++++++++++ src/org/oscim/utils/osmpbf/OsmPbfReader.java | 38 +++ 2 files changed, 359 insertions(+) create mode 100644 src/org/oscim/utils/osmpbf/OsmPbfParser.java create mode 100644 src/org/oscim/utils/osmpbf/OsmPbfReader.java diff --git a/src/org/oscim/utils/osmpbf/OsmPbfParser.java b/src/org/oscim/utils/osmpbf/OsmPbfParser.java new file mode 100644 index 00000000..8c972b76 --- /dev/null +++ b/src/org/oscim/utils/osmpbf/OsmPbfParser.java @@ -0,0 +1,321 @@ +// This software is released into the Public Domain. See copying.txt for details. +package org.oscim.utils.osmpbf; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.openstreetmap.osmosis.osmbinary.BinaryParser; +import org.openstreetmap.osmosis.osmbinary.Osmformat; +import org.oscim.core.Tag; +import org.oscim.core.TagSet; +import org.oscim.core.osm.OSMData; +import org.oscim.core.osm.OSMMember; +import org.oscim.core.osm.OSMNode; +import org.oscim.core.osm.OSMRelation; +import org.oscim.core.osm.OSMWay; + +import android.util.Log; + +/** + * Class that reads and parses binary files and sends the contained entities to + * the sink. + */ +public class OsmPbfParser extends BinaryParser { + + @Override + public void complete() { + //sink.complete(); + } + + // /** Get the osmosis object representing a the user in a given Info protobuf. + // * @param info The info protobuf. + // * @return The OsmUser object */ + // OsmUser getUser(Osmformat.Info info) { + // // System.out.println(info); + // if (info.hasUid() && info.hasUserSid()) { + // if (info.getUid() < 0) { + // return OsmUser.NONE; + // } + // return new OsmUser(info.getUid(), getStringById(info.getUserSid())); + // } else { + // return OsmUser.NONE; + // } + // } + + /** + * The magic number used to indicate no version number metadata for this + * entity. + */ + static final int NOVERSION = -1; + /** The magic number used to indicate no changeset metadata for this entity. */ + static final int NOCHANGESET = -1; + + HashMap mNodeMap = new HashMap(); + HashMap mWayMap = new HashMap(); + + @Override + protected void parseNodes(List nodes) { + for (Osmformat.Node i : nodes) { + int tagCnt = i.getKeysCount(); + + TagSet tags = new TagSet(tagCnt); + + // List tags = new ArrayList(); + for (int j = 0; j < tagCnt; j++) { + tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j)))); + } + // long id, int version, Date timestamp, OsmUser user, + // long changesetId, Collection tags, + // double latitude, double longitude + OSMNode tmp; + long id = i.getId(); + double latf = parseLat(i.getLat()), lonf = parseLon(i.getLon()); + + // if (i.hasInfo()) { + // Osmformat.Info info = i.getInfo(); + // tmp = new OSMNode(new CommonEntityData(id, info.getVersion(), getDate(info), + // getUser(info), info.getChangeset(), tags), latf, lonf); + // } else { + tmp = new OSMNode(latf, lonf, tags, id); + // tmp = new Node(new CommonEntityData(id, NOVERSION, NODATE, OsmUser.NONE, + // NOCHANGESET, tags), latf, lonf); + // } + //sink.process(new NodeContainer(tmp)); + mNodeMap.put(Long.valueOf(id), tmp); + } + } + + @Override + protected void parseDense(Osmformat.DenseNodes nodes) { + long lastId = 0, lastLat = 0, lastLon = 0; + + int j = 0; // Index into the keysvals array. + + // Stuff for dense info + // long lasttimestamp = 0, lastchangeset = 0; + // int lastuserSid = 0, lastuid = 0; + // DenseInfo di = null; + // if (nodes.hasDenseinfo()) { + // di = nodes.getDenseinfo(); + // } + + for (int i = 0; i < nodes.getIdCount(); i++) { + OSMNode tmp; + TagSet tags = new TagSet(4); + long lat = nodes.getLat(i) + lastLat; + lastLat = lat; + long lon = nodes.getLon(i) + lastLon; + lastLon = lon; + long id = nodes.getId(i) + lastId; + lastId = id; + double latf = parseLat(lat), lonf = parseLon(lon); + // If empty, assume that nothing here has keys or vals. + if (nodes.getKeysValsCount() > 0) { + while (nodes.getKeysVals(j) != 0) { + int keyid = nodes.getKeysVals(j++); + int valid = nodes.getKeysVals(j++); + tags.add(new Tag(getStringById(keyid), getStringById(valid))); + } + j++; // Skip over the '0' delimiter. + } + // Handle dense info. + // if (di != null) { + // int uid = di.getUid(i) + lastuid; lastuid = uid; + // int userSid = di.getUserSid(i) + lastuserSid; lastuserSid = userSid; + // long timestamp = di.getTimestamp(i) + lasttimestamp; lasttimestamp = timestamp; + // int version = di.getVersion(i); + // long changeset = di.getChangeset(i) + lastchangeset; lastchangeset = changeset; + // + // Date date = new Date(date_granularity * timestamp); + + //OsmUser user; + // if (uid < 0) { + // user = OsmUser.NONE; + // } else { + // user = new OsmUser(uid, getStringById(userSid)); + // } + // + // tmp = new OSMNode(id, tags, latf, lonf); + // } else { + tmp = new OSMNode(latf, lonf, tags, id); + + mNodeMap.put(Long.valueOf(id), tmp); + + // } + + //sink.process(new NodeContainer(tmp)); + } + } + + @Override + protected void parseWays(List ways) { + for (Osmformat.Way i : ways) { + int tagCnt = i.getKeysCount(); + TagSet tags = new TagSet(tagCnt); + + // List tags = new ArrayList(); + for (int j = 0; j < tagCnt; j++) { + tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j)))); + } + // List tags = new ArrayList(); + // for (int j = 0; j < ; j++) { + // tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j)))); + // } + + long lastId = 0; + List nodes = new ArrayList(); + for (long j : i.getRefsList()) { + OSMNode n = mNodeMap.get(Long.valueOf(j + lastId)); + if (n == null) + n = new OSMNode(Double.NaN, Double.NaN, null, j + lastId); + + nodes.add(n); + lastId = j + lastId; + } + + long id = i.getId(); + + // long id, int version, Date timestamp, OsmUser user, + // long changesetId, Collection tags, + // List wayNodes + OSMWay tmp; + // if (i.hasInfo()) { + // Osmformat.Info info = i.getInfo(); + // tmp = new Way(new CommonEntityData(id, info.getVersion(), getDate(info), + // getUser(info), info.getChangeset(), tags), nodes); + // } else { + tmp = new OSMWay(tags, id, nodes); + // } + + mWayMap.put(Long.valueOf(id), tmp); + + //sink.process(new WayContainer(tmp)); + } + } + + @Override + protected void parseRelations(List rels) { + for (Osmformat.Relation i : rels) { + int tagCnt = i.getKeysCount(); + TagSet tags = new TagSet(tagCnt); + + for (int j = 0; j < tagCnt; j++) + tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j)))); + + + long id = i.getId(); + + long lastMid = 0; + List nodes = new ArrayList(); + int memberCnt = i.getMemidsCount(); + +// for (int j = 0; j < memberCnt; j++) { +// long mid = lastMid + i.getMemids(j); +// lastMid = mid; +// String role = getStringById(i.getRolesSid(j)); +// +// Osmformat.Relation.MemberType t = i.getTypes(j); +// +// if (t == Osmformat.Relation.MemberType.NODE) { +// etype = EntityType.Node; +// } else if (t == Osmformat.Relation.MemberType.WAY) { +// etype = EntityType.Way; +// } else if (t == Osmformat.Relation.MemberType.RELATION) { +// etype = EntityType.Relation; +// } else { +// assert false; // TODO; Illegal file? +// } +// +// nodes.add(new OSMMember(mid, etype, role)); +// } + + // long id, int version, TimestampContainer timestampContainer, + // OsmUser user, + // long changesetId, Collection tags, + // List members + OSMRelation tmp = new OSMRelation(tags, id, memberCnt); + + // if (i.hasInfo()) { + // Osmformat.Info info = i.getInfo(); + // tmp = new Relation(new CommonEntityData(id, info.getVersion(), getDate(info), + // getUser(info), info.getChangeset(), tags), nodes); + // } else { + // tmp = new Relation(new CommonEntityData(id, NOVERSION, NODATE, OsmUser.NONE, + // NOCHANGESET, tags), nodes); + // } +// sink.process(new RelationContainer(tmp)); + } + } + + @Override + public void parse(Osmformat.HeaderBlock block) { + for (String s : block.getRequiredFeaturesList()) { + if (s.equals("OsmSchema-V0.6")) { + continue; // We can parse this. + } + if (s.equals("DenseNodes")) { + continue; // We can parse this. + } + throw new RuntimeException("File requires unknown feature: " + s); + } + + // if (block.hasBbox()) { + // String source = OsmosisConstants.VERSION; + // if (block.hasSource()) { + // source = block.getSource(); + // } + // + // double multiplier = .000000001; + // double rightf = block.getBbox().getRight() * multiplier; + // double leftf = block.getBbox().getLeft() * multiplier; + // double topf = block.getBbox().getTop() * multiplier; + // double bottomf = block.getBbox().getBottom() * multiplier; + // + // Bound bounds = new Bound(rightf, leftf, topf, bottomf, source); + // sink.process(new BoundContainer(bounds)); + // } + } + + public OSMData getData() { + +// for (Entry> entry : relationMembersForRelation +// .entrySet()) { +// +// OSMRelation relation = entry.getKey(); +// +// for (TmpRelation member : entry.getValue()) { +// +// OSMElement memberObject = null; +// +// if ("node".equals(member)) { +// memberObject = nodesById.get(member.id); +// } else if ("way".equals(member)) { +// memberObject = waysById.get(member.id); +// } else if ("relation".equals(member)) { +// memberObject = relationsById.get(member.id); +// } else { +// // log("missing relation " + member.id); +// continue; +// } +// +// if (memberObject != null) { +// OSMMember ownMember = new OSMMember(member.role, +// memberObject); +// +// relation.relationMembers.add(ownMember); +// } +// } +// } + + + // give up references to original collections + + ArrayList ways = new ArrayList (mWayMap.values()); + ArrayList nodes= new ArrayList (mNodeMap.values()); + + Log.d("..", "nodes: " + nodes.size() + " ways: " + ways.size()); + + return new OSMData(null, nodes, ways, null); + } +} diff --git a/src/org/oscim/utils/osmpbf/OsmPbfReader.java b/src/org/oscim/utils/osmpbf/OsmPbfReader.java new file mode 100644 index 00000000..1d14dd52 --- /dev/null +++ b/src/org/oscim/utils/osmpbf/OsmPbfReader.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013 + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.utils.osmpbf; + +import java.io.IOException; +import java.io.InputStream; + +import org.openstreetmap.osmosis.osmbinary.file.BlockInputStream; +import org.oscim.core.osm.OSMData; + +public class OsmPbfReader { + + public static OSMData process(InputStream is){ + OsmPbfParser parser = new OsmPbfParser(); + + try { + (new BlockInputStream(is, parser)).process(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + + return parser.getData(); + } +}