Unverified Commit 342fea6f authored by Juon Kawakami's avatar Juon Kawakami 🥗
Browse files

init

parent 54f6cedf
package maps.gml.view;
import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import maps.gml.GMLDirectedEdge;
import maps.gml.GMLEdge;
import maps.gml.GMLMap;
import maps.gml.GMLNode;
import maps.gml.GMLObject;
import maps.gml.GMLShape;
import maps.validate.ValidationError;
/**
A class for inspecting GML objects.
*/
public class GMLObjectInspector extends JPanel {
private static final int NODE_ROW_ID = 0;
private static final int NODE_ROW_X = 1;
private static final int NODE_ROW_Y = 2;
private static final int NODE_ROW_ATTACHED_EDGES = 3;
private static final int NODE_ROWS = 4;
private static final int EDGE_ROW_ID = 0;
private static final int EDGE_ROW_START = 1;
private static final int EDGE_ROW_END = 2;
private static final int EDGE_ROW_PASSABLE = 3;
private static final int EDGE_ROW_ATTACHED_SHAPES = 4;
private static final int EDGE_ROWS = 5;
private static final int SHAPE_ROW_ID = 0;
private static final int SHAPE_ROW_EDGE_COUNT = 1;
private static final int SHAPE_BASE_ROWS = 2;
private static final TableModel EMPTY_MODEL = new AbstractTableModel() {
@Override
public int getRowCount() {
return 0;
}
@Override
public int getColumnCount() {
return 0;
}
@Override
public Object getValueAt(int row, int col) {
return null;
}
};
private GMLMap map;
private JTable table;
private NodeTableModel nodeModel;
private EdgeTableModel edgeModel;
private ShapeTableModel shapeModel;
private Map<Integer, List<ValidationError>> errors;
/**
Construct a new GMLObjectInspector.
@param map The GMLMap to consult for geometry information.
*/
public GMLObjectInspector(GMLMap map) {
super(new BorderLayout());
this.map = map;
errors = new HashMap<Integer, List<ValidationError>>();
nodeModel = new NodeTableModel();
edgeModel = new EdgeTableModel();
shapeModel = new ShapeTableModel();
table = new JTable();
JScrollPane scroll = new JScrollPane(table);
add(scroll, BorderLayout.CENTER);
}
/**
Set the map this inspector should consult for geometry information.
@param newMap The new map.
*/
public void setMap(GMLMap newMap) {
map = newMap;
}
/**
Inspect a GMLNode.
@param node The node to inspect.
*/
public void inspect(GMLNode node) {
table.setModel(nodeModel);
List<ValidationError> e = (node == null) ? null : errors.get(node.getID());
nodeModel.show(node, e);
}
/**
Inspect a GMLEdge.
@param edge The edge to inspect.
*/
public void inspect(GMLEdge edge) {
table.setModel(edgeModel);
List<ValidationError> e = (edge == null) ? null : errors.get(edge.getID());
edgeModel.show(edge, e);
}
/**
Inspect a GMLShape.
@param shape The shape to inspect.
*/
public void inspect(GMLShape shape) {
table.setModel(shapeModel);
List<ValidationError> e = (shape == null) ? null : errors.get(shape.getID());
shapeModel.show(shape, e);
}
/**
Inspect a GMLObject.
@param object The object to inspect.
*/
public void inspect(GMLObject object) {
if (object == null) {
table.setModel(EMPTY_MODEL);
}
else if (object instanceof GMLNode) {
inspect((GMLNode)object);
}
else if (object instanceof GMLEdge) {
inspect((GMLEdge)object);
}
else if (object instanceof GMLShape) {
inspect((GMLShape)object);
}
else {
throw new IllegalArgumentException("Don't know how to inspect " + object);
}
}
/**
* Set the Collection of ValidationErrors for the Inspector to display in the table.
* @param err The collection of errors.
*/
public void setErrors(Collection<ValidationError> err) {
errors.clear();
for (ValidationError e : err) {
if (!errors.containsKey(e.getId())) {
errors.put(e.getId(), new ArrayList<ValidationError>());
}
errors.get(e.getId()).add(e);
}
}
private class NodeTableModel extends AbstractTableModel {
private GMLNode node;
private List<ValidationError> errors;
void show(GMLNode n, List<ValidationError> err) {
node = n;
errors = err;
fireTableDataChanged();
}
@Override
public int getRowCount() {
int errorCount = (errors == null) ? 0 : errors.size();
return NODE_ROWS + errorCount;
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Object getValueAt(int row, int col) {
if (col == 0) {
switch (row) {
case NODE_ROW_ID:
return "Node ID";
case NODE_ROW_X:
return "X";
case NODE_ROW_Y:
return "Y";
case NODE_ROW_ATTACHED_EDGES:
return "Attached edges";
default:
return "Error";
}
}
else if (col == 1) {
if (node == null) {
return null;
}
switch (row) {
case NODE_ROW_ID:
return node.getID();
case NODE_ROW_X:
return node.getX();
case NODE_ROW_Y:
return node.getY();
case NODE_ROW_ATTACHED_EDGES:
if (map == null) {
return "";
}
Collection<GMLEdge> attached = map.getAttachedEdges(node);
StringBuilder result = new StringBuilder();
for (GMLEdge next : attached) {
result.append(next.toString());
result.append(" ");
}
return result.toString();
default:
int errorCount = (errors == null) ? 0 : errors.size();
int index = row - NODE_ROWS;
if (index < 0 || index >= errorCount) {
throw new IllegalArgumentException("Invalid row: " + row);
}
return errors.get(index).getMessage();
}
}
else {
throw new IllegalArgumentException("Unrecognised column: " + col);
}
}
}
private class EdgeTableModel extends AbstractTableModel {
private GMLEdge edge;
private List<ValidationError> errors;
void show(GMLEdge e, List<ValidationError> err) {
edge = e;
errors = err;
fireTableDataChanged();
}
@Override
public int getRowCount() {
int errorCount = (errors == null) ? 0 : errors.size();
return EDGE_ROWS + errorCount;
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Object getValueAt(int row, int col) {
if (col == 0) {
switch (row) {
case EDGE_ROW_ID:
return "Edge ID";
case EDGE_ROW_START:
return "Start node";
case EDGE_ROW_END:
return "End node";
case EDGE_ROW_PASSABLE:
return "Passable";
case EDGE_ROW_ATTACHED_SHAPES:
return "Attached shapes";
default:
return "Error";
}
}
else if (col == 1) {
if (edge == null) {
return null;
}
switch (row) {
case EDGE_ROW_ID:
return edge.getID();
case EDGE_ROW_START:
return edge.getStart().getID();
case EDGE_ROW_END:
return edge.getEnd().getID();
case EDGE_ROW_PASSABLE:
return edge.isPassable();
case EDGE_ROW_ATTACHED_SHAPES:
if (map == null) {
return "";
}
Collection<GMLShape> attached = map.getAttachedShapes(edge);
StringBuilder result = new StringBuilder();
for (GMLShape next : attached) {
result.append(next.toString());
result.append(" ");
}
return result.toString();
default:
int errorCount = (errors == null) ? 0 : errors.size();
int index = row - EDGE_ROWS;
if (index < 0 || index >= errorCount) {
throw new IllegalArgumentException("Invalid row: " + row);
}
return errors.get(index).getMessage();
}
}
else {
throw new IllegalArgumentException("Unrecognised column: " + col);
}
}
}
private static class ShapeTableModel extends AbstractTableModel {
private GMLShape shape;
private List<ValidationError> errors;
void show(GMLShape s, List<ValidationError> err) {
shape = s;
errors = err;
fireTableDataChanged();
}
@Override
public int getRowCount() {
int edgeCount = (shape == null) ? 0 : shape.getEdges().size();
int errorCount = (errors == null) ? 0 : errors.size();
return SHAPE_BASE_ROWS + edgeCount + errorCount;
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Object getValueAt(int row, int col) {
if (col == 0) {
switch (row) {
case SHAPE_ROW_ID:
return "Shape ID";
case SHAPE_ROW_EDGE_COUNT:
return "Number of edges";
default:
int edgeCount = (shape == null) ? 0 : shape.getEdges().size();
if (row < SHAPE_BASE_ROWS + edgeCount) {
return "Edge " + (row - SHAPE_BASE_ROWS + 1);
}
return "Error";
}
}
else if (col == 1) {
if (shape == null) {
return null;
}
switch (row) {
case SHAPE_ROW_ID:
return shape.getID();
case SHAPE_ROW_EDGE_COUNT:
return shape.getEdges().size();
default:
int edgeCount = shape.getEdges().size();
if (row < SHAPE_BASE_ROWS + edgeCount) {
List<GMLDirectedEdge> edges = shape.getEdges();
int index = row - SHAPE_BASE_ROWS;
if (index < 0 || index >= edges.size()) {
throw new IllegalArgumentException("Invalid row: " + row);
}
return edges.get(index);
}
int errorCount = (errors == null) ? 0 : errors.size();
int index = row - SHAPE_BASE_ROWS - edgeCount;
if (index < 0 || index >= errorCount) {
throw new IllegalArgumentException("Invalid row: " + row);
}
return errors.get(index).getMessage();
}
}
else {
throw new IllegalArgumentException("Unrecognised column: " + col);
}
}
}
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLEdge;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Stroke;
import java.awt.BasicStroke;
/**
An EdgeDecorator that draws a line for each edge.
*/
public class LineEdgeDecorator implements EdgeDecorator {
private static final Stroke PASSABLE_STROKE = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);
private static final Stroke IMPASSABLE_STROKE = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);
private Color colour;
/**
Construct a LineEdgeDecorator.
@param colour The colour to draw the line.
*/
public LineEdgeDecorator(Color colour) {
this.colour = colour;
}
@Override
public void decorate(GMLEdge edge, Graphics2D g, ScreenTransform transform) {
int x1 = transform.xToScreen(edge.getStart().getX());
int y1 = transform.yToScreen(edge.getStart().getY());
int x2 = transform.xToScreen(edge.getEnd().getX());
int y2 = transform.yToScreen(edge.getEnd().getY());
g.setColor(colour);
g.setStroke(edge.isPassable() ? PASSABLE_STROKE : IMPASSABLE_STROKE);
g.drawLine(x1, y1, x2, y2);
}
}
\ No newline at end of file
package maps.gml.view;
import java.awt.Graphics2D;
import java.awt.Color;
import rescuecore2.misc.gui.ScreenTransform;
import rescuecore2.misc.geometry.Point2D;
/**
A line overlay.
*/
public class LineOverlay implements Overlay {
private Point2D start;
private Point2D end;
private Color colour;
private boolean useWorldCoords;
/**
Construct a LineOverlay with no coordinates defined..
@param colour The colour to draw the rectangle.
@param useWorldCoords Whether to convert the coordinates from world to screen. Set to false if you want to directly specify screen coordinates.
*/
public LineOverlay(Color colour, boolean useWorldCoords) {
this(null, null, colour, useWorldCoords);
}
/**
Construct a LineOverlay.
@param start The start coordinate.
@param end The end coordinate.
@param colour The colour to draw the rectangle.
@param useWorldCoords Whether to convert the coordinates from world to screen. Set to false if you want to directly specify screen coordinates.
*/
public LineOverlay(Point2D start, Point2D end, Color colour, boolean useWorldCoords) {
this.start = start;
this.end = end;
this.colour = colour;
this.useWorldCoords = useWorldCoords;
}
/**
Set the start coordinate.
@param p The new start coordinate.
*/
public void setStart(Point2D p) {
start = p;
}
/**
Set the end coordinate.
@param p The new end coordinate.
*/
public void setEnd(Point2D p) {
end = p;
}
/**
Set the colour.
@param c The new colour.
*/
public void setColour(Color c) {
colour = c;
}
/**
Set whether to use world coordinates or not. If true, the coordinates will be converted to screen coordinates; if false the coordinates will be used as given.
@param b True to use world coordinates, false otherwise.
*/
public void setUseWorldCoordinates(boolean b) {
useWorldCoords = b;
}
@Override
public void render(Graphics2D g, ScreenTransform transform) {
if (start == null || end == null) {
return;
}
Graphics2D graphics = (Graphics2D)g.create();
graphics.setColor(colour);
double x1 = start.getX();
double x2 = end.getX();
double y1 = start.getY();
double y2 = end.getY();
if (useWorldCoords) {
x1 = transform.xToScreen(x1);
x2 = transform.xToScreen(x2);
/*
double temp = transform.yToScreen(y2);
y2 = transform.yToScreen(y1);
y1 = temp;
*/
y1 = transform.yToScreen(y1);
y2 = transform.yToScreen(y2);
}
graphics.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
}
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLNode;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
/**
Interface for objects that know how to decorate GMLNodes.
*/
public interface NodeDecorator {
/**
Decorate a GMLNode.
@param node The node to decorate.
@param g The graphics to draw on.
@param transform The screen transform.
*/
void decorate(GMLNode node, Graphics2D g, ScreenTransform transform);
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLBuilding;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
/**
A no-op BuildingDecorator.
*/
public class NullBuildingDecorator implements BuildingDecorator {
@Override
public void decorate(GMLBuilding building, Graphics2D g, ScreenTransform transform) {
}
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLEdge;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
/**
A no-op EdgeDecorator.
*/
public class NullEdgeDecorator implements EdgeDecorator {
@Override
public void decorate(GMLEdge edge, Graphics2D g, ScreenTransform transform) {
}
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLNode;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
/**
A no-op NodeDecorator.
*/
public class NullNodeDecorator implements NodeDecorator {
@Override
public void decorate(GMLNode node, Graphics2D g, ScreenTransform transform) {
}
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLRoad;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
/**
A no-op RoadDecorator.
*/
public class NullRoadDecorator implements RoadDecorator {
@Override
public void decorate(GMLRoad road, Graphics2D g, ScreenTransform transform) {
}
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLSpace;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
/**
A no-op SpaceDecorator.
*/
public class NullSpaceDecorator implements SpaceDecorator {
@Override
public void decorate(GMLSpace space, Graphics2D g, ScreenTransform transform) {
}
}
\ No newline at end of file
package maps.gml.view;
import java.awt.Graphics2D;
import rescuecore2.misc.gui.ScreenTransform;
/**
Interface for overlays that appear on the GML map viewer.
*/
public interface Overlay {
/**
Render this overlay.
@param g The graphics to draw on.
@param transform The current screen transform.
*/
void render(Graphics2D g, ScreenTransform transform);
}
\ No newline at end of file
package maps.gml.view;
import java.awt.Graphics2D;
import java.awt.Color;
import rescuecore2.misc.gui.ScreenTransform;
/**
A rectangular overlay.
*/
public class RectangleOverlay implements Overlay {
private double left;
private double right;
private double bottom;
private double top;
private Color colour;
private boolean useWorldCoords;
/**
Construct a RectangleOverlay with no coordinates defined..
@param colour The colour to draw the rectangle.
@param useWorldCoords Whether to convert the coordinates from world to screen. Set to false if you want to directly specify screen coordinates.
*/
public RectangleOverlay(Color colour, boolean useWorldCoords) {
this(Double.NaN, Double.NaN, Double.NaN, Double.NaN, colour, useWorldCoords);
}
/**
Construct a RectangleOverlay.
@param left The left-hand X coordinate.
@param right The right-hand X coordinate.
@param top The top Y coordinate.
@param bottom The bottom Y coordinate.
@param colour The colour to draw the rectangle.
@param useWorldCoords Whether to convert the coordinates from world to screen. Set to false if you want to directly specify screen coordinates.
*/
public RectangleOverlay(double left, double right, double top, double bottom, Color colour, boolean useWorldCoords) {
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
this.colour = colour;
this.useWorldCoords = useWorldCoords;
}
/**
Set the left-hand X coordinate.
@param x The new coordinate.
*/
public void setLeft(double x) {
left = x;
}
/**
Set the right-hand X coordinate.
@param x The new coordinate.
*/
public void setRight(double x) {
right = x;
}
/**
Set the top Y coordinate.
@param y The new coordinate.
*/
public void setTop(double y) {
top = y;
}
/**
Set the bottom Y coordinate.
@param y The new coordinate.
*/
public void setBottom(double y) {
bottom = y;
}
/**
Set the colour.
@param c The new colour.
*/
public void setColour(Color c) {
colour = c;
}
/**
Set whether to use world coordinates or not. If true, the coordinates will be converted to screen coordinates; if false the coordinates will be used as given.
@param b True to use world coordinates, false otherwise.
*/
public void setUseWorldCoordinates(boolean b) {
useWorldCoords = b;
}
@Override
public void render(Graphics2D g, ScreenTransform transform) {
if (Double.isNaN(left) || Double.isNaN(right) || Double.isNaN(top) || Double.isNaN(bottom)) {
return;
}
Graphics2D graphics = (Graphics2D)g.create();
graphics.setColor(colour);
double x1 = left < right ? left : right;
double x2 = left < right ? right : left;
double y1 = bottom < top ? bottom : top;
double y2 = bottom < top ? top : bottom;
if (useWorldCoords) {
x1 = transform.xToScreen(x1);
x2 = transform.xToScreen(x2);
double temp = transform.yToScreen(y2);
y2 = transform.yToScreen(y1);
y1 = temp;
}
graphics.fillRect((int)x1, (int)y1, (int)(x2 - x1), (int)(y2 - y1));
}
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLRoad;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
/**
Interface for objects that know how to decorate GMLRoads.
*/
public interface RoadDecorator {
/**
Decorate a GMLRoad.
@param road The road to decorate.
@param g The graphics to draw on.
@param transform The screen transform.
*/
void decorate(GMLRoad road, Graphics2D g, ScreenTransform transform);
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLSpace;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
/**
Interface for objects that know how to decorate GMLSpaces.
*/
public interface SpaceDecorator {
/**
Decorate a GMLSpace.
@param space The space to decorate.
@param g The graphics to draw on.
@param transform The screen transform.
*/
void decorate(GMLSpace space, Graphics2D g, ScreenTransform transform);
}
\ No newline at end of file
package maps.gml.view;
import maps.gml.GMLNode;
import rescuecore2.misc.gui.ScreenTransform;
import java.awt.Graphics2D;
import java.awt.Color;
/**
A NodeDecorator that draws a square for each node.
*/
public class SquareNodeDecorator implements NodeDecorator {
private Color colour;
private int size;
/**
Construct a SquareNodeDecorator.
@param colour The colour to draw the square.
@param size The size of the square.
*/
public SquareNodeDecorator(Color colour, int size) {
this.colour = colour;
this.size = size;
}
@Override
public void decorate(GMLNode node, Graphics2D g, ScreenTransform transform) {
int x = transform.xToScreen(node.getX());
int y = transform.yToScreen(node.getY());
g.setColor(colour);
g.fillRect(x - (size / 2), y - (size / 2), size + 1, size + 1);
}
}
\ No newline at end of file
package maps.legacy;
import static rescuecore2.misc.EncodingTools.readInt32LE;
import static rescuecore2.misc.EncodingTools.reallySkip;
import java.io.InputStream;
import java.io.IOException;
/**
A legacy building.
*/
public class LegacyBuilding extends LegacyObject {
private int floors;
private int code;
private int[] entrances;
private int[] apexes;
@Override
public void read(InputStream in) throws IOException {
// CHECKSTYLE:OFF:MagicNumber
// Skip size
reallySkip(in, 4);
id = readInt32LE(in);
x = readInt32LE(in);
y = readInt32LE(in);
floors = readInt32LE(in);
// Skip attributes, ignition, fieryness, brokenness - 4 * 4 bytes
reallySkip(in, 16);
int numEntrances = readInt32LE(in);
entrances = new int[numEntrances];
for (int j = 0; j < numEntrances; ++j) {
entrances[j] = readInt32LE(in);
}
// Skip shapeID, ground area, total read - 3 * 4 bytes
reallySkip(in, 12);
code = readInt32LE(in);
int numApexes = readInt32LE(in);
apexes = new int[numApexes * 2];
for (int j = 0; j < numApexes; ++j) {
// Apexes
apexes[j * 2] = readInt32LE(in);
apexes[j * 2 + 1] = readInt32LE(in);
}
// CHECKSTYLE:ON:MagicNumber
}
/**
Get the number of floors in this building.
@return The number of floors.
*/
public int getFloors() {
return floors;
}
/**
Get the building code.
@return The building code.
*/
public int getCode() {
return code;
}
/**
Get the list of entrance nodes.
@return The entrances.
*/
public int[] getEntrances() {
return entrances;
}
/**
Get the list of apexes.
@return The apex list.
*/
public int[] getApexes() {
return apexes;
}
}
\ No newline at end of file
package maps.legacy;
import static rescuecore2.misc.EncodingTools.readInt32LE;
import static rescuecore2.misc.EncodingTools.reallySkip;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.util.Collection;
import java.util.Collections;
import rescuecore2.log.Logger;
/**
A legacy (version 0) RoboCup Rescue map.
*/
public class LegacyMap implements maps.Map {
private Map<Integer, LegacyNode> nodes;
private Map<Integer, LegacyRoad> roads;
private Map<Integer, LegacyBuilding> buildings;
/**
Construct an empty map.
*/
public LegacyMap() {
nodes = new HashMap<Integer, LegacyNode>();
roads = new HashMap<Integer, LegacyRoad>();
buildings = new HashMap<Integer, LegacyBuilding>();
}
/**
Construct a map and read from a directory.
@param baseDir The map directory.
@throws IOException If there is a problem reading the map.
*/
public LegacyMap(File baseDir) throws IOException {
this();
read(baseDir);
}
/**
Read map data from a directory.
@param baseDir The map directory.
@throws IOException If there is a problem reading the map.
*/
public void read(File baseDir) throws IOException {
nodes.clear();
roads.clear();
buildings.clear();
readNodes(baseDir);
readRoads(baseDir);
readBuildings(baseDir);
}
/**
Get all roads.
@return All roads.
*/
public Collection<LegacyRoad> getRoads() {
return Collections.unmodifiableCollection(roads.values());
}
/**
Get a road by ID.
@param id The ID to look up.
@return The road with the given ID or null if no such road exists.
*/
public LegacyRoad getRoad(int id) {
return roads.get(id);
}
/**
Get all nodes.
@return All nodes.
*/
public Collection<LegacyNode> getNodes() {
return Collections.unmodifiableCollection(nodes.values());
}
/**
Get a node by ID.
@param id The ID to look up.
@return The node with the given ID or null if no such node exists.
*/
public LegacyNode getNode(int id) {
return nodes.get(id);
}
/**
Get all buildings.
@return All buildings.
*/
public Collection<LegacyBuilding> getBuildings() {
return Collections.unmodifiableCollection(buildings.values());
}
/**
Get a building by ID.
@param id The ID to look up.
@return The building with the given ID or null if no such building exists.
*/
public LegacyBuilding getBuilding(int id) {
return buildings.get(id);
}
private void readNodes(File baseDir) throws IOException {
File f = new File(baseDir, "node.bin");
InputStream in = new FileInputStream(f);
// CHECKSTYLE:OFF:MagicNumber
reallySkip(in, 12);
// CHECKSTYLE:ON:MagicNumber
int num = readInt32LE(in);
Logger.debug("Reading " + num + " nodes");
for (int i = 0; i < num; ++i) {
LegacyNode node = new LegacyNode();
node.read(in);
nodes.put(node.getID(), node);
}
}
private void readRoads(File baseDir) throws IOException {
File f = new File(baseDir, "road.bin");
InputStream in = new FileInputStream(f);
// CHECKSTYLE:OFF:MagicNumber
reallySkip(in, 12);
// CHECKSTYLE:ON:MagicNumber
int num = readInt32LE(in);
Logger.debug("Reading " + num + " roads");
for (int i = 0; i < num; ++i) {
LegacyRoad road = new LegacyRoad();
road.read(in);
roads.put(road.getID(), road);
}
}
private void readBuildings(File baseDir) throws IOException {
File f = new File(baseDir, "building.bin");
InputStream in = new FileInputStream(f);
// CHECKSTYLE:OFF:MagicNumber
reallySkip(in, 12);
// CHECKSTYLE:ON:MagicNumber
int num = readInt32LE(in);
Logger.debug("Reading " + num + " buildings");
for (int i = 0; i < num; ++i) {
LegacyBuilding building = new LegacyBuilding();
building.read(in);
buildings.put(building.getID(), building);
}
}
}
\ No newline at end of file
package maps.legacy;
import maps.Map;
import maps.MapFormat;
import maps.MapException;
import java.io.File;
import java.io.IOException;
/**
MapFormat for legacy maps.
*/
public final class LegacyMapFormat implements MapFormat {
/** Singleton instance. */
public static final LegacyMapFormat INSTANCE = new LegacyMapFormat();
private LegacyMapFormat() {}
@Override
public LegacyMap read(File file) throws MapException {
try {
return new LegacyMap(file);
}
catch (IOException e) {
throw new MapException(e);
}
}
@Override
public void write(Map map, File file) throws MapException {
throw new RuntimeException("LegacyMapFormat.write not implemented");
}
@Override
public boolean canRead(File file) throws MapException {
if (!file.exists() || !file.isDirectory()) {
return false;
}
// Look for road.bin, node.bin and building.bin files
File road = new File(file, "road.bin");
File node = new File(file, "node.bin");
File building = new File(file, "building.bin");
return road.exists() && node.exists() && building.exists();
}
}
package maps.legacy;
import static rescuecore2.misc.EncodingTools.readInt32LE;
import static rescuecore2.misc.EncodingTools.reallySkip;
import java.io.InputStream;
import java.io.IOException;
/**
A legacy node.
*/
public class LegacyNode extends LegacyObject {
private int[] edges;
@Override
public void read(InputStream in) throws IOException {
// CHECKSTYLE:OFF:MagicNumber
// Skip size
reallySkip(in, 4);
id = readInt32LE(in);
x = readInt32LE(in);
y = readInt32LE(in);
int numEdges = readInt32LE(in);
edges = new int[numEdges];
for (int j = 0; j < numEdges; ++j) {
edges[j] = readInt32LE(in);
}
// Skip signal flag, timing, pocket to turn across, shortcut to turn
reallySkip(in, (numEdges * 6 + 1) * 4);
// CHECKSTYLE:ON:MagicNumber
}
/**
Get the list of edges, i.e. roads and buildings adjacent to this node.
@return The edge list.
*/
public int[] getEdges() {
return edges;
}
}
\ No newline at end of file
package maps.legacy;
import java.io.InputStream;
import java.io.IOException;
/**
Abstract base class for legacy objects.
*/
public abstract class LegacyObject {
/** The ID of this object. */
protected int id;
/** The X coordinate. */
protected int x;
/** The Y coordinate. */
protected int y;
/**
Read the data for this object.
@param in The InputStream to read.
@throws IOException If there is a problem reading the stream.
*/
public abstract void read(InputStream in) throws IOException;
/**
Get the ID of this object.
@return The object ID.
*/
public int getID() {
return id;
}
/**
Get the X coordinate.
@return The X coordinate.
*/
public int getX() {
return x;
}
/**
Get the Y coordinate.
@return The Y coordinate.
*/
public int getY() {
return y;
}
}
\ No newline at end of file
package maps.legacy;
import static rescuecore2.misc.EncodingTools.readInt32LE;
import static rescuecore2.misc.EncodingTools.reallySkip;
import java.io.InputStream;
import java.io.IOException;
/**
A legacy road.
*/
public class LegacyRoad extends LegacyObject {
private int head;
private int tail;
private int length;
private int width;
@Override
public void read(InputStream in) throws IOException {
// CHECKSTYLE:OFF:MagicNumber
// Skip size
reallySkip(in, 4);
id = readInt32LE(in);
head = readInt32LE(in);
tail = readInt32LE(in);
length = readInt32LE(in);
// Skip roadkind, cars/humans to head/tail - 5 * 4 bytes
reallySkip(in, 20);
width = readInt32LE(in);
// Skip block, repaircost, median, lines to head/tail, width for walkers - 6 * 4 bytes
reallySkip(in, 24);
// CHECKSTYLE:ON:MagicNumber
}
/**
Get the ID of the head node.
@return The head node id.
*/
public int getHead() {
return head;
}
/**
Get the ID of the tail node.
@return The tail node id.
*/
public int getTail() {
return tail;
}
/**
Get the length of this road in mm.
@return The length.
*/
public int getLength() {
return length;
}
/**
Get the width of this road in mm.
@return The width.
*/
public int getWidth() {
return width;
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment