Initial commit.

This commit is contained in:
Mikael Capelle
2018-01-29 12:35:24 +01:00
commit 65c81b9921
34 changed files with 2193 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
package org.insa.graph.io;
import org.insa.graph.Graph;
public interface AbstractGraphReader {
/**
* Read a graph an returns it.
*
* @return Graph.
* @throws Exception
*
*/
public Graph read() throws Exception;
}

View File

@@ -0,0 +1,18 @@
package org.insa.graph.io;
import org.insa.graph.Graph;
import org.insa.graph.Path;
public interface AbstractPathReader {
/**
* Read a path of the given graph and returns it.
*
* @param graph Graph of the path.
*
* @return A new path.
* @throws Exception
*/
public Path readPath(Graph graph) throws Exception;
}

View File

@@ -0,0 +1,21 @@
package org.insa.graph.io;
import java.io.IOException;
public class BadFormatException extends IOException {
/**
*
*/
private static final long serialVersionUID = -5455552814725826052L;
/**
*
* @param actualVersion
* @param expectedVersion
*/
public BadFormatException() {
super();
}
}

View File

@@ -0,0 +1,36 @@
package org.insa.graph.io;
import java.io.IOException;
public class BadMagicNumberException extends IOException {
/**
*
*/
private static final long serialVersionUID = -2176603967548838864L;
// Actual and expected magic numbers.
private int actualNumber, expectedNumber;
/**
*
* @param actualVersion
* @param expectedVersion
*/
public BadMagicNumberException(int actualNumber, int expectedNumber) {
super();
this.actualNumber = actualNumber;
this.expectedNumber = expectedNumber;
}
/**
*
*/
public int getActualMagicNumber() { return actualNumber; }
/**
*
*/
public int getExpectedMagicNumber() { return expectedNumber; }
}

View File

@@ -0,0 +1,35 @@
package org.insa.graph.io;
import java.io.IOException;
public class BadVersionException extends IOException {
/**
*
*/
private static final long serialVersionUID = 7776317018302386042L;
// Actual and expected version..
private int actualVersion, expectedVersion;
/**
*
* @param actualVersion
* @param expectedVersion
*/
public BadVersionException(int actualVersion, int expectedVersion) {
super();
this.actualVersion = actualVersion;
this.expectedVersion = expectedVersion;
}
/**
*
*/
public int getActualVersion() { return actualVersion; }
/**
*
*/
public int getExpectedVersion() { return expectedVersion; }
}

View File

@@ -0,0 +1,176 @@
package org.insa.graph.io;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.insa.graph.Arc;
import org.insa.graph.Graph;
import org.insa.graph.Node;
import org.insa.graph.Point;
import org.insa.graph.RoadInformation;
import org.insa.graph.RoadInformation.RoadType;
public class BinaryGraphReader extends BinaryReader implements AbstractGraphReader {
// Map version and magic number targeted for this reader.
private static final int VERSION = 4;
private static final int MAGIC_NUMBER = 0xbacaff;
/**
* Convert a character to its corresponding road type.
*
* @param ch Character to convert.
*
* @return Road type corresponding to ch.
*
* @see http://wiki.openstreetmap.org/wiki/Highway_tag_usage.
*/
public static RoadType toRoadType(char ch) {
switch (ch) {
case 'a': return RoadType.MOTORWAY;
case 'b': return RoadType.TRUNK;
case 'c': return RoadType.PRIMARY;
case 'd': return RoadType.SECONDARY;
case 'e': return RoadType.MOTORWAY_LINK;
case 'f': return RoadType.TRUNK_LINK;
case 'g': return RoadType.PRIMARY_LINK;
case 'h': return RoadType.SECONDARY_LINK;
case 'i': return RoadType.TERTIARY;
case 'j': return RoadType.RESIDENTIAL;
case 'k': return RoadType.UNCLASSIFIED;
case 'l': return RoadType.ROAD;
case 'm': return RoadType.LIVING_STREET;
case 'n': return RoadType.SERVICE;
case 'o': return RoadType.ROUNDABOUT;
case 'z': return RoadType.COASTLINE;
}
return RoadType.UNCLASSIFIED;
}
/**
* Create a new BinaryGraphReader using the given DataInputStream.
*
* @param dis
*/
public BinaryGraphReader(DataInputStream dis) {
super(MAGIC_NUMBER, VERSION, dis);
}
@Override
public Graph read() throws IOException {
// Read and check magic number and file version.
checkMagicNumberOrThrow(dis.readInt());
checkVersionOrThrow(dis.readInt());
// Read map id.
int mapId = dis.readInt();
// Read zone.
int graphZone = dis.readInt();
// Number of descriptors and nodes.
int nbDesc = dis.readInt();
int nbNodes = dis.readInt();
// Number of successors for each nodes.
int[] nbSuccessors = new int[nbNodes];
// Construct an array list with initial capacity of nbNodes.
ArrayList<Node> nodes = new ArrayList<Node>(nbNodes);
// Read nodes.
for (int node = 0; node < nbNodes; ++node) {
float longitude = ((float)dis.readInt ()) / 1E6f;
float latitude = ((float)dis.readInt ()) / 1E6f;
nbSuccessors[node] = dis.readUnsignedByte();
nodes.add(new Node(node, new Point(longitude, latitude)));
}
// Check format.
checkByteOrThrow(255);
// Read descriptors.
RoadInformation[] descs = new RoadInformation[nbDesc];
// Read
for (int descr = 0; descr < nbDesc; ++descr) {
descs[descr] = readRoadInformation();
}
// Check format.
checkByteOrThrow(254);
// Read successors and convert to arcs.
for (int node = 0; node < nbNodes; ++node) {
for (int succ = 0; succ < nbSuccessors[node]; ++succ) {
// Read destination zone.
int destZone = dis.readUnsignedByte();
// Read target node number.
int destNode = this.read24bits();
// Read information number.
int descrNum = this.read24bits();
// Length of the arc.
int length = dis.readUnsignedShort();
// Number of segments.
int nbSegments = dis.readUnsignedShort();
// Chain of points corresponding to the segments.
ArrayList<Point> points = new ArrayList<Point>(nbSegments + 2);
points.add(nodes.get(node).getPoint());
for (int seg = 0; seg < nbSegments; ++seg) {
Point lastPoint = points.get(points.size() - 1);
float dlon = (dis.readShort()) / 2.0e5f;
float dlat = (dis.readShort()) / 2.0e5f;
points.add(new Point(lastPoint.getLongitude() + dlon,
lastPoint.getLatitude() + dlat));
}
points.add(nodes.get(destNode).getPoint());
if (graphZone == destZone) {
RoadInformation info = descs[descrNum];
Node orig = nodes.get(node);
Node dest = nodes.get(destNode);
// Add successor to initial arc.
orig.addSuccessor(new Arc(dest, length, info, points));
// And reverse arc if its a two-way road.
if (!info.isOneWay()) {
// Add without segments.
dest.addSuccessor(new Arc(orig, length, info));
}
}
}
}
// Check format.
checkByteOrThrow(253);
return new Graph(mapId, nodes);
}
/**
* Read the next road information from the stream.
*
* @throws IOException
*/
private RoadInformation readRoadInformation() throws IOException {
char type = (char)dis.readUnsignedByte();
int x = dis.readUnsignedByte() ;
return new RoadInformation(toRoadType(type), (x & 0x80) > 0, (x & 0x7F) * 5, dis.readUTF());
}
}

