All Downloads are FREE. Search and download functionalities are using the official Maven repository.

crosby.binary.OsmObjectFactory Maven / Gradle / Ivy

The newest version!
package crosby.binary;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.osmtools.pbf.data.MemberType;
import org.osmtools.pbf.data.Node;
import org.osmtools.pbf.data.Relation;
import org.osmtools.pbf.data.RelationMember;
import org.osmtools.pbf.data.Tag;
import org.osmtools.pbf.data.Way;

import crosby.binary.Osmformat.DenseInfo;

public class OsmObjectFactory {

	private int granularity;
	private long latOffset;
	private long lonOffset;
	private int dateGranularity;
	private String strings[];

	public OsmObjectFactory(int granularity, long latOffset, long lonOffset, int dateGranularity, String[] strings) {
		this.granularity = granularity;
		this.latOffset = latOffset;
		this.lonOffset = lonOffset;
		this.dateGranularity = dateGranularity;
		this.strings = strings;
	}

	/**
	 * Get a string based on the index used.
	 * 
	 * Index 0 is reserved to use as a delimiter, therefore, index 1 corresponds to the first string in the table
	 * 
	 * @param id
	 * @return
	 */
	private String getStringById(int id) {
		return strings[id];
	}

	/**
	 * Convert a latitude value stored in a protobuf into a double, compensating for granularity and latitude offset
	 */
	private double parseLat(long degree) {
		// Support non-zero offsets. (We don't currently generate them)
		return (granularity * degree + latOffset) * .000000001;
	}

	/**
	 * Convert a longitude value stored in a protobuf into a double, compensating for granularity and longitude offset
	 */
	private double parseLon(long degree) {
		// Support non-zero offsets. (We don't currently generate them)
		return (granularity * degree + lonOffset) * .000000001;
	}

	private OsmInfo createOsmInfo(boolean hasOsmInfo, Osmformat.Info info) {
		OsmInfoReader osmInfoReader = hasOsmInfo ? new OsmInfoReader(info, dateGranularity) : new OsmInfoReader();
		String userName = osmInfoReader.hasValidUserId() ? getStringById(osmInfoReader.getUserSid()) : "";
		return new OsmInfo(osmInfoReader.getVersion(), osmInfoReader.getChangeset(), userName, osmInfoReader.getDate());
	}

	public Node createNode(Osmformat.Node pbfNode) {
		OsmInfo osmInfo = createOsmInfo(pbfNode.hasInfo(), pbfNode.getInfo());

		List tags = new ArrayList();
		for (int j = 0; j < pbfNode.getKeysCount(); j++) {
			tags.add(new Tag(getStringById(pbfNode.getKeys(j)), getStringById(pbfNode.getVals(j))));
		}

		long id = pbfNode.getId();
		double latf = parseLat(pbfNode.getLat());
		double lonf = parseLon(pbfNode.getLon());

		return new Node(id, osmInfo.getVersion(), osmInfo.getChangesetId(), osmInfo.getTimestamp(),
				osmInfo.getUsername(), tags, latf, lonf);
	}

	public List createNodes(Osmformat.DenseNodes pbfNodes) {
		List nodes = new ArrayList();
		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 (pbfNodes.hasDenseinfo()) {
			di = pbfNodes.getDenseinfo();
		}
		for (int nodeCount = 0; nodeCount < pbfNodes.getIdCount(); nodeCount++) {
			List tags = new ArrayList(0);
			long lat = pbfNodes.getLat(nodeCount) + lastLat;
			lastLat = lat;
			long lon = pbfNodes.getLon(nodeCount) + lastLon;
			lastLon = lon;
			long id = pbfNodes.getId(nodeCount) + lastId;
			lastId = id;
			double latf = parseLat(lat), lonf = parseLon(lon);
			// If empty, assume that nothing here has keys or vals.
			if (pbfNodes.getKeysValsCount() > 0) {
				while (pbfNodes.getKeysVals(j) != 0) {
					int keyid = pbfNodes.getKeysVals(j++);
					int valid = pbfNodes.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(nodeCount) + lastuid;
				lastuid = uid;
				int userSid = di.getUserSid(nodeCount) + lastuserSid;
				lastuserSid = userSid;
				long timestamp = di.getTimestamp(nodeCount) + lasttimestamp;
				lasttimestamp = timestamp;
				int version = di.getVersion(nodeCount);
				long changeset = di.getChangeset(nodeCount) + lastchangeset;
				lastchangeset = changeset;

				Date date = new Date(dateGranularity * timestamp);

				String user;
				if (uid < 0) {
					user = "";
				}
				else {
					user = getStringById(userSid);
				}
				nodes.add(new Node(id, version, changeset, date, user, tags, latf, lonf));
			}
			else {
				nodes.add(new Node(id, -1, -1, new Date(-1), "", tags, latf, lonf));
			}
		}

		return nodes;
	}

	public Way createWay(Osmformat.Way pbfWay) {
		OsmInfo osmInfo = createOsmInfo(pbfWay.hasInfo(), pbfWay.getInfo());

		List tags = new ArrayList();
		for (int j = 0; j < pbfWay.getKeysCount(); j++) {
			tags.add(new Tag(getStringById(pbfWay.getKeys(j)), getStringById(pbfWay.getVals(j))));
		}

		long lastId = 0;
		List nodes = new ArrayList();
		for (long ref : pbfWay.getRefsList()) {
			long nodeId = ref + lastId;
			nodes.add(Long.valueOf(nodeId));
			lastId = nodeId;
		}

		long id = pbfWay.getId();

		return new Way(id, osmInfo.getVersion(), osmInfo.getChangesetId(), osmInfo.getTimestamp(),
				osmInfo.getUsername(), tags, nodes);
	}

	public Relation createRelation(Osmformat.Relation pbfRelation) {
		OsmInfo osmInfo = createOsmInfo(pbfRelation.hasInfo(), pbfRelation.getInfo());

		List tags = new ArrayList();
		for (int j = 0; j < pbfRelation.getKeysCount(); j++) {
			tags.add(new Tag(getStringById(pbfRelation.getKeys(j)), getStringById(pbfRelation.getVals(j))));
		}

		long id = pbfRelation.getId();
		List members = convertMembers(pbfRelation);
		Relation relation = new Relation(id, osmInfo.getVersion(), osmInfo.getChangesetId(), osmInfo.getTimestamp(),
				osmInfo.getUsername(), tags, members);
		return relation;
	}

	private List convertMembers(Osmformat.Relation pbfRelation) {
		long lastMid = 0;
		List nodes = new ArrayList();
		for (int j = 0; j < pbfRelation.getMemidsCount(); j++) {
			long mid = lastMid + pbfRelation.getMemids(j);
			lastMid = mid;
			String role = getStringById(pbfRelation.getRolesSid(j));
			MemberType memberType = decideMemberType(pbfRelation.getTypes(j));
			nodes.add(new RelationMember(mid, role, memberType));
		}
		return nodes;
	}

	private MemberType decideMemberType(Osmformat.Relation.MemberType memberType) {
		MemberType etype = null;

		if (memberType == Osmformat.Relation.MemberType.NODE) {
			etype = MemberType.NODE;
		}
		else if (memberType == Osmformat.Relation.MemberType.WAY) {
			etype = MemberType.WAY;
		}
		else if (memberType == Osmformat.Relation.MemberType.RELATION) {
			etype = MemberType.RELATION;
		}
		else {
			assert false; // TODO; Illegal file?
		}
		return etype;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy