Enforce immutability via final and unmodifiableList.
This commit is contained in:
parent
7640fa34c7
commit
d00e012497
@ -2,9 +2,10 @@ package org.insa.algo.weakconnectivity;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
import org.insa.algo.AbstractAlgorithm;
|
import org.insa.algo.AbstractAlgorithm;
|
||||||
import org.insa.algo.AbstractSolution.Status;
|
import org.insa.algo.AbstractSolution.Status;
|
||||||
@ -12,146 +13,149 @@ import org.insa.graph.Arc;
|
|||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
import org.insa.graph.Node;
|
import org.insa.graph.Node;
|
||||||
|
|
||||||
public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm<WeaklyConnectedComponentObserver>{
|
public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm<WeaklyConnectedComponentObserver> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param instance
|
* @param instance
|
||||||
* @param logOutput
|
* @param logOutput
|
||||||
*/
|
*/
|
||||||
public WeaklyConnectedComponentsAlgorithm(WeaklyConnectedComponentsData instance) {
|
public WeaklyConnectedComponentsAlgorithm(WeaklyConnectedComponentsData instance) {
|
||||||
super(instance);
|
super(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public WeaklyConnectedComponentsSolution run() {
|
|
||||||
return (WeaklyConnectedComponentsSolution)super.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WeaklyConnectedComponentsData getInstance() {
|
|
||||||
return (WeaklyConnectedComponentsData)super.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all observers that the algorithm is entering a new component.
|
|
||||||
*
|
|
||||||
* @param curNode Starting node for the component.
|
|
||||||
*/
|
|
||||||
protected void notifyStartComponent(Node curNode) {
|
|
||||||
for (WeaklyConnectedComponentObserver obs: getObservers()) {
|
|
||||||
obs.notifyStartComponent(curNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all observers that a new node has been found for the current component.
|
|
||||||
*
|
|
||||||
* @param node New node found for the current component.
|
|
||||||
*/
|
|
||||||
protected void notifyNewNodeInComponent(Node node) {
|
|
||||||
for (WeaklyConnectedComponentObserver obs: getObservers()) {
|
|
||||||
obs.notifyNewNodeInComponent(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all observers that the algorithm has computed a new component.
|
|
||||||
*
|
|
||||||
* @param nodes List of nodes in the component.
|
|
||||||
*/
|
|
||||||
protected void notifyEndComponent(ArrayList<Node> nodes) {
|
|
||||||
for (WeaklyConnectedComponentObserver obs: getObservers()) {
|
|
||||||
obs.notifyEndComponent(nodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return An adjacency list for the undirected graph equivalent to the stored graph.
|
|
||||||
*/
|
|
||||||
protected ArrayList<HashSet<Integer>> createUndirectedGraph() {
|
|
||||||
int nNodes = getInstance().getGraph().getNodes().size();
|
|
||||||
ArrayList<HashSet<Integer>> res = new ArrayList<HashSet<Integer>>(nNodes);
|
|
||||||
for (int i = 0; i < nNodes; ++i) {
|
|
||||||
res.add(new HashSet<Integer>());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Node node: getInstance().getGraph().getNodes()) {
|
|
||||||
for (Arc arc: node.getSuccessors()) {
|
|
||||||
res.get(node.getId()).add(arc.getDestination().getId());
|
|
||||||
if (arc.getInfo().isOneWay()) {
|
|
||||||
res.get(arc.getDestination().getId()).add(node.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply a breadth first search algorithm on the given undirected graph (adjacency list),
|
|
||||||
* starting at node cur, and marking nodes in marked.
|
|
||||||
*
|
|
||||||
* @param marked
|
|
||||||
* @param cur
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected ArrayList<Node> bfs(ArrayList<HashSet<Integer>> ugraph, boolean[] marked, int cur) {
|
|
||||||
ArrayList<Node> nodes = getInstance().getGraph().getNodes();
|
|
||||||
ArrayList<Node> component = new ArrayList<Node>();
|
|
||||||
|
|
||||||
// Using a queue because we are doing a BFS
|
|
||||||
Queue<Integer> queue = new LinkedList<Integer>();
|
|
||||||
|
|
||||||
// Notify observers about the current component.
|
@Override
|
||||||
notifyStartComponent(nodes.get(cur));
|
public WeaklyConnectedComponentsSolution run() {
|
||||||
|
return (WeaklyConnectedComponentsSolution) super.run();
|
||||||
// Add original node and loop until the queue is empty.
|
}
|
||||||
queue.add(cur);
|
|
||||||
marked[cur] = true;
|
|
||||||
while (!queue.isEmpty()) {
|
|
||||||
Node node = nodes.get(queue.remove());
|
|
||||||
component.add(node);
|
|
||||||
|
|
||||||
// Notify observers
|
|
||||||
notifyNewNodeInComponent(node);
|
|
||||||
|
|
||||||
for (Integer destId: ugraph.get(node.getId())) {
|
|
||||||
Node dest = nodes.get(destId);
|
|
||||||
if (!marked[dest.getId()]) {
|
|
||||||
queue.add(destId);
|
|
||||||
marked[destId] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyEndComponent(component);
|
|
||||||
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WeaklyConnectedComponentsSolution doRun() {
|
public WeaklyConnectedComponentsData getInstance() {
|
||||||
|
return (WeaklyConnectedComponentsData) super.getInstance();
|
||||||
Graph graph = getInstance().getGraph();
|
}
|
||||||
ArrayList<HashSet<Integer>> ugraph = createUndirectedGraph();
|
|
||||||
boolean[] marked = new boolean[graph.getNodes().size()];
|
/**
|
||||||
Arrays.fill(marked, false);
|
* Notify all observers that the algorithm is entering a new component.
|
||||||
|
*
|
||||||
ArrayList<ArrayList<Node>> components = new ArrayList<ArrayList<Node>>();
|
* @param curNode Starting node for the component.
|
||||||
|
*/
|
||||||
// perform algorithm
|
protected void notifyStartComponent(Node curNode) {
|
||||||
int cur = 0;
|
for (WeaklyConnectedComponentObserver obs: getObservers()) {
|
||||||
while (cur < marked.length) {
|
obs.notifyStartComponent(curNode);
|
||||||
// Apply BFS
|
}
|
||||||
components.add(this.bfs(ugraph, marked, cur));
|
}
|
||||||
|
|
||||||
// Find next non-marked
|
/**
|
||||||
for (; cur < marked.length && marked[cur]; ++cur);
|
* Notify all observers that a new node has been found for the current
|
||||||
}
|
* component.
|
||||||
|
*
|
||||||
return new WeaklyConnectedComponentsSolution(getInstance(), Status.OPTIMAL, components);
|
* @param node New node found for the current component.
|
||||||
}
|
*/
|
||||||
|
protected void notifyNewNodeInComponent(Node node) {
|
||||||
|
for (WeaklyConnectedComponentObserver obs: getObservers()) {
|
||||||
|
obs.notifyNewNodeInComponent(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify all observers that the algorithm has computed a new component.
|
||||||
|
*
|
||||||
|
* @param nodes List of nodes in the component.
|
||||||
|
*/
|
||||||
|
protected void notifyEndComponent(ArrayList<Node> nodes) {
|
||||||
|
for (WeaklyConnectedComponentObserver obs: getObservers()) {
|
||||||
|
obs.notifyEndComponent(nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return An adjacency list for the undirected graph equivalent to the stored
|
||||||
|
* graph.
|
||||||
|
*/
|
||||||
|
protected ArrayList<HashSet<Integer>> createUndirectedGraph() {
|
||||||
|
int nNodes = getInstance().getGraph().getNodes().size();
|
||||||
|
ArrayList<HashSet<Integer>> res = new ArrayList<HashSet<Integer>>(nNodes);
|
||||||
|
for (int i = 0; i < nNodes; ++i) {
|
||||||
|
res.add(new HashSet<Integer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Node node: getInstance().getGraph().getNodes()) {
|
||||||
|
for (Arc arc: node.getSuccessors()) {
|
||||||
|
res.get(node.getId()).add(arc.getDestination().getId());
|
||||||
|
if (arc.getInfo().isOneWay()) {
|
||||||
|
res.get(arc.getDestination().getId()).add(node.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a breadth first search algorithm on the given undirected graph
|
||||||
|
* (adjacency list), starting at node cur, and marking nodes in marked.
|
||||||
|
*
|
||||||
|
* @param marked
|
||||||
|
* @param cur
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected ArrayList<Node> bfs(ArrayList<HashSet<Integer>> ugraph, boolean[] marked, int cur) {
|
||||||
|
List<Node> nodes = getInstance().getGraph().getNodes();
|
||||||
|
ArrayList<Node> component = new ArrayList<Node>();
|
||||||
|
|
||||||
|
// Using a queue because we are doing a BFS
|
||||||
|
Queue<Integer> queue = new LinkedList<Integer>();
|
||||||
|
|
||||||
|
// Notify observers about the current component.
|
||||||
|
notifyStartComponent(nodes.get(cur));
|
||||||
|
|
||||||
|
// Add original node and loop until the queue is empty.
|
||||||
|
queue.add(cur);
|
||||||
|
marked[cur] = true;
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
Node node = nodes.get(queue.remove());
|
||||||
|
component.add(node);
|
||||||
|
|
||||||
|
// Notify observers
|
||||||
|
notifyNewNodeInComponent(node);
|
||||||
|
|
||||||
|
for (Integer destId: ugraph.get(node.getId())) {
|
||||||
|
Node dest = nodes.get(destId);
|
||||||
|
if (!marked[dest.getId()]) {
|
||||||
|
queue.add(destId);
|
||||||
|
marked[destId] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyEndComponent(component);
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected WeaklyConnectedComponentsSolution doRun() {
|
||||||
|
|
||||||
|
Graph graph = getInstance().getGraph();
|
||||||
|
ArrayList<HashSet<Integer>> ugraph = createUndirectedGraph();
|
||||||
|
boolean[] marked = new boolean[graph.getNodes().size()];
|
||||||
|
Arrays.fill(marked, false);
|
||||||
|
|
||||||
|
ArrayList<ArrayList<Node>> components = new ArrayList<ArrayList<Node>>();
|
||||||
|
|
||||||
|
// perform algorithm
|
||||||
|
int cur = 0;
|
||||||
|
while (cur < marked.length) {
|
||||||
|
// Apply BFS
|
||||||
|
components.add(this.bfs(ugraph, marked, cur));
|
||||||
|
|
||||||
|
// Find next non-marked
|
||||||
|
for (; cur < marked.length && marked[cur]; ++cur)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WeaklyConnectedComponentsSolution(getInstance(), Status.OPTIMAL, components);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,92 +1,95 @@
|
|||||||
package org.insa.graph;
|
package org.insa.graph;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Arc {
|
public class Arc {
|
||||||
|
|
||||||
// Destination node.
|
|
||||||
private Node origin, destination;
|
|
||||||
|
|
||||||
// Length of the road (in meters).
|
// Destination node.
|
||||||
private int length;
|
private final Node origin, destination;
|
||||||
|
|
||||||
// Road information.
|
|
||||||
RoadInformation info;
|
|
||||||
|
|
||||||
// Segments.
|
|
||||||
ArrayList<Point> points;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param dest
|
|
||||||
* @param length
|
|
||||||
* @param roadInformation
|
|
||||||
* @param points
|
|
||||||
*/
|
|
||||||
public Arc(Node origin, Node dest, int length, RoadInformation roadInformation) {
|
|
||||||
this.origin = origin;
|
|
||||||
this.destination = dest;
|
|
||||||
this.length = length;
|
|
||||||
this.info = roadInformation;
|
|
||||||
this.points = new ArrayList<Point>();
|
|
||||||
origin.addSuccessor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Length of the road (in meters).
|
||||||
* @param dest
|
private final int length;
|
||||||
* @param length
|
|
||||||
* @param roadInformation
|
|
||||||
* @param points
|
|
||||||
*/
|
|
||||||
public Arc(Node origin, Node dest, int length, RoadInformation roadInformation, ArrayList<Point> points) {
|
|
||||||
this.origin = origin;
|
|
||||||
this.destination = dest;
|
|
||||||
this.length = length;
|
|
||||||
this.info = roadInformation;
|
|
||||||
this.points = points;
|
|
||||||
origin.addSuccessor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Origin node of this arc.
|
|
||||||
*/
|
|
||||||
public Node getOrigin() {
|
|
||||||
return origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Destination node of this arc.
|
|
||||||
*/
|
|
||||||
public Node getDestination() {
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Road information.
|
||||||
* @return Length of this arc, in meters.
|
private final RoadInformation info;
|
||||||
*/
|
|
||||||
public int getLength() {
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Minimum time required to travel this arc, in seconds.
|
|
||||||
*/
|
|
||||||
public double getMinimumTravelTime() {
|
|
||||||
return getLength() * 3600.0 / (info.getMaximumSpeed() * 1000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Segments.
|
||||||
* @return Road information for this arc.
|
private final ArrayList<Point> points;
|
||||||
*/
|
|
||||||
public RoadInformation getInfo() {
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Points representing segments of this arc. This function may return an empty
|
* @param dest
|
||||||
* ArrayList if the segments are stored in the reversed arc (for two-ways road).
|
* @param length
|
||||||
*/
|
* @param roadInformation
|
||||||
public ArrayList<Point> getPoints() {
|
* @param points
|
||||||
return points;
|
*/
|
||||||
}
|
public Arc(Node origin, Node dest, int length, RoadInformation roadInformation) {
|
||||||
|
this.origin = origin;
|
||||||
|
this.destination = dest;
|
||||||
|
this.length = length;
|
||||||
|
this.info = roadInformation;
|
||||||
|
this.points = new ArrayList<Point>();
|
||||||
|
origin.addSuccessor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dest
|
||||||
|
* @param length
|
||||||
|
* @param roadInformation
|
||||||
|
* @param points
|
||||||
|
*/
|
||||||
|
public Arc(Node origin, Node dest, int length, RoadInformation roadInformation, ArrayList<Point> points) {
|
||||||
|
this.origin = origin;
|
||||||
|
this.destination = dest;
|
||||||
|
this.length = length;
|
||||||
|
this.info = roadInformation;
|
||||||
|
this.points = points;
|
||||||
|
origin.addSuccessor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Origin node of this arc.
|
||||||
|
*/
|
||||||
|
public Node getOrigin() {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Destination node of this arc.
|
||||||
|
*/
|
||||||
|
public Node getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Length of this arc, in meters.
|
||||||
|
*/
|
||||||
|
public int getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Minimum time required to travel this arc, in seconds.
|
||||||
|
*/
|
||||||
|
public double getMinimumTravelTime() {
|
||||||
|
return getLength() * 3600.0 / (info.getMaximumSpeed() * 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Road information for this arc.
|
||||||
|
*/
|
||||||
|
public RoadInformation getInfo() {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Points representing segments of this arc. This function may return an
|
||||||
|
* empty ArrayList if the segments are stored in the reversed arc (for
|
||||||
|
* two-ways road).
|
||||||
|
*/
|
||||||
|
public List<Point> getPoints() {
|
||||||
|
return Collections.unmodifiableList(points);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,60 +1,66 @@
|
|||||||
package org.insa.graph ;
|
package org.insa.graph;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Graph {
|
public class Graph {
|
||||||
|
|
||||||
// Map identifier.
|
// Map identifier.
|
||||||
private int mapId;
|
private final int mapId;
|
||||||
|
|
||||||
// Nodes of the graph.
|
|
||||||
private ArrayList<Node> nodes;
|
|
||||||
|
|
||||||
/**
|
// Nodes of the graph.
|
||||||
* @param mapId
|
private final ArrayList<Node> nodes;
|
||||||
* @param nodes
|
|
||||||
*/
|
/**
|
||||||
public Graph(int mapId, ArrayList<Node> nodes) {
|
* @param mapId
|
||||||
this.mapId = mapId;
|
* @param nodes
|
||||||
this.nodes = nodes;
|
*/
|
||||||
}
|
public Graph(int mapId, ArrayList<Node> nodes) {
|
||||||
|
this.mapId = mapId;
|
||||||
/**
|
this.nodes = nodes;
|
||||||
* @return Nodes of this graph.
|
}
|
||||||
*/
|
|
||||||
public ArrayList<Node> getNodes() { return nodes; }
|
/**
|
||||||
|
* @return Nodes of this graph.
|
||||||
/**
|
*/
|
||||||
* Find the closet node to the given point.
|
public List<Node> getNodes() {
|
||||||
*
|
return Collections.unmodifiableList(nodes);
|
||||||
* @param point
|
}
|
||||||
*
|
|
||||||
* @return Closest node to the given point.
|
/**
|
||||||
*/
|
* Find the closet node to the given point.
|
||||||
public Node findClosestNode(Point point) {
|
*
|
||||||
Node node = null;
|
* @param point
|
||||||
double minDis = Double.POSITIVE_INFINITY;
|
*
|
||||||
for (int n = 0 ; n < nodes.size(); ++n) {
|
* @return Closest node to the given point.
|
||||||
double dis = point.distanceTo(nodes.get(n).getPoint());
|
*/
|
||||||
if (dis < minDis) {
|
public Node findClosestNode(Point point) {
|
||||||
node = nodes.get(n);
|
Node node = null;
|
||||||
minDis = dis;
|
double minDis = Double.POSITIVE_INFINITY;
|
||||||
}
|
for (int n = 0; n < nodes.size(); ++n) {
|
||||||
|
double dis = point.distanceTo(nodes.get(n).getPoint());
|
||||||
|
if (dis < minDis) {
|
||||||
|
node = nodes.get(n);
|
||||||
|
minDis = dis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Map ID of this graph.
|
* @return Map ID of this graph.
|
||||||
*/
|
*/
|
||||||
public int getMapId() { return mapId; }
|
public int getMapId() {
|
||||||
|
return mapId;
|
||||||
/**
|
}
|
||||||
* @return Return the transpose graph of this graph.
|
|
||||||
*/
|
/**
|
||||||
public Graph transpose() {
|
* @return Return the transpose graph of this graph.
|
||||||
// TODO:
|
*/
|
||||||
return null;
|
public Graph transpose() {
|
||||||
}
|
// TODO:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,65 +1,73 @@
|
|||||||
package org.insa.graph;
|
package org.insa.graph;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Node implements Comparable<Node> {
|
public class Node implements Comparable<Node> {
|
||||||
|
|
||||||
// ID of the node.
|
// ID of the node.
|
||||||
private int id;
|
private final int id;
|
||||||
|
|
||||||
// Point of this graph.
|
|
||||||
private Point point;
|
|
||||||
|
|
||||||
// Successors.
|
|
||||||
private ArrayList<Arc> successors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Node corresponding to the given Point with
|
|
||||||
* an empty list of successors.
|
|
||||||
*
|
|
||||||
* @param point
|
|
||||||
*/
|
|
||||||
public Node(int id, Point point) {
|
|
||||||
this.id = id;
|
|
||||||
this.point = point;
|
|
||||||
this.successors = new ArrayList<Arc>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Point of this graph.
|
||||||
* Add a successor to this node.
|
private final Point point;
|
||||||
*
|
|
||||||
* @param arc Arc to the successor.
|
// Successors.
|
||||||
*/
|
private final ArrayList<Arc> successors;
|
||||||
protected void addSuccessor(Arc arc) {
|
|
||||||
successors.add(arc);
|
/**
|
||||||
}
|
* Create a new Node corresponding to the given Point with an empty list of
|
||||||
|
* successors.
|
||||||
/**
|
*
|
||||||
* @return ID of this node.
|
* @param point
|
||||||
*/
|
*/
|
||||||
public int getId() { return id; }
|
public Node(int id, Point point) {
|
||||||
|
this.id = id;
|
||||||
/**
|
this.point = point;
|
||||||
* @return List of successors of this node.
|
this.successors = new ArrayList<Arc>();
|
||||||
*/
|
}
|
||||||
public ArrayList<Arc> getSuccessors() { return successors; }
|
|
||||||
|
/**
|
||||||
/**
|
* Add a successor to this node.
|
||||||
* @return Point of this node.
|
*
|
||||||
*/
|
* @param arc Arc to the successor.
|
||||||
public Point getPoint() { return point; }
|
*/
|
||||||
|
protected void addSuccessor(Arc arc) {
|
||||||
@Override
|
successors.add(arc);
|
||||||
public boolean equals(Object other) {
|
}
|
||||||
if (other instanceof Node) {
|
|
||||||
return getId() == ((Node) other).getId();
|
/**
|
||||||
}
|
* @return ID of this node.
|
||||||
return false;
|
*/
|
||||||
}
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return List of successors of this node.
|
||||||
|
*/
|
||||||
|
public List<Arc> getSuccessors() {
|
||||||
|
return Collections.unmodifiableList(successors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Point of this node.
|
||||||
|
*/
|
||||||
|
public Point getPoint() {
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (other instanceof Node) {
|
||||||
|
return getId() == ((Node) other).getId();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Node other) {
|
||||||
|
return Integer.compare(getId(), other.getId());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(Node other) {
|
|
||||||
return Integer.compare(getId(), other.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,62 +5,66 @@ package org.insa.graph;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Point {
|
public class Point {
|
||||||
|
|
||||||
// Earth radius, in meters;
|
|
||||||
private static final double EARTH_RADIUS = 6378137.0 ;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute the distance between the two given points.
|
|
||||||
*
|
|
||||||
* @param long1
|
|
||||||
* @param lat1
|
|
||||||
* @param long2
|
|
||||||
* @param lat2
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static double distance(Point p1, Point p2) {
|
|
||||||
double sinLat = Math.sin(Math.toRadians(p1.getLatitude()))*Math.sin(Math.toRadians(p2.getLatitude()));
|
|
||||||
double cosLat = Math.cos(Math.toRadians(p1.getLatitude()))*Math.cos(Math.toRadians(p2.getLatitude()));
|
|
||||||
double cosLong = Math.cos(Math.toRadians(p2.getLongitude() - p1.getLongitude()));
|
|
||||||
return EARTH_RADIUS * Math.acos(sinLat+cosLat*cosLong);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Longitude and latitude of the point.
|
// Earth radius, in meters;
|
||||||
private double longitude, latitude;
|
private static final double EARTH_RADIUS = 6378137.0;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param longitude Longitude of the point, in degrees.
|
|
||||||
* @param latitude Latitude of the point, in degrees.
|
|
||||||
*/
|
|
||||||
public Point(double longitude, double latitude) {
|
|
||||||
this.longitude = longitude;
|
|
||||||
this.latitude = latitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Longitude of this point (in degrees).
|
|
||||||
*/
|
|
||||||
public double getLongitude() { return longitude; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Latitude of this point (in degrees).
|
|
||||||
*/
|
|
||||||
public double getLatitude() { return latitude; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the distance from this point to the given point
|
* Compute the distance between the two given points.
|
||||||
*
|
*
|
||||||
* @param target Target point.
|
* @param long1
|
||||||
*
|
* @param lat1
|
||||||
* @return Distane between this point and the target point, in meters.
|
* @param long2
|
||||||
*/
|
* @param lat2
|
||||||
public double distanceTo(Point target) {
|
* @return
|
||||||
return distance(this, target);
|
*/
|
||||||
}
|
public static double distance(Point p1, Point p2) {
|
||||||
|
double sinLat = Math.sin(Math.toRadians(p1.getLatitude())) * Math.sin(Math.toRadians(p2.getLatitude()));
|
||||||
|
double cosLat = Math.cos(Math.toRadians(p1.getLatitude())) * Math.cos(Math.toRadians(p2.getLatitude()));
|
||||||
|
double cosLong = Math.cos(Math.toRadians(p2.getLongitude() - p1.getLongitude()));
|
||||||
|
return EARTH_RADIUS * Math.acos(sinLat + cosLat * cosLong);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
// Longitude and latitude of the point.
|
||||||
public String toString() {
|
private final double longitude, latitude;
|
||||||
return String.format("Point(%f, %f)", getLongitude(), getLatitude());
|
|
||||||
}
|
/**
|
||||||
|
*
|
||||||
|
* @param longitude Longitude of the point, in degrees.
|
||||||
|
* @param latitude Latitude of the point, in degrees.
|
||||||
|
*/
|
||||||
|
public Point(double longitude, double latitude) {
|
||||||
|
this.longitude = longitude;
|
||||||
|
this.latitude = latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Longitude of this point (in degrees).
|
||||||
|
*/
|
||||||
|
public double getLongitude() {
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Latitude of this point (in degrees).
|
||||||
|
*/
|
||||||
|
public double getLatitude() {
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the distance from this point to the given point
|
||||||
|
*
|
||||||
|
* @param target Target point.
|
||||||
|
*
|
||||||
|
* @return Distane between this point and the target point, in meters.
|
||||||
|
*/
|
||||||
|
public double distanceTo(Point target) {
|
||||||
|
return distance(this, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Point(%f, %f)", getLongitude(), getLatitude());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,85 +1,75 @@
|
|||||||
package org.insa.graph ;
|
package org.insa.graph;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class containing information for road that may be shared
|
* Class containing information for road that may be shared by multiple arcs.
|
||||||
* by multiple arcs.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RoadInformation {
|
public class RoadInformation {
|
||||||
|
|
||||||
/**
|
|
||||||
* Road type.
|
|
||||||
*/
|
|
||||||
public enum RoadType {
|
|
||||||
MOTORWAY,
|
|
||||||
TRUNK,
|
|
||||||
PRIMARY,
|
|
||||||
SECONDARY,
|
|
||||||
MOTORWAY_LINK,
|
|
||||||
TRUNK_LINK,
|
|
||||||
PRIMARY_LINK,
|
|
||||||
SECONDARY_LINK,
|
|
||||||
TERTIARY,
|
|
||||||
RESIDENTIAL,
|
|
||||||
UNCLASSIFIED,
|
|
||||||
ROAD,
|
|
||||||
LIVING_STREET,
|
|
||||||
SERVICE,
|
|
||||||
ROUNDABOUT,
|
|
||||||
COASTLINE
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type of the road (see above).
|
/**
|
||||||
private RoadType type;
|
* Road type.
|
||||||
|
*/
|
||||||
|
public enum RoadType {
|
||||||
|
MOTORWAY, TRUNK, PRIMARY, SECONDARY, MOTORWAY_LINK, TRUNK_LINK, PRIMARY_LINK, SECONDARY_LINK, TERTIARY, RESIDENTIAL, UNCLASSIFIED, ROAD, LIVING_STREET, SERVICE, ROUNDABOUT, COASTLINE
|
||||||
|
}
|
||||||
|
|
||||||
// One way road?
|
// Type of the road (see above).
|
||||||
private boolean oneway;
|
private final RoadType type;
|
||||||
|
|
||||||
// Max speed in kilometers per hour.
|
// One way road?
|
||||||
private int maxSpeed;
|
private final boolean oneway;
|
||||||
|
|
||||||
// Name of the road.
|
// Max speed in kilometers per hour.
|
||||||
private String name;
|
private final int maxSpeed;
|
||||||
|
|
||||||
public RoadInformation(RoadType roadType, boolean isOneWay, int maxSpeed, String name) {
|
// Name of the road.
|
||||||
this.type = roadType;
|
private final String name;
|
||||||
this.oneway = isOneWay;
|
|
||||||
this.maxSpeed = maxSpeed;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Type of the road.
|
|
||||||
*/
|
|
||||||
public RoadType getType() { return type; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if this is a one-way road.
|
|
||||||
*/
|
|
||||||
public boolean isOneWay() { return oneway; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Maximum speed for this road (in km/h).
|
|
||||||
*/
|
|
||||||
public int getMaximumSpeed() { return maxSpeed; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Name of the road.
|
|
||||||
*/
|
|
||||||
public String getName() { return name; }
|
|
||||||
|
|
||||||
@Override
|
public RoadInformation(RoadType roadType, boolean isOneWay, int maxSpeed, String name) {
|
||||||
public String toString() {
|
this.type = roadType;
|
||||||
String typeAsString = "road";
|
this.oneway = isOneWay;
|
||||||
if (getType() == RoadType.COASTLINE) {
|
this.maxSpeed = maxSpeed;
|
||||||
typeAsString = "coast";
|
this.name = name;
|
||||||
}
|
}
|
||||||
if (getType() == RoadType.MOTORWAY) {
|
|
||||||
typeAsString = "highway";
|
/**
|
||||||
}
|
* @return Type of the road.
|
||||||
return typeAsString + " : " + getName()
|
*/
|
||||||
+ " " + (isOneWay() ? " (oneway) " : "")
|
public RoadType getType() {
|
||||||
+ maxSpeed + " km/h (max.)";
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if this is a one-way road.
|
||||||
|
*/
|
||||||
|
public boolean isOneWay() {
|
||||||
|
return oneway;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Maximum speed for this road (in km/h).
|
||||||
|
*/
|
||||||
|
public int getMaximumSpeed() {
|
||||||
|
return maxSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Name of the road.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String typeAsString = "road";
|
||||||
|
if (getType() == RoadType.COASTLINE) {
|
||||||
|
typeAsString = "coast";
|
||||||
|
}
|
||||||
|
if (getType() == RoadType.MOTORWAY) {
|
||||||
|
typeAsString = "highway";
|
||||||
|
}
|
||||||
|
return typeAsString + " : " + getName() + " " + (isOneWay() ? " (oneway) " : "") + maxSpeed + " km/h (max.)";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ import java.awt.event.MouseListener;
|
|||||||
import java.awt.geom.NoninvertibleTransformException;
|
import java.awt.geom.NoninvertibleTransformException;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@ -238,14 +238,12 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
/**
|
/**
|
||||||
* Draw the given arc.
|
* Draw the given arc.
|
||||||
*
|
*
|
||||||
* @param arc
|
* @param arc Arc to draw.
|
||||||
* Arc to draw.
|
* @param palette Palette to use to retrieve color and width for arc, or null to
|
||||||
* @param palette
|
* use current settings.
|
||||||
* Palette to use to retrieve color and width for arc, or null to use
|
|
||||||
* current settings.
|
|
||||||
*/
|
*/
|
||||||
public void drawArc(Arc arc, GraphPalette palette) {
|
public void drawArc(Arc arc, GraphPalette palette) {
|
||||||
ArrayList<Point> pts = arc.getPoints();
|
List<Point> pts = arc.getPoints();
|
||||||
if (!pts.isEmpty()) {
|
if (!pts.isEmpty()) {
|
||||||
if (palette != null) {
|
if (palette != null) {
|
||||||
setColor(palette.getColorForType(arc.getInfo().getType()));
|
setColor(palette.getColorForType(arc.getInfo().getType()));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.insa.graphics.drawing.utils;
|
package org.insa.graphics.drawing.utils;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.ArrayList;
|
import java.util.List;
|
||||||
|
|
||||||
import org.insa.graph.Point;
|
import org.insa.graph.Point;
|
||||||
import org.mapsforge.core.graphics.Canvas;
|
import org.mapsforge.core.graphics.Canvas;
|
||||||
@ -41,7 +41,7 @@ public class PolylineAutoScaling extends Polyline {
|
|||||||
/**
|
/**
|
||||||
* @param points
|
* @param points
|
||||||
*/
|
*/
|
||||||
public void add(ArrayList<Point> points) {
|
public void add(List<Point> points) {
|
||||||
for (Point point: points) {
|
for (Point point: points) {
|
||||||
add(point);
|
add(point);
|
||||||
}
|
}
|
||||||
|
@ -1,60 +1,53 @@
|
|||||||
package org.insa.graph.io;
|
package org.insa.graph.io;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.List;
|
||||||
|
|
||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
import org.insa.graph.Node;
|
import org.insa.graph.Node;
|
||||||
import org.insa.graph.Point;
|
import org.insa.graph.Point;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
|
||||||
|
|
||||||
public class BinaryGraphReaderTest {
|
public class BinaryGraphReaderTest {
|
||||||
|
|
||||||
// Epsilon for latitude and longitude.
|
|
||||||
private static final double EPS = 1e-5;
|
|
||||||
|
|
||||||
private static Graph midip;
|
|
||||||
|
|
||||||
@BeforeAll
|
// Epsilon for latitude and longitude.
|
||||||
|
private static final double EPS = 1e-5;
|
||||||
|
|
||||||
|
private static Graph midip;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
static void initAll() throws IOException {
|
static void initAll() throws IOException {
|
||||||
BinaryGraphReader reader = new BinaryGraphReader(Openfile.open("midip"));
|
BinaryGraphReader reader = new BinaryGraphReader(Openfile.open("midip"));
|
||||||
midip = reader.read();
|
midip = reader.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertPointAt(Point p1, double longitude, double latitude) {
|
||||||
|
assertEquals(p1.getLongitude(), longitude, EPS);
|
||||||
|
assertEquals(p1.getLatitude(), latitude, EPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertPointAt(Point p1, double longitude, double latitude) {
|
|
||||||
assertEquals(p1.getLongitude(), longitude, EPS);
|
|
||||||
assertEquals(p1.getLatitude(), latitude, EPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testMidipNodes() {
|
void testMidipNodes() {
|
||||||
ArrayList<Node> nodes = midip.getNodes();
|
List<Node> nodes = midip.getNodes();
|
||||||
|
|
||||||
assertEquals(nodes.size(), 150827);
|
assertEquals(nodes.size(), 150827);
|
||||||
|
|
||||||
// Check the locations of some nodes.
|
// Check the locations of some nodes.
|
||||||
assertPointAt(nodes.get(58411).getPoint(), 1.799864, 43.92864);
|
assertPointAt(nodes.get(58411).getPoint(), 1.799864, 43.92864);
|
||||||
assertPointAt(nodes.get(133312).getPoint(), 0.539752, 43.317505);
|
assertPointAt(nodes.get(133312).getPoint(), 0.539752, 43.317505);
|
||||||
assertPointAt(nodes.get(113688).getPoint(), 1.682739, 44.799774);
|
assertPointAt(nodes.get(113688).getPoint(), 1.682739, 44.799774);
|
||||||
assertPointAt(nodes.get(118141).getPoint(), 0.274857, 43.47475);
|
assertPointAt(nodes.get(118141).getPoint(), 0.274857, 43.47475);
|
||||||
assertPointAt(nodes.get(146918).getPoint(), 0.116148, 43.811386);
|
assertPointAt(nodes.get(146918).getPoint(), 0.116148, 43.811386);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testMidipArcs() {
|
void testMidipArcs() {
|
||||||
// TODO: Check the number of edges.
|
// TODO: Check the number of edges.
|
||||||
// TODO: Check information for some edges.
|
// TODO: Check information for some edges.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user