View File

@@ -0,0 +1,70 @@
package org.insa.graph.io;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.insa.graph.Graph;
import org.insa.graph.Node;
import org.insa.graph.Path;
public class BinaryPathReader extends BinaryReader implements AbstractPathReader {
// Map version and magic number targeted for this reader.
private static final int VERSION = 1;
private static final int MAGIC_NUMBER = 0xdecafe;
public BinaryPathReader(DataInputStream dis) {
super(MAGIC_NUMBER, VERSION, dis);
}
@Override
public Path readPath(Graph graph) throws Exception {
// Read and check magic number and version.
checkMagicNumberOrThrow(dis.readInt());
checkVersionOrThrow(dis.readInt());
// Read map ID and check against graph.
int mapId = dis.readInt();
if (mapId != graph.getMapId()) {
throw new MapMismatchException(mapId, graph.getMapId());
}
// Number of nodes in the path (without first and last).
int nbNodes = dis.readInt();
ArrayList<Node> nodes = new ArrayList<Node>(nbNodes + 2);
// Read first node
nodes.add(readNode(graph));
// Read last node
Node lastNode = readNode(graph);
// Read intermediate nodes:
for (int node = 0; node < nbNodes; ++node) {
nodes.add(readNode(graph));
}
// Add last node
nodes.add(lastNode);
return new Path(graph, nodes);
}
/**
* Read a node from the stream and returns id.
*
* @return
* @throws IOException
*/
protected Node readNode(Graph graph) throws IOException {
// Discard zone.
dis.readUnsignedByte();
return graph.getNodes().get(read24bits());
}
}

View File

@@ -0,0 +1,67 @@
package org.insa.graph.io;
import java.io.DataInputStream;
import java.io.IOException;
public abstract class BinaryReader {
// Map version and magic number targeted for this reader.
private int version;
private int magicNumber;
// InputStream
protected DataInputStream dis;
protected BinaryReader(int magicNumber, int version, DataInputStream dis) {
this.magicNumber = magicNumber;
this.version = version;
this.dis = dis;
}
/**
* @param version
* @throws BadVersionException
*/
public void checkVersionOrThrow(int version) throws BadVersionException {
if (this.version != version) {
throw new BadVersionException(version, this.version);
}
}
/**
* @param magicNumber
* @throws BadMagicNumberException
*/
public void checkMagicNumberOrThrow(int magicNumber) throws BadMagicNumberException {
if (this.magicNumber != magicNumber) {
throw new BadMagicNumberException(magicNumber, this.magicNumber);
}
}
/**
* Check if the next byte in the input stream correspond to the
* given byte. This function consumes the next byte in the input
* stream.
*
* @param i Byte to check against.
*
* @throws IOException
*/
public void checkByteOrThrow(int i) throws IOException {
if (dis.readUnsignedByte() != i) {
throw new BadFormatException();
}
}
/**
* Read 24 bits from the stream and return the corresponding integer value.
*
* @return Integer value read from the next 24 bits of the stream.
*
* @throws IOException
*/
protected int read24bits() throws IOException {
int x = dis.readUnsignedShort() ;
return (x << 8) | dis.readUnsignedByte() ;
}
}

View File

@@ -0,0 +1,36 @@
package org.insa.graph.io;
public class MapMismatchException extends Exception {
/**
*
*/
private static final long serialVersionUID = 3076730078387819138L;
// Actual and expected magic numbers.
private int actualMapId, expectedMapId;
/**
*
* @param actualVersion
* @param expectedVersion
*/
public MapMismatchException(int actualMapId, int expectedMapId) {
super();
this.actualMapId = actualMapId;
this.expectedMapId = expectedMapId;
}
/**
* @return
*/
public int getActualMapId() {
return actualMapId;
}
/**
* @return
*/
public int getExpectedMapId() {
return expectedMapId;
}
}