/**************************************************************************
OSMemory library for OSM data processing.
Copyright (C) 2014 Aleś Bułojčyk <alex73mail@gmail.com>
This is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This software 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
package org.alex73.osmemory;
import java.io.File;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.openstreetmap.osmosis.core.container.v0_6.EntityContainer;
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.Relation;
import org.openstreetmap.osmosis.core.domain.v0_6.RelationMember;
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 org.openstreetmap.osmosis.core.task.v0_6.Sink;
import org.openstreetmap.osmosis.pbf2.v0_6.PbfReader;
import com.vividsolutions.jts.geom.Envelope;
/**
* This class reads pbf file using osmosis library and stores all data into MemoryStorage.
*/
public class PBFReader extends BaseReader {
public static final Charset UTF8 = Charset.forName("UTF-8");
public static void main(String[] aa) throws Exception {
MemoryStorage storage = new PBFReader().read(new File("tmp/belarus-updated.osm.pbf"));
storage.showStat();
}
public PBFReader() {
super(null);
}
public PBFReader(Envelope cropBox) {
super(cropBox);
}
public synchronized MemoryStorage read(File pbf) throws Exception {
PbfReader rd = new PbfReader(pbf, 1);
rd.setSink(new Sink() {
@Override
public void initialize(Map<String, Object> arg0) {
}
@Override
public void process(EntityContainer arg0) {
Entity e = arg0.getEntity();
switch (e.getType()) {
case Node:
IOsmNode n = createNode((Node) e);
if (n != null) {
storage.nodes.add(n);
}
break;
case Way:
storage.ways.add(createWay((Way) e));
break;
case Relation:
storage.relations.add(createRelation((Relation) e));
break;
case Bound:
break;
}
}
@Override
public void complete() {
}
@Override
public void release() {
}
});
rd.run();
storage.finishLoading();
return storage;
}
void applyTags(Collection<Tag> tags, OsmBase obj) {
if (tags.isEmpty()) {
return;
}
int i = 0;
for (Tag t : tags) {
obj.tagKeys[i] = storage.getTagsPack().getTagCode(t.getKey());
obj.tagValues[i] = t.getValue().getBytes(UTF8);
i++;
}
}
OsmNode createNode(Node in) {
long lat = Math.round(in.getLatitude() / OsmNode.DIVIDER);
if (lat >= Integer.MAX_VALUE || lat <= Integer.MIN_VALUE) {
throw new RuntimeException("Wrong value for latitude: " + lat);
}
long lon = Math.round(in.getLongitude() / OsmNode.DIVIDER);
if (lon >= Integer.MAX_VALUE || lon <= Integer.MIN_VALUE) {
throw new RuntimeException("Wrong value for longitude: " + lon);
}
int intLon = (int) lon;
int intLat = (int) lat;
if (!isInsideCropBox(intLat, intLon)) {
return null;
}
if (in.getTags().isEmpty()) {
if (storage.simpleNodeCount >= storage.simpleNodeIds.length) {
// extend
storage.simpleNodeIds = Arrays.copyOf(storage.simpleNodeIds,
storage.simpleNodeIds.length + 1024 * 1024);
storage.simpleNodeLats = Arrays.copyOf(storage.simpleNodeLats,
storage.simpleNodeLats.length + 1024 * 1024);
storage.simpleNodeLons = Arrays.copyOf(storage.simpleNodeLons,
storage.simpleNodeLons.length + 1024 * 1024);
}
int p = storage.simpleNodeCount++;
storage.simpleNodeIds[p] = in.getId();
storage.simpleNodeLats[p] = intLat;
storage.simpleNodeLons[p] = intLon;
return null;
} else {
OsmNode result = new OsmNode(in.getId(), in.getTags().size(), intLat, intLon);
applyTags(in.getTags(), result);
return result;
}
}
OsmWay createWay(Way in) {
List<WayNode> wayNodes = in.getWayNodes();
long[] nodes = new long[wayNodes.size()];
for (int i = 0; i < wayNodes.size(); i++) {
nodes[i] = wayNodes.get(i).getNodeId();
}
OsmWay result = new OsmWay(in.getId(), in.getTags().size(), nodes);
applyTags(in.getTags(), result);
return result;
}
OsmRelation createRelation(Relation in) {
List<RelationMember> inMembers = in.getMembers();
OsmRelation result = new OsmRelation(in.getId(), in.getTags().size(), inMembers.size());
applyTags(in.getTags(), result);
// apply members
for (int i = 0; i < inMembers.size(); i++) {
RelationMember m = inMembers.get(i);
switch (m.getMemberType()) {
case Node:
result.memberTypes[i] = IOsmObject.TYPE_NODE;
break;
case Way:
result.memberTypes[i] = IOsmObject.TYPE_WAY;
break;
case Relation:
result.memberTypes[i] = IOsmObject.TYPE_RELATION;
break;
default:
throw new RuntimeException("Unknown relation member type: " + m.getMemberType());
}
result.memberRoles[i] = storage.getRelationRolesPack().getTagCode(m.getMemberRole());
result.memberIDs[i] = m.getMemberId();
}
return result;
}
}