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

init

parent 54f6cedf
package maps.gml;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Collections;
import java.awt.geom.Rectangle2D;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.misc.geometry.GeometryTools2D;
/**
Abstract base class for shapes in GML space.
*/
public abstract class GMLShape extends GMLObject {
private List<GMLDirectedEdge> edges;
private Map<GMLDirectedEdge, Integer> neighbours;
private List<GMLCoordinates> points;
private Rectangle2D bounds;
private Point2D centroid;
/**
Construct a GMLShape.
@param id The ID of the shape.
*/
protected GMLShape(int id) {
super(id);
this.edges = new ArrayList<GMLDirectedEdge>();
neighbours = new HashMap<GMLDirectedEdge, Integer>();
bounds = null;
centroid = null;
}
/**
Construct a GMLShape.
@param id The ID of the shape.
@param edges The edges of the shape.
*/
protected GMLShape(int id, List<GMLDirectedEdge> edges) {
this(id);
this.edges.addAll(edges);
points = getUnderlyingCoordinates();
}
/**
Construct a GMLShape.
@param id The ID of the shape.
@param edges The edges of the shape.
@param neighbours The neighbours of each edge.
*/
protected GMLShape(int id, List<GMLDirectedEdge> edges, List<Integer> neighbours) {
this(id, edges);
Iterator<GMLDirectedEdge> it = edges.iterator();
Iterator<Integer> ix = neighbours.iterator();
while (it.hasNext() && ix.hasNext()) {
setNeighbour(it.next(), ix.next());
}
points = getUnderlyingCoordinates();
}
/**
Get the edges of this shape.
@return The edges.
*/
public List<GMLDirectedEdge> getEdges() {
return new ArrayList<GMLDirectedEdge>(edges);
}
/**
Set the list of edges.
@param newEdges The new edge list.
*/
public void setEdges(List<GMLDirectedEdge> newEdges) {
edges.clear();
neighbours.clear();
edges.addAll(newEdges);
bounds = null;
centroid = null;
points = getUnderlyingCoordinates();
}
/**
Reorder the list of edges. This will not clear the neighbour map or the bounds.
@param newEdges The reordered edge list.
*/
public void reorderEdges(List<GMLDirectedEdge> newEdges) {
edges.clear();
edges.addAll(newEdges);
points = getUnderlyingCoordinates();
centroid = null;
neighbours.keySet().retainAll(newEdges);
}
/**
Replace a GMLDirectedEdge with a set of new edges. The neighbour of the old edge will be set for each of the new edges.
@param oldEdge The edge to replace.
@param newEdges The new edges.
*/
public void replaceEdge(GMLDirectedEdge oldEdge, GMLDirectedEdge... newEdges) {
ListIterator<GMLDirectedEdge> it = edges.listIterator();
while (it.hasNext()) {
if (it.next() == oldEdge) {
it.remove();
for (GMLDirectedEdge e : newEdges) {
it.add(e);
}
}
}
bounds = null;
centroid = null;
points = getUnderlyingCoordinates();
}
/**
Remove an edge from this shape.
@param edge The underlying edge to remove.
*/
public void removeEdge(GMLEdge edge) {
for (Iterator<GMLDirectedEdge> it = edges.iterator(); it.hasNext();) {
GMLDirectedEdge dEdge = it.next();
if (dEdge.getEdge().equals(edge)) {
it.remove();
neighbours.remove(dEdge);
}
}
bounds = null;
centroid = null;
points = getUnderlyingCoordinates();
}
/**
Get the ID of the neighbour through a particular edge.
@param edge The edge to look up.
@return The ID of the neighbour through that edge or null.
*/
public Integer getNeighbour(GMLDirectedEdge edge) {
return neighbours.get(edge);
}
/**
Set the ID of the neighbour through a particular edge.
@param edge The edge to set the neighbour of.
@param neighbour The new neighbour ID for that edge. This may be null.
*/
public void setNeighbour(GMLDirectedEdge edge, Integer neighbour) {
if (neighbour == null) {
neighbours.remove(edge);
}
else {
neighbours.put(edge, neighbour);
}
}
/**
Find out if an edge has a neighbour.
@param edge The edge to look up.
@return True if there is a neighbour through that edge or false otherwise.
*/
public boolean hasNeighbour(GMLDirectedEdge edge) {
return neighbours.containsKey(edge);
}
/**
Get the ID of the neighbour through a particular edge.
@param edge The edge to look up.
@return The ID of the neighbour through that edge or null.
*/
public Integer getNeighbour(GMLEdge edge) {
return getNeighbour(findDirectedEdge(edge));
}
/**
Set the ID of the neighbour through a particular edge.
@param edge The edge to set the neighbour of.
@param neighbour The new neighbour ID for that edge. This may be null.
*/
public void setNeighbour(GMLEdge edge, Integer neighbour) {
setNeighbour(findDirectedEdge(edge), neighbour);
}
/**
Find out if an edge has a neighbour.
@param edge The edge to look up.
@return True if there is a neighbour through that edge or false otherwise.
*/
public boolean hasNeighbour(GMLEdge edge) {
return neighbours.containsKey(findDirectedEdge(edge));
}
/**
Get the coordinates of the edges that make up this shape.
@return The underlying edge coordinates.
*/
public List<GMLCoordinates> getUnderlyingCoordinates() {
List<GMLCoordinates> result = new ArrayList<GMLCoordinates>();
for (GMLDirectedEdge next : edges) {
result.add(next.getStartCoordinates());
}
return result;
}
/**
Get the nodes of the edges that make up this shape.
@return The underlying nodes.
*/
public List<GMLNode> getUnderlyingNodes() {
List<GMLNode> result = new ArrayList<GMLNode>();
for (GMLDirectedEdge next : edges) {
result.add(next.getStartNode());
}
return result;
}
/**
Get the coordinates of the apexes of this shape.
@return The apex coordinates.
*/
public List<GMLCoordinates> getCoordinates() {
return Collections.unmodifiableList(points);
}
/**
Set the coordinates of the apexes of this shape.
@param newPoints The new apex coordinates.
*/
public void setCoordinates(List<GMLCoordinates> newPoints) {
points.clear();
points.addAll(newPoints);
bounds = null;
centroid = null;
}
/**
Get the x coordinate of the centroid of this shape.
@return The x coordinate of the centroid.
*/
public double getCentreX() {
return getCentroid().getX();
}
/**
Get the y coordinate of the centroid of this shape.
@return The y coordinate of the centroid.
*/
public double getCentreY() {
return getCentroid().getY();
}
/**
Get the bounds of this shape.
@return The bounds of the shape.
*/
public Rectangle2D getBounds() {
if (bounds == null) {
bounds = GMLTools.getBounds(getCoordinates());
}
return bounds;
}
/**
Get the centroid of this shape.
@return The centroid of the shape.
*/
public Point2D getCentroid() {
if (centroid == null) {
centroid = GeometryTools2D.computeCentroid(GMLTools.coordinatesAsPoints(getCoordinates()));
}
return centroid;
}
private GMLDirectedEdge findDirectedEdge(GMLEdge e) {
for (GMLDirectedEdge next : edges) {
if (next.getEdge().equals(e)) {
return next;
}
}
throw new IllegalArgumentException(this + ": Edge " + e + " not found");
}
}
package maps.gml;
import java.util.List;
/**
An open space in GML space.
*/
public class GMLSpace extends GMLShape {
/**
Construct a GMLSpace.
@param id The ID of the space.
*/
public GMLSpace(int id) {
super(id);
}
/**
Construct a GMLSpace.
@param id The ID of the space.
@param edges The edges of the space.
*/
public GMLSpace(int id, List<GMLDirectedEdge> edges) {
super(id, edges);
}
/**
Construct a GMLSpace.
@param id The ID of the space.
@param edges The edges of the space.
@param neighbours The neighbours of each edge.
*/
public GMLSpace(int id, List<GMLDirectedEdge> edges, List<Integer> neighbours) {
super(id, edges, neighbours);
}
}
package maps.gml;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Path2D;
import java.awt.Shape;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.misc.geometry.Line2D;
/**
Useful tools for manipulating GML.
*/
public final class GMLTools {
private GMLTools() {
}
/**
Turn a list of coordinates into a string suitable for putting into an XML document.
@param coords The coordinate list.
@return A string version of the list.
*/
public static String getCoordinatesString(List<GMLCoordinates> coords) {
StringBuilder result = new StringBuilder();
for (Iterator<GMLCoordinates> it = coords.iterator(); it.hasNext();) {
GMLCoordinates next = it.next();
result.append(String.valueOf(next.getX()));
result.append(",");
result.append(String.valueOf(next.getY()));
if (it.hasNext()) {
result.append(" ");
}
}
return result.toString();
}
/**
Turn a coordinates string into a list of GMLCoordinates.
@param coords The coordinates string.
@return A list of GMLCoordinates.
*/
public static List<GMLCoordinates> getCoordinatesList(String coords) {
List<GMLCoordinates> result = new ArrayList<GMLCoordinates>();
StringTokenizer tokens = new StringTokenizer(coords, " ");
while (tokens.hasMoreTokens()) {
result.add(new GMLCoordinates(tokens.nextToken()));
}
return result;
}
/**
Convert a list of GMLCoordinates to Point2D objects.
@param coords The GMLCoordinates to convert.
@return A list of Point2D objects.
*/
public static List<Point2D> coordinatesAsPoints(List<GMLCoordinates> coords) {
List<Point2D> result = new ArrayList<Point2D>(coords.size());
for (GMLCoordinates next : coords) {
result.add(new Point2D(next.getX(), next.getY()));
}
return result;
}
/**
Get the bounds of a set of coordinates.
@param coords The coordinate list.
@return The bounds of the coordinates.
*/
public static Rectangle2D getBounds(List<GMLCoordinates> coords) {
if (coords.isEmpty()) {
return null;
}
double minX = Double.POSITIVE_INFINITY;
double minY = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY;
double maxY = Double.NEGATIVE_INFINITY;
for (GMLCoordinates next : coords) {
minX = Math.min(minX, next.getX());
minY = Math.min(minY, next.getY());
maxX = Math.max(maxX, next.getX());
maxY = Math.max(maxY, next.getY());
}
return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
}
/**
Get the bounds of a set of gml objects.
@param objects The object list.
@return The bounds of the objects.
*/
public static Rectangle2D getObjectBounds(List<? extends GMLObject> objects) {
Rectangle2D result = null;
for (GMLObject next : objects) {
result = expand(result, next);
}
return result;
}
/**
Turn a list of coordinates into a shape.
@param coords The coordinates.
@return A new shape.
*/
public static Shape coordsToShape(List<GMLCoordinates> coords) {
Path2D path = new Path2D.Double();
Iterator<GMLCoordinates> it = coords.iterator();
GMLCoordinates c = it.next();
path.moveTo(c.getX(), c.getY());
while (it.hasNext()) {
c = it.next();
path.lineTo(c.getX(), c.getY());
}
path.closePath();
return path;
}
/**
Turn a GMLNode into a Point2D.
@param node The node to convert.
@return A new Point2D.
*/
public static Point2D toPoint(GMLNode node) {
return new Point2D(node.getX(), node.getY());
}
/**
Turn a GMLEdge into a Line2D.
@param edge The edge to convert.
@return A new Line2D.
*/
public static Line2D toLine(GMLEdge edge) {
return new Line2D(toPoint(edge.getStart()), toPoint(edge.getEnd()));
}
private static Rectangle2D expand(Rectangle2D rect, double x, double y) {
if (rect == null) {
return new Rectangle2D.Double(x, y, 0, 0);
}
double newMinX = Math.min(x, rect.getX());
double newMaxX = Math.max(x, rect.getX() + rect.getWidth());
double newMinY = Math.min(y, rect.getY());
double newMaxY = Math.max(y, rect.getY() + rect.getHeight());
rect.setRect(newMinX, newMinY, newMaxX - newMinX, newMaxY - newMinY);
return rect;
}
private static Rectangle2D expand(Rectangle2D rect, GMLNode node) {
return expand(rect, node.getX(), node.getY());
}
private static Rectangle2D expand(Rectangle2D rect, GMLEdge edge) {
return expand(expand(rect, edge.getStart()), edge.getEnd());
}
private static Rectangle2D expand(Rectangle2D rect, GMLShape shape) {
for (GMLDirectedEdge next : shape.getEdges()) {
rect = expand(rect, next.getEdge());
}
return rect;
}
private static Rectangle2D expand(Rectangle2D rect, GMLObject object) {
if (object instanceof GMLNode) {
return expand(rect, (GMLNode)object);
}
if (object instanceof GMLEdge) {
return expand(rect, (GMLEdge)object);
}
if (object instanceof GMLShape) {
return expand(rect, (GMLShape)object);
}
return rect;
}
}
package maps.gml;
import maps.MapReader;
import maps.gml.view.GMLMapViewer;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
/**
A GML map viewer.
*/
public final class ViewGMLMap {
private static final int VIEWER_SIZE = 500;
private ViewGMLMap() {
}
/**
Start the viewer.
@param args Command-line arguments: mapname.
*/
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: ViewGMLMap <mapname>");
return;
}
try {
GMLMap map = (GMLMap)MapReader.readMap(args[0]);
GMLMapViewer gmlViewer = new GMLMapViewer(map);
JFrame frame = new JFrame("GML Map");
gmlViewer.setPreferredSize(new Dimension(VIEWER_SIZE, VIEWER_SIZE));
frame.setContentPane(gmlViewer);
frame.pack();
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
// CHECKSTYLE:OFF:IllegalCatch
catch (Exception e) {
e.printStackTrace();
}
// CHECKSTYLE:ON:IllegalCatch
}
}
package maps.gml.debug;
import java.awt.Color;
import rescuecore2.misc.gui.ShapeDebugFrame;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.misc.geometry.Line2D;
import maps.gml.GMLDirectedEdge;
import maps.gml.GMLNode;
/**
A ShapeInfo that knows how to draw GMLDirectedEdges.
*/
public class GMLDirectedEdgeShapeInfo extends ShapeDebugFrame.Line2DShapeInfo {
private GMLDirectedEdge edge;
/**
Create a new GMLDirectedEdgeShapeInfo.
@param edge The directed edge to draw.
@param name The name of the edge.
@param colour The colour to draw the edge.
@param thick Whether to draw the edge thick or not.
@param arrow Whether to draw the direction arrow or not.
*/
public GMLDirectedEdgeShapeInfo(GMLDirectedEdge edge, String name, Color colour, boolean thick, boolean arrow) {
super(gmlDirectedEdgeToLine(edge), name, colour, thick, arrow);
this.edge = edge;
}
@Override
public Object getObject() {
return edge;
}
private static Line2D gmlDirectedEdgeToLine(GMLDirectedEdge edge) {
if (edge == null) {
return null;
}
GMLNode start = edge.getStartNode();
GMLNode end = edge.getEndNode();
Point2D origin = new Point2D(start.getX(), start.getY());
Point2D endPoint = new Point2D(end.getX(), end.getY());
return new Line2D(origin, endPoint);
}
}
package maps.gml.debug;
import java.awt.Color;
import rescuecore2.misc.gui.ShapeDebugFrame;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.misc.geometry.Line2D;
import maps.gml.GMLEdge;
import maps.gml.GMLNode;
/**
A ShapeInfo that knows how to draw GMLEdges.
*/
public class GMLEdgeShapeInfo extends ShapeDebugFrame.Line2DShapeInfo {
private GMLEdge edge;
/**
Create a new GMLEdgeShapeInfo.
@param edge The edge to draw.
@param name The name of the edge.
@param colour The colour to draw the edge.
@param thick Whether to draw the edge thick or not.
*/
public GMLEdgeShapeInfo(GMLEdge edge, String name, Color colour, boolean thick) {
super(gmlEdgeToLine(edge), name, colour, thick, false);
this.edge = edge;
}
@Override
public Object getObject() {
return edge;
}
private static Line2D gmlEdgeToLine(GMLEdge edge) {
if (edge == null) {
return null;
}
GMLNode start = edge.getStart();
GMLNode end = edge.getEnd();
Point2D origin = new Point2D(start.getX(), start.getY());
Point2D endPoint = new Point2D(end.getX(), end.getY());
return new Line2D(origin, endPoint);
}
}
package maps.gml.debug;
import java.awt.Color;
import rescuecore2.misc.gui.ShapeDebugFrame;
import rescuecore2.misc.geometry.Point2D;
import maps.gml.GMLNode;
/**
A ShapeInfo that knows how to draw GMLNodes.
*/
public class GMLNodeShapeInfo extends ShapeDebugFrame.Point2DShapeInfo {
private GMLNode node;
/**
Create a new GMLNodeShapeInfo.
@param node The node to draw.
@param name The name of the node.
@param colour The colour to draw the node.
@param square Whether to draw the node with a square or not.
*/
public GMLNodeShapeInfo(GMLNode node, String name, Color colour, boolean square) {
super(gmlNodeToPoint(node), name, colour, square);
this.node = node;
}
@Override
public Object getObject() {
return node;
}
private static Point2D gmlNodeToPoint(GMLNode node) {
return new Point2D(node.getX(), node.getY());
}
}
package maps.gml.debug;
import java.awt.Color;
import java.awt.Shape;
import java.awt.Polygon;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.List;
import rescuecore2.misc.gui.ScreenTransform;
import rescuecore2.misc.gui.ShapeDebugFrame;
import maps.gml.GMLShape;
import maps.gml.GMLTools;
import maps.gml.GMLCoordinates;
/**
A ShapeInfo that knows how to draw GMLShapes.
*/
public class GMLShapeInfo extends ShapeDebugFrame.ShapeInfo {
private GMLShape shape;
private Color outlineColour;
private Color fillColour;
private Rectangle2D bounds;
/**
Create a new GMLShapeInfo.
@param shape The shape to draw.
@param name The name of the shape.
@param outlineColour The colour to draw the outline of the shape. This may be null to indicate that the outline should not be painted.
@param fillColour The colour to draw the interior of the shape. This may be null to indicate that the interior should not be painted.
*/
public GMLShapeInfo(GMLShape shape, String name, Color outlineColour, Color fillColour) {
super(shape, name);
this.shape = shape;
this.outlineColour = outlineColour;
this.fillColour = fillColour;
if (shape != null) {
bounds = GMLTools.getBounds(shape.getCoordinates());
}
}
@Override
public Shape paint(Graphics2D g, ScreenTransform transform) {
if (shape == null) {
return null;
}
List<GMLCoordinates> coordinates = shape.getCoordinates();
int n = coordinates.size();
int[] xs = new int[n];
int[] ys = new int[n];
int i = 0;
for (GMLCoordinates next : coordinates) {
xs[i] = transform.xToScreen(next.getX());
ys[i] = transform.yToScreen(next.getY());
++i;
}
Polygon p = new Polygon(xs, ys, n);
if (outlineColour != null) {
g.setColor(outlineColour);
g.draw(p);
}
if (fillColour != null) {
g.setColor(fillColour);
g.fill(p);
}
return p;
}
@Override
public void paintLegend(Graphics2D g, int width, int height) {
if (outlineColour != null) {
g.setColor(outlineColour);
g.drawRect(0, 0, width - 1, height - 1);
}
if (fillColour != null) {
g.setColor(fillColour);
g.fillRect(0, 0, width, height);
}
}
@Override
public Rectangle2D getBoundsShape() {
return bounds;
}
@Override
public java.awt.geom.Point2D getBoundsPoint() {
return null;
}
}
package maps.gml.editor;
/**
Abstract base class for Function implementations.
*/
public abstract class AbstractFunction implements Function {
/** The GMLEditor instance. */
protected GMLEditor editor;
/**
Construct an AbstractFunction.
@param editor The editor instance.
*/
protected AbstractFunction(GMLEditor editor) {
this.editor = editor;
}
}
\ No newline at end of file
package maps.gml.editor;
/**
Abstract base class for Tool implementations.
*/
public abstract class AbstractTool implements Tool {
/** The GMLEditor instance. */
protected GMLEditor editor;
/**
Construct an AbstractTool.
@param editor The editor instance.
*/
protected AbstractTool(GMLEditor editor) {
this.editor = editor;
}
}
\ No newline at end of file
package maps.gml.editor;
import maps.gml.GMLNode;
import maps.gml.GMLCoordinates;
import java.util.Random;
import org.uncommons.maths.random.DiscreteUniformGenerator;
import org.uncommons.maths.random.MersenneTwisterRNG;
/**
A function for adding noise to node coordinates.
*/
public class AddNoiseFunction extends ProgressFunction {
private static final int RANGE = 5;
private static final double FACTOR = 0.001;
private Random random;
/**
Construct an AddNoiseFunction.
@param editor The editor instance.
*/
public AddNoiseFunction(GMLEditor editor) {
super(editor);
random = new MersenneTwisterRNG();
}
@Override
public String getName() {
return "Add noise";
}
@Override
protected String getTitle() {
return "Adding noise";
}
@Override
protected void executeImpl() {
DiscreteUniformGenerator generator = new DiscreteUniformGenerator(-RANGE, RANGE, random);
setProgressLimit(editor.getMap().getNodes().size());
for (GMLNode next : editor.getMap().getNodes()) {
GMLCoordinates c = next.getCoordinates();
c.setX(c.getX() + (generator.nextValue() * FACTOR));
c.setY(c.getY() + (generator.nextValue() * FACTOR));
bumpProgress();
}
editor.setChanged();
editor.getViewer().repaint();
}
}
\ No newline at end of file
package maps.gml.editor;
/**
Exception for indicating the the user has cancelled an operation.
*/
public class CancelledByUserException extends Exception {
/**
Constructor.
*/
public CancelledByUserException() {}
}
\ No newline at end of file
package maps.gml.editor;
import java.util.Collection;
import java.util.List;
import java.util.Iterator;
import maps.gml.GMLEdge;
import maps.gml.GMLDirectedEdge;
import maps.gml.GMLShape;
import maps.gml.GMLRoad;
import rescuecore2.log.Logger;
/**
A function for computing passable edges.
*/
public class ComputePassableEdgesFunction extends ProgressFunction {
/**
Construct a ComputePassableEdgesFunction.
@param editor The editor instance.
*/
public ComputePassableEdgesFunction(GMLEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Compute passable edges";
}
@Override
protected String getTitle() {
return "Finding neighbours";
}
@Override
protected void executeImpl() {
final Collection<GMLEdge> edges = editor.getMap().getEdges();
setProgressLimit(edges.size());
int passable = 0;
int impassable = 0;
for (GMLEdge next : edges) {
Collection<GMLShape> shapes = editor.getMap().getAttachedShapes(next);
if (shapes.size() == 2) {
Iterator<GMLShape> it = shapes.iterator();
GMLShape first = it.next();
GMLShape second = it.next();
if (first instanceof GMLRoad || second instanceof GMLRoad
|| next.isPassable()) {
next.setPassable(true);
GMLDirectedEdge firstEdge = findDirectedEdge(first.getEdges(), next);
GMLDirectedEdge secondEdge = findDirectedEdge(second.getEdges(), next);
first.setNeighbour(firstEdge, second.getID());
second.setNeighbour(secondEdge, first.getID());
++passable;
}
else {
makeImpassable(next, shapes);
++impassable;
}
}
else {
makeImpassable(next, shapes);
++impassable;
}
bumpProgress();
}
editor.setChanged();
editor.getViewer().repaint();
Logger.debug("Made " + passable + " edges passable and " + impassable + " impassable");
}
private void makeImpassable(GMLEdge edge, Collection<GMLShape> attached) {
edge.setPassable(false);
for (GMLShape shape : attached) {
shape.setNeighbour(edge, null);
}
}
private GMLDirectedEdge findDirectedEdge(List<GMLDirectedEdge> possible, GMLEdge target) {
for (GMLDirectedEdge next : possible) {
if (next.getEdge() == target) {
return next;
}
}
return null;
}
}
\ No newline at end of file
package maps.gml.editor;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.UndoableEdit;
import java.util.List;
import maps.gml.GMLNode;
import maps.gml.GMLBuilding;
/**
A tool for creating buildings.
*/
public class CreateBuildingTool extends CreateShapeTool {
/**
Construct a CreateBuildingTool.
@param editor The editor instance.
*/
public CreateBuildingTool(GMLEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Create building";
}
@Override
protected UndoableEdit finished(List<GMLNode> nodes) {
GMLBuilding building = editor.getMap().createBuildingFromNodes(nodes);
return new CreateBuildingEdit(building);
}
private class CreateBuildingEdit extends AbstractUndoableEdit {
private GMLBuilding building;
public CreateBuildingEdit(GMLBuilding building) {
this.building = building;
}
@Override
public void undo() {
super.undo();
editor.getMap().removeBuilding(building);
editor.getViewer().repaint();
}
@Override
public void redo() {
super.redo();
editor.getMap().addBuilding(building);
editor.getViewer().repaint();
}
}
}
\ No newline at end of file
package maps.gml.editor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Color;
import java.awt.Point;
import java.awt.Insets;
import javax.swing.undo.AbstractUndoableEdit;
import maps.gml.view.NodeDecorator;
import maps.gml.view.SquareNodeDecorator;
import maps.gml.view.LineOverlay;
import maps.gml.GMLNode;
import maps.gml.GMLEdge;
import maps.gml.GMLCoordinates;
import rescuecore2.misc.geometry.Point2D;
/**
A tool for creating edges.
*/
public class CreateEdgeTool extends AbstractTool {
private static final Color HIGHLIGHT_COLOUR = Color.BLUE;
private static final int HIGHLIGHT_SIZE = 6;
private Listener listener;
private NodeDecorator nodeHighlight;
private LineOverlay overlay;
private GMLNode hover;
private GMLNode start;
private GMLNode end;
// private GMLEdge edge;
/**
Construct a CreateEdgeTool.
@param editor The editor instance.
*/
public CreateEdgeTool(GMLEditor editor) {
super(editor);
listener = new Listener();
nodeHighlight = new SquareNodeDecorator(HIGHLIGHT_COLOUR, HIGHLIGHT_SIZE);
overlay = new LineOverlay(HIGHLIGHT_COLOUR, true);
}
@Override
public String getName() {
return "Create edge";
}
@Override
public void activate() {
editor.getViewer().addMouseListener(listener);
editor.getViewer().addMouseMotionListener(listener);
editor.getViewer().addOverlay(overlay);
hover = null;
start = null;
end = null;
// edge = null;
}
@Override
public void deactivate() {
editor.getViewer().removeMouseListener(listener);
editor.getViewer().removeMouseMotionListener(listener);
editor.getViewer().clearAllNodeDecorators();
editor.getViewer().removeOverlay(overlay);
editor.getViewer().repaint();
}
private void setHover(GMLNode node) {
if (hover == node) {
return;
}
if (hover != null) {
editor.getViewer().clearNodeDecorator(hover);
}
hover = node;
if (hover != null) {
editor.getViewer().setNodeDecorator(nodeHighlight, hover);
}
editor.getViewer().repaint();
}
private void setStart(GMLNode node) {
if (start == node) {
return;
}
if (start != null) {
editor.getViewer().clearNodeDecorator(start);
}
start = node;
if (start != null) {
editor.getViewer().setNodeDecorator(nodeHighlight, start);
}
editor.getViewer().repaint();
}
private void setEnd(GMLNode node) {
if (start == node || end == node) {
return;
}
if (end != null) {
editor.getViewer().clearNodeDecorator(end);
}
end = node;
if (end != null) {
editor.getViewer().setNodeDecorator(nodeHighlight, end);
}
editor.getViewer().repaint();
}
private class Listener implements MouseListener, MouseMotionListener {
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Point p = fixEventPoint(e.getPoint());
GMLCoordinates c = editor.getViewer().getCoordinatesAtPoint(p.x, p.y);
GMLNode node = editor.getMap().findNearestNode(c.getX(), c.getY());
overlay.setStart(new Point2D(node.getX(), node.getY()));
setStart(node);
setHover(null);
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (start != null && end != null) {
GMLEdge edge = editor.getMap().createEdge(start, end);
editor.setChanged();
editor.addEdit(new CreateEdgeEdit(edge));
editor.getViewer().clearAllNodeDecorators();
overlay.setStart(null);
overlay.setEnd(null);
editor.getViewer().repaint();
start = null;
end = null;
hover = null;
}
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (start != null) {
Point p = fixEventPoint(e.getPoint());
GMLCoordinates c = editor.getViewer().getCoordinatesAtPoint(p.x, p.y);
GMLNode node = editor.getMap().findNearestNode(c.getX(), c.getY());
overlay.setEnd(new Point2D(node.getX(), node.getY()));
setEnd(node);
}
}
@Override
public void mouseMoved(MouseEvent e) {
Point p = fixEventPoint(e.getPoint());
GMLCoordinates c = editor.snap(editor.getViewer().getCoordinatesAtPoint(p.x, p.y));
GMLNode node = editor.getMap().findNearestNode(c.getX(), c.getY());
setHover(node);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private Point fixEventPoint(Point p) {
Insets insets = editor.getViewer().getInsets();
return new Point(p.x - insets.left, p.y - insets.top);
}
}
private class CreateEdgeEdit extends AbstractUndoableEdit {
private GMLEdge edge;
public CreateEdgeEdit(GMLEdge edge) {
this.edge = edge;
}
@Override
public void undo() {
super.undo();
editor.getMap().removeEdge(edge);
editor.getViewer().repaint();
}
@Override
public void redo() {
super.redo();
editor.getMap().addEdge(edge);
editor.getViewer().repaint();
}
}
}
\ No newline at end of file
package maps.gml.editor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Point;
import java.awt.Insets;
import javax.swing.undo.AbstractUndoableEdit;
import maps.gml.GMLNode;
import maps.gml.GMLCoordinates;
/**
A tool for creating nodes.
*/
public class CreateNodeTool extends AbstractTool {
private Listener listener;
/**
Construct a CreateNodeTool.
@param editor The editor instance.
*/
public CreateNodeTool(GMLEditor editor) {
super(editor);
listener = new Listener();
}
@Override
public String getName() {
return "Create node";
}
@Override
public void activate() {
editor.getViewer().addMouseListener(listener);
editor.getViewer().addMouseMotionListener(listener);
}
@Override
public void deactivate() {
editor.getViewer().removeMouseListener(listener);
editor.getViewer().removeMouseMotionListener(listener);
}
private class Listener implements MouseListener, MouseMotionListener {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Point p = fixEventPoint(e.getPoint());
GMLCoordinates c = editor.snap(editor.getViewer().getCoordinatesAtPoint(p.x, p.y));
GMLNode node = editor.getMap().createNode(c);
editor.setChanged();
editor.addEdit(new CreateNodeEdit(node));
editor.getViewer().repaint();
}
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private Point fixEventPoint(Point p) {
Insets insets = editor.getViewer().getInsets();
return new Point(p.x - insets.left, p.y - insets.top);
}
}
private class CreateNodeEdit extends AbstractUndoableEdit {
private GMLNode node;
public CreateNodeEdit(GMLNode node) {
this.node = node;
}
@Override
public void undo() {
super.undo();
editor.getMap().removeNode(node);
editor.getViewer().repaint();
}
@Override
public void redo() {
super.redo();
editor.getMap().addNode(node);
editor.getViewer().repaint();
}
}
}
\ No newline at end of file
package maps.gml.editor;
import javax.swing.undo.UndoableEdit;
import javax.swing.undo.AbstractUndoableEdit;
import java.util.List;
import maps.gml.GMLNode;
import maps.gml.GMLRoad;
/**
A tool for creating roads.
*/
public class CreateRoadTool extends CreateShapeTool {
/**
Construct a CreateRoadTool.
@param editor The editor instance.
*/
public CreateRoadTool(GMLEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Create road";
}
@Override
protected UndoableEdit finished(List<GMLNode> nodes) {
GMLRoad road = editor.getMap().createRoadFromNodes(nodes);
return new CreateRoadEdit(road);
}
private class CreateRoadEdit extends AbstractUndoableEdit {
private GMLRoad road;
public CreateRoadEdit(GMLRoad road) {
this.road = road;
}
@Override
public void undo() {
super.undo();
editor.getMap().removeRoad(road);
editor.getViewer().repaint();
}
@Override
public void redo() {
super.redo();
editor.getMap().addRoad(road);
editor.getViewer().repaint();
}
}
}
\ No newline at end of file
package maps.gml.editor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Color;
import java.awt.Point;
import java.awt.Insets;
import javax.swing.undo.UndoableEdit;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import maps.gml.view.EdgeDecorator;
import maps.gml.view.LineEdgeDecorator;
import maps.gml.GMLNode;
import maps.gml.GMLEdge;
import maps.gml.GMLCoordinates;
/**
A tool for creating shapes.
*/
public abstract class CreateShapeTool extends AbstractTool {
private static final Color HOVER_COLOUR = Color.BLUE;
private static final Color SELECTED_COLOUR = Color.GREEN;
private static final Color POSSIBLE_COLOUR = Color.WHITE;
private Listener listener;
private EdgeDecorator hoverHighlight;
private EdgeDecorator selectedHighlight;
private EdgeDecorator possibleHighlight;
private List<GMLEdge> edges;
private List<GMLNode> nodes;
private Set<GMLEdge> possible;
private GMLNode startNode;
private GMLNode currentNode;
private GMLEdge hover;
/**
Construct a CreateShapeTool.
@param editor The editor instance.
*/
protected CreateShapeTool(GMLEditor editor) {
super(editor);
listener = new Listener();
hoverHighlight = new LineEdgeDecorator(HOVER_COLOUR);
selectedHighlight = new LineEdgeDecorator(SELECTED_COLOUR);
possibleHighlight = new LineEdgeDecorator(POSSIBLE_COLOUR);
edges = new ArrayList<GMLEdge>();
nodes = new ArrayList<GMLNode>();
possible = new HashSet<GMLEdge>();
}
@Override
public void activate() {
editor.getViewer().addMouseListener(listener);
editor.getViewer().addMouseMotionListener(listener);
clearData();
}
@Override
public void deactivate() {
editor.getViewer().removeMouseListener(listener);
editor.getViewer().removeMouseMotionListener(listener);
editor.getViewer().clearAllEdgeDecorators();
editor.getViewer().repaint();
clearData();
}
/**
Perform whatever shape creation tasks are needed once the shape has been closed.
@param shapeNodes The nodes of the shape.
@return An UndoableEdit for the change.
*/
protected abstract UndoableEdit finished(List<GMLNode> shapeNodes);
private void addEdge(GMLEdge edge) {
editor.getViewer().clearEdgeDecorator(possible);
edges.add(edge);
possible.clear();
editor.getViewer().setEdgeDecorator(selectedHighlight, edge);
editor.getViewer().repaint();
if (edges.size() == 1) {
startNode = edge.getStart();
currentNode = edge.getEnd();
possible.addAll(editor.getMap().getAttachedEdges(startNode));
possible.addAll(editor.getMap().getAttachedEdges(currentNode));
}
else if (edges.size() == 2) {
// Find the shared node
GMLEdge first = edges.get(0);
GMLEdge second = edges.get(1);
GMLNode shared;
if (first.getStart().equals(second.getStart()) || first.getStart().equals(second.getEnd())) {
startNode = first.getEnd();
shared = first.getStart();
}
else {
startNode = first.getStart();
shared = first.getEnd();
}
currentNode = shared.equals(second.getStart()) ? second.getEnd() : second.getStart();
nodes.add(startNode);
nodes.add(shared);
nodes.add(currentNode);
possible.addAll(editor.getMap().getAttachedEdges(currentNode));
}
else if (edges.size() > 2) {
// Update end node
currentNode = currentNode.equals(edge.getStart()) ? edge.getEnd() : edge.getStart();
if (currentNode.equals(startNode)) {
// We're done
editor.addEdit(finished(nodes));
editor.setChanged();
clearData();
editor.getViewer().clearAllEdgeDecorators();
editor.getViewer().repaint();
}
else {
nodes.add(currentNode);
possible.addAll(editor.getMap().getAttachedEdges(currentNode));
}
}
possible.removeAll(edges);
editor.getViewer().setEdgeDecorator(possibleHighlight, possible);
if (possible.size() == 1) {
addEdge(possible.iterator().next());
}
editor.getViewer().repaint();
}
private void clearData() {
nodes.clear();
edges.clear();
possible.clear();
startNode = null;
currentNode = null;
hover = null;
}
private void hover(GMLEdge edge) {
if (hover == edge) {
return;
}
if (hover != null) {
editor.getViewer().clearEdgeDecorator(hover);
if (possible.contains(hover)) {
editor.getViewer().setEdgeDecorator(possibleHighlight, hover);
}
}
hover = edge;
if (hover != null) {
editor.getViewer().setEdgeDecorator(hoverHighlight, hover);
}
editor.getViewer().repaint();
}
private class Listener implements MouseListener, MouseMotionListener {
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
Point p = fixEventPoint(e.getPoint());
GMLCoordinates c = editor.snap(editor.getViewer().getCoordinatesAtPoint(p.x, p.y));
if (edges.isEmpty()) {
hover(editor.getMap().findNearestEdge(c.getX(), c.getY()));
}
else {
hover(editor.getMap().findNearestEdge(c.getX(), c.getY(), possible));
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (hover != null && e.getButton() == MouseEvent.BUTTON1) {
GMLEdge edge = hover;
hover(null);
addEdge(edge);
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private Point fixEventPoint(Point p) {
Insets insets = editor.getViewer().getInsets();
return new Point(p.x - insets.left, p.y - insets.top);
}
}
}
\ No newline at end of file
package maps.gml.editor;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.UndoableEdit;
import java.util.List;
import maps.gml.GMLNode;
import maps.gml.GMLSpace;
/**
A tool for creating spaces.
*/
public class CreateSpaceTool extends CreateShapeTool {
/**
Construct a CreateSpaceTool.
@param editor The editor instance.
*/
public CreateSpaceTool(GMLEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Create space";
}
@Override
protected UndoableEdit finished(List<GMLNode> nodes) {
GMLSpace space = editor.getMap().createSpaceFromNodes(nodes);
return new CreateSpaceEdit(space);
}
private class CreateSpaceEdit extends AbstractUndoableEdit {
private GMLSpace space;
public CreateSpaceEdit(GMLSpace space) {
this.space = space;
}
@Override
public void undo() {
super.undo();
editor.getMap().removeSpace(space);
editor.getViewer().repaint();
}
@Override
public void redo() {
super.redo();
editor.getMap().addSpace(space);
editor.getViewer().repaint();
}
}
}
\ No newline at end of file
package maps.gml.editor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Color;
import java.awt.Point;
import java.awt.Insets;
import javax.swing.undo.AbstractUndoableEdit;
import maps.gml.view.EdgeDecorator;
import maps.gml.view.LineEdgeDecorator;
import maps.gml.GMLEdge;
import maps.gml.GMLCoordinates;
import maps.gml.GMLObject;
import java.util.Collection;
/**
A tool for deleting edges.
*/
public class DeleteEdgeTool extends AbstractTool {
private static final Color HIGHLIGHT_COLOUR = Color.BLUE;
private Listener listener;
private EdgeDecorator edgeHighlight;
private GMLEdge edge;
/**
Construct a DeleteEdgeTool.
@param editor The editor instance.
*/
public DeleteEdgeTool(GMLEditor editor) {
super(editor);
listener = new Listener();
edgeHighlight = new LineEdgeDecorator(HIGHLIGHT_COLOUR);
}
@Override
public String getName() {
return "Delete edge";
}
@Override
public void activate() {
editor.getViewer().addMouseListener(listener);
editor.getViewer().addMouseMotionListener(listener);
edge = null;
}
@Override
public void deactivate() {
editor.getViewer().removeMouseListener(listener);
editor.getViewer().removeMouseMotionListener(listener);
editor.getViewer().clearAllEdgeDecorators();
editor.getViewer().repaint();
}
private void highlightEdge(GMLEdge newEdge) {
if (edge == newEdge) {
return;
}
if (edge != null) {
editor.getViewer().clearEdgeDecorator(edge);
}
edge = newEdge;
if (edge != null) {
editor.getViewer().setEdgeDecorator(edgeHighlight, edge);
}
editor.getViewer().repaint();
}
private class Listener implements MouseListener, MouseMotionListener {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Collection<GMLObject> deleted = editor.getMap().removeEdge(edge);
editor.getViewer().repaint();
editor.setChanged();
editor.addEdit(new DeleteEdgeEdit(edge, deleted));
}
}
@Override
public void mouseMoved(MouseEvent e) {
Point p = fixEventPoint(e.getPoint());
GMLCoordinates c = editor.snap(editor.getViewer().getCoordinatesAtPoint(p.x, p.y));
highlightEdge(editor.getMap().findNearestEdge(c.getX(), c.getY()));
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private Point fixEventPoint(Point p) {
Insets insets = editor.getViewer().getInsets();
return new Point(p.x - insets.left, p.y - insets.top);
}
}
private class DeleteEdgeEdit extends AbstractUndoableEdit {
private GMLEdge edge;
private Collection<GMLObject> deleted;
public DeleteEdgeEdit(GMLEdge edge, Collection<GMLObject> deleted) {
this.edge = edge;
this.deleted = deleted;
}
@Override
public void undo() {
super.undo();
editor.getMap().addEdge(edge);
editor.getMap().add(deleted);
editor.getViewer().repaint();
}
@Override
public void redo() {
super.redo();
editor.getMap().removeEdge(edge);
editor.getViewer().repaint();
}
}
}
\ 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