Update.
This commit is contained in:
parent
65c81b9921
commit
cfb59ac0f1
37 changed files with 1511 additions and 473 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.DS_Store
|
||||
bin
|
|
@ -1,24 +1,42 @@
|
|||
package org.insa.algo ;
|
||||
|
||||
import java.io.* ;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class AbstractAlgorithm {
|
||||
public abstract class AbstractAlgorithm implements Runnable {
|
||||
|
||||
protected PrintStream output;
|
||||
protected AbstractInstance instance;
|
||||
protected AbstractSolution solution;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param instance
|
||||
* @param logOutput
|
||||
*/
|
||||
protected AbstractAlgorithm(AbstractInstance instance, PrintStream logOutput) {
|
||||
protected ArrayList<AbstractObserver> observers;
|
||||
|
||||
protected AbstractAlgorithm(AbstractInstance instance) {
|
||||
this.instance = instance;
|
||||
this.observers = new ArrayList<AbstractObserver>();
|
||||
this.solution = null;
|
||||
}
|
||||
|
||||
protected AbstractAlgorithm(AbstractInstance instance, ArrayList<AbstractObserver> observers) {
|
||||
this.instance = instance;
|
||||
this.output = logOutput;
|
||||
this.observers = observers;;
|
||||
this.solution = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an observer to this algorithm.
|
||||
*
|
||||
* @param observer
|
||||
*/
|
||||
public void addObserver(AbstractObserver observer) {
|
||||
observers.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The list of observers for this algorithm.
|
||||
*/
|
||||
public ArrayList<AbstractObserver> getObservers() {
|
||||
return observers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current solution.
|
||||
*
|
||||
|
@ -44,9 +62,8 @@ public abstract class AbstractAlgorithm {
|
|||
*
|
||||
* @return true if a feasible solution was found (even non-optimal).
|
||||
*/
|
||||
public boolean run() {
|
||||
public void run() {
|
||||
this.solution = this.doRun();
|
||||
return this.solution != null && this.solution.isFeasible();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
20
src/main/org/insa/algo/AbstractObserver.java
Normal file
20
src/main/org/insa/algo/AbstractObserver.java
Normal file
|
@ -0,0 +1,20 @@
|
|||
package org.insa.algo;
|
||||
|
||||
public abstract class AbstractObserver {
|
||||
|
||||
// Specify if the observer is graphic or not.
|
||||
private final boolean isgraphic;
|
||||
|
||||
protected AbstractObserver(boolean isGraphic) {
|
||||
this.isgraphic = isGraphic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this observer is graphic (use drawing to display
|
||||
* information).
|
||||
*/
|
||||
public boolean isGraphic() {
|
||||
return isgraphic;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package org.insa.algo.connectivity ;
|
||||
|
||||
import java.io.* ;
|
||||
|
||||
import org.insa.algo.AbstractAlgorithm;
|
||||
import org.insa.algo.AbstractSolution;
|
||||
|
||||
public class ConnectivityAlgorithm extends AbstractAlgorithm {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param instance
|
||||
* @param logOutput
|
||||
*/
|
||||
public ConnectivityAlgorithm(ConnectivityInstance instance, PrintStream logOutput) {
|
||||
super(instance, logOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected AbstractSolution doRun() {
|
||||
ConnectivityInstance instance = (ConnectivityInstance)getInstance();
|
||||
ConnectivitySolution solution = null;
|
||||
// TODO:
|
||||
return solution;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package org.insa.algo.connectivity;
|
||||
|
||||
import org.insa.algo.AbstractInstance;
|
||||
import org.insa.graph.Graph;
|
||||
|
||||
public class ConnectivityInstance extends AbstractInstance {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
public ConnectivityInstance(Graph graph) {
|
||||
super(graph);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package org.insa.algo.connectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.insa.algo.AbstractSolution;
|
||||
|
||||
public class ConnectivitySolution extends AbstractSolution {
|
||||
|
||||
protected ConnectivitySolution(ConnectivityInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
protected ConnectivitySolution(ConnectivityInstance instance,
|
||||
Duration solvingTime, Status status) {
|
||||
super(instance, solvingTime, status);
|
||||
|
||||
// TODO:
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.insa.algo.strongconnectivity ;
|
||||
|
||||
import org.insa.algo.AbstractAlgorithm;
|
||||
|
||||
public abstract class StronglyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param instance
|
||||
* @param logOutput
|
||||
*/
|
||||
public StronglyConnectedComponentsAlgorithm(StronglyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.insa.algo.strongconnectivity;
|
||||
|
||||
import org.insa.algo.AbstractInstance;
|
||||
import org.insa.graph.Graph;
|
||||
|
||||
public class StronglyConnectedComponentsInstance extends AbstractInstance {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
public StronglyConnectedComponentsInstance(Graph graph) {
|
||||
super(graph);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.insa.algo.strongconnectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.algo.AbstractSolution;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class StronglyConnectedComponentsSolution extends AbstractSolution {
|
||||
|
||||
// Components
|
||||
private ArrayList<ArrayList<Node>> components;
|
||||
|
||||
protected StronglyConnectedComponentsSolution(StronglyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
protected StronglyConnectedComponentsSolution(StronglyConnectedComponentsInstance instance,
|
||||
Duration solvingTime, Status status, ArrayList<ArrayList<Node>> components) {
|
||||
super(instance, solvingTime, status);
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Components of the solution, if any.
|
||||
*/
|
||||
public ArrayList<ArrayList<Node>> getComponents() { return components; }
|
||||
|
||||
}
|
155
src/main/org/insa/algo/strongconnectivity/TarjanAlgorithm.java
Normal file
155
src/main/org/insa/algo/strongconnectivity/TarjanAlgorithm.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
package org.insa.algo.strongconnectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.insa.algo.AbstractSolution;
|
||||
import org.insa.algo.AbstractSolution.Status;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class TarjanAlgorithm extends StronglyConnectedComponentsAlgorithm {
|
||||
|
||||
private final static int UNDEFINED = -1;
|
||||
|
||||
// Stack of nodes and flags.
|
||||
private Stack<Node> stack;
|
||||
private boolean[] inStack;
|
||||
|
||||
// Current index.
|
||||
private int index;
|
||||
|
||||
// Information of nodes
|
||||
private int[] indexes;
|
||||
private int[] lowlink;
|
||||
|
||||
// Array of strongly connected components
|
||||
ArrayList<ArrayList<Node>> components;
|
||||
|
||||
public TarjanAlgorithm(StronglyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the given node to the stack.
|
||||
*
|
||||
* @param node
|
||||
*/
|
||||
protected void pushNode(Node node) {
|
||||
stack.push(node);
|
||||
inStack[node.getId()] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop and return a node from the stack.
|
||||
*
|
||||
* @return Node popped from the stack
|
||||
*/
|
||||
protected Node popNode() {
|
||||
Node top = stack.pop();
|
||||
inStack[top.getId()] = false;
|
||||
return top;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given node is in the stack.
|
||||
*
|
||||
* @param node
|
||||
*
|
||||
* @return true if the given node is in the stack, false otherwize.
|
||||
*/
|
||||
protected boolean isInStack(Node node) {
|
||||
return inStack[node.getId()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the strong component containing the given node.
|
||||
*
|
||||
* @param node
|
||||
*
|
||||
* @return The strong component containing the given node.
|
||||
*/
|
||||
protected void findAndAddStrongComponent(Node v) {
|
||||
Graph graph = getInstance().getGraph();
|
||||
|
||||
// Update node info, index and push the node.
|
||||
indexes[v.getId()] = index;
|
||||
lowlink[v.getId()] = index;
|
||||
index += 1;
|
||||
pushNode(v);
|
||||
|
||||
for (Arc a: v.getSuccessors()) {
|
||||
Node w = a.getDestination();
|
||||
if (!hasBeenVisited(w)) {
|
||||
findAndAddStrongComponent(w);
|
||||
lowlink[v.getId()] = Math.min(lowlink[v.getId()], lowlink[w.getId()]);
|
||||
}
|
||||
else if (isInStack(w)) {
|
||||
lowlink[v.getId()] = Math.min(lowlink[v.getId()], indexes[w.getId()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the component (if any)
|
||||
if (lowlink[v.getId()] == indexes[v.getId()]) {
|
||||
ArrayList<Node> component = new ArrayList<Node>();
|
||||
Node w;
|
||||
do {
|
||||
w = popNode();
|
||||
component.add(w);
|
||||
} while (!w.equals(v));
|
||||
components.add(component);
|
||||
System.out.println("Size of the stack: " + stack.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given node has not been visited yet.
|
||||
*
|
||||
* @return true if the node has been visited.
|
||||
*/
|
||||
protected boolean hasBeenVisited(Node node) {
|
||||
return this.indexes[node.getId()] != UNDEFINED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractSolution doRun() {
|
||||
Graph graph = getInstance().getGraph();
|
||||
|
||||
components = new ArrayList<ArrayList<Node>>();
|
||||
|
||||
// Starting time...
|
||||
Instant start = Instant.now();
|
||||
|
||||
// Initialize everything
|
||||
final int nbNodes = graph.getNodes().size();
|
||||
stack = new Stack<Node>();
|
||||
inStack = new boolean[nbNodes];
|
||||
|
||||
// Current index.
|
||||
index = 0;
|
||||
|
||||
// Information of nodes
|
||||
indexes = new int[nbNodes];
|
||||
Arrays.fill(indexes, UNDEFINED);
|
||||
lowlink = new int[nbNodes];
|
||||
|
||||
// Find components
|
||||
for (Node node: graph.getNodes()) {
|
||||
if (!hasBeenVisited(node)) {
|
||||
findAndAddStrongComponent(node);
|
||||
}
|
||||
}
|
||||
|
||||
// Duration...
|
||||
Duration solvingTime = Duration.between(start, Instant.now());
|
||||
|
||||
return new StronglyConnectedComponentsSolution((StronglyConnectedComponentsInstance)getInstance(),
|
||||
solvingTime, Status.OPTIMAL, components);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.drawing.Drawing;
|
||||
import org.insa.drawing.graph.GraphDrawing;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class WeaklyConnectedComponentGraphicObserver extends WeaklyConnectedComponentObserver {
|
||||
|
||||
private static final Color[] COLORS = {
|
||||
Color.BLUE, Color.ORANGE, Color.GREEN, Color.YELLOW, Color.RED
|
||||
};
|
||||
|
||||
// Drawing + Graph drawing
|
||||
private Drawing drawing;
|
||||
private GraphDrawing gdrawing;
|
||||
|
||||
// Current index color
|
||||
private int cindex = 0;
|
||||
|
||||
public WeaklyConnectedComponentGraphicObserver(Drawing drawing) {
|
||||
super(true);
|
||||
this.drawing = drawing;
|
||||
this.gdrawing = new GraphDrawing(drawing);
|
||||
this.drawing.setAutoRepaint(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyStartComponent(Node curNode) {
|
||||
this.drawing.setColor(COLORS[cindex]);
|
||||
cindex = (cindex + 1) % COLORS.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNewNodeInComponent(Node node) {
|
||||
this.gdrawing.drawPoint(node.getPoint(), 5);
|
||||
this.drawing.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEndComponent(ArrayList<Node> nodes) {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.algo.AbstractObserver;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public abstract class WeaklyConnectedComponentObserver extends AbstractObserver {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected WeaklyConnectedComponentObserver(boolean isGraphic) {
|
||||
super(isGraphic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify that the algorithm is entering a new component.
|
||||
*
|
||||
* @param curNode Starting node for the component.
|
||||
*/
|
||||
public abstract void notifyStartComponent(Node curNode);
|
||||
|
||||
/**
|
||||
* Notify that a new node has been found for the current component.
|
||||
*
|
||||
* @param node New node found for the current component.
|
||||
*/
|
||||
public abstract void notifyNewNodeInComponent(Node node);
|
||||
|
||||
/**
|
||||
* Notify that the algorithm has computed a new component.
|
||||
*
|
||||
* @param nodes List of nodes in the component.
|
||||
*/
|
||||
public abstract void notifyEndComponent(ArrayList<Node> nodes);
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class WeaklyConnectedComponentTextObserver extends WeaklyConnectedComponentObserver {
|
||||
|
||||
// Number of the current component.
|
||||
private int numComponent = 1;
|
||||
|
||||
// Output stream
|
||||
PrintStream stream;
|
||||
|
||||
public WeaklyConnectedComponentTextObserver(PrintStream stream) {
|
||||
super(false);
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyStartComponent(Node curNode) {
|
||||
stream.print("Entering component #" + numComponent + " from node #" + curNode.getId() + "... ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNewNodeInComponent(Node node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEndComponent(ArrayList<Node> nodes) {
|
||||
stream.println(nodes.size() + " nodes found.");
|
||||
stream.flush();
|
||||
numComponent += 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.insa.algo.AbstractAlgorithm;
|
||||
import org.insa.algo.AbstractObserver;
|
||||
import org.insa.algo.AbstractSolution;
|
||||
import org.insa.algo.AbstractSolution.Status;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param instance
|
||||
* @param logOutput
|
||||
*/
|
||||
public WeaklyConnectedComponentsAlgorithm(WeaklyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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>();
|
||||
|
||||
for (AbstractObserver obs: getObservers()) {
|
||||
((WeaklyConnectedComponentObserver)obs).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
|
||||
for (AbstractObserver obs: getObservers()) ((WeaklyConnectedComponentObserver)obs).notifyNewNodeInComponent(node);
|
||||
|
||||
for (Integer destId: ugraph.get(node.getId())) {
|
||||
Node dest = nodes.get(destId);
|
||||
if (!marked[dest.getId()]) {
|
||||
queue.add(destId);
|
||||
marked[destId] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (AbstractObserver obs: getObservers()) {
|
||||
((WeaklyConnectedComponentObserver)obs).notifyEndComponent(component);
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractSolution doRun() {
|
||||
|
||||
Instant start = Instant.now();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Duration solvingTime = Duration.between(start, Instant.now());
|
||||
|
||||
return new WeaklyConnectedComponentsSolution((WeaklyConnectedComponentsInstance)getInstance(),
|
||||
solvingTime, Status.OPTIMAL, components);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import org.insa.algo.AbstractInstance;
|
||||
import org.insa.graph.Graph;
|
||||
|
||||
public class WeaklyConnectedComponentsInstance extends AbstractInstance {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
public WeaklyConnectedComponentsInstance(Graph graph) {
|
||||
super(graph);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.algo.AbstractSolution;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class WeaklyConnectedComponentsSolution extends AbstractSolution {
|
||||
|
||||
// Components
|
||||
private ArrayList<ArrayList<Node>> components;
|
||||
|
||||
protected WeaklyConnectedComponentsSolution(WeaklyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
protected WeaklyConnectedComponentsSolution(WeaklyConnectedComponentsInstance instance,
|
||||
Duration solvingTime, Status status, ArrayList<ArrayList<Node>> components) {
|
||||
super(instance, solvingTime, status);
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Components of the solution, if any.
|
||||
*/
|
||||
public ArrayList<ArrayList<Node>> getComponents() { return components; }
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package org.insa.base ;
|
||||
|
||||
/**
|
||||
* Choix des couleurs pour l'affichage.
|
||||
*/
|
||||
|
||||
import java.awt.* ;
|
||||
|
||||
import org.insa.drawing.Drawing;
|
||||
|
||||
public class Couleur {
|
||||
|
||||
static final Color autoroute = Color.red ;
|
||||
static final Color bigroute = new Color(255, 105, 0) ;
|
||||
static final Color tiroute = new Color(255, 234, 0) ;
|
||||
static final Color cote = Color.blue ;
|
||||
|
||||
public static void set(Drawing d, char type) {
|
||||
|
||||
// Voir le fichier Descripteur.java pour le type des routes.
|
||||
switch (type) {
|
||||
case 'a':
|
||||
d.setWidth(2) ;
|
||||
d.setColor(Color.red) ;
|
||||
break ;
|
||||
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
d.setWidth(1) ;
|
||||
d.setColor(bigroute) ;
|
||||
break ;
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
d.setWidth(1) ;
|
||||
d.setColor(tiroute) ;
|
||||
break ;
|
||||
|
||||
case 'z':
|
||||
d.setWidth(4) ;
|
||||
d.setColor(cote) ;
|
||||
break ;
|
||||
|
||||
default:
|
||||
d.setWidth(1) ;
|
||||
d.setColor(Color.black) ;
|
||||
}
|
||||
}
|
||||
}
|
340
src/main/org/insa/base/MainWindow.java
Normal file
340
src/main/org/insa/base/MainWindow.java
Normal file
|
@ -0,0 +1,340 @@
|
|||
package org.insa.base;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver;
|
||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentTextObserver;
|
||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm;
|
||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsInstance;
|
||||
import org.insa.drawing.DrawingVisible;
|
||||
import org.insa.drawing.graph.BlackAndWhiteGraphPalette;
|
||||
import org.insa.drawing.graph.GraphDrawing;
|
||||
import org.insa.drawing.graph.PathDrawing;
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.Path;
|
||||
import org.insa.graph.io.BinaryGraphReader;
|
||||
import org.insa.graph.io.BinaryPathReader;
|
||||
import org.insa.graph.io.MapMismatchException;
|
||||
import org.insa.graph.io.Openfile;
|
||||
|
||||
import com.sun.glass.events.KeyEvent;
|
||||
|
||||
public class MainWindow extends JFrame {
|
||||
|
||||
public class JOutputStream extends OutputStream {
|
||||
private JTextArea textArea;
|
||||
|
||||
public JOutputStream(JTextArea textArea) {
|
||||
this.textArea = textArea;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
// redirects data to the text area
|
||||
textArea.setText(textArea.getText() + String.valueOf((char)b));
|
||||
// scrolls the text area to the end of data
|
||||
textArea.setCaretPosition(textArea.getDocument().getLength());
|
||||
// keeps the textArea up to date
|
||||
textArea.update(textArea.getGraphics());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -527660583705140687L;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String WINDOW_TITLE = "BE Graphes INSA";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final Dimension DEFAULT_DIMENSION = new Dimension(800, 600);
|
||||
|
||||
// Current graph.
|
||||
private Graph graph;
|
||||
|
||||
// Current loaded path.
|
||||
private Path currentPath;
|
||||
|
||||
// List of item for the top menus.
|
||||
private JMenuItem openMapItem;
|
||||
|
||||
// List of items that cannot be used without a graph
|
||||
private ArrayList<JMenuItem> graphItems = new ArrayList<JMenuItem>();
|
||||
|
||||
// Label containing the map ID of the current graph.
|
||||
private JLabel mapIdPanel;
|
||||
|
||||
// Log stream and print stream
|
||||
private JOutputStream logStream;
|
||||
private PrintStream printStream;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private DrawingVisible drawing;
|
||||
|
||||
public MainWindow() {
|
||||
super(WINDOW_TITLE);
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
setLayout(new BorderLayout());
|
||||
setSize(DEFAULT_DIMENSION);
|
||||
setJMenuBar(createMenuBar());
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
int confirmed = JOptionPane.showConfirmDialog(null,
|
||||
"Are you sure you want to close the application?", "Exit Confirmation",
|
||||
JOptionPane.YES_NO_OPTION);
|
||||
|
||||
if (confirmed == JOptionPane.YES_OPTION) {
|
||||
dispose();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create graph area
|
||||
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||
|
||||
drawing = new DrawingVisible();
|
||||
drawing.setBackground(Color.WHITE);
|
||||
|
||||
JTextArea infoPanel = new JTextArea();
|
||||
infoPanel.setMinimumSize(new Dimension(200, 50));
|
||||
// infoPanel.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, Color.GRAY));
|
||||
infoPanel.setBackground(Color.WHITE);
|
||||
infoPanel.setLineWrap(true);
|
||||
infoPanel.setEditable(false);
|
||||
this.logStream = new JOutputStream(infoPanel);
|
||||
this.printStream = new PrintStream(this.logStream);
|
||||
|
||||
sp.setResizeWeight(0.8);
|
||||
// sp.setEnabled(false);
|
||||
sp.setDividerSize(5);
|
||||
|
||||
sp.setBackground(Color.WHITE);
|
||||
sp.add(drawing);
|
||||
sp.add(new JScrollPane(infoPanel));
|
||||
this.add(sp, BorderLayout.CENTER);
|
||||
|
||||
this.add(createStatusBar(), BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
private JMenuBar createMenuBar() {
|
||||
|
||||
// Open Map item...
|
||||
openMapItem = new JMenuItem("Open Map... ",
|
||||
KeyEvent.VK_O);
|
||||
openMapItem.setAccelerator(KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_O, ActionEvent.ALT_MASK));
|
||||
openMapItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
FileNameExtensionFilter filter = new FileNameExtensionFilter(
|
||||
"Map & compressed map files", "map", "map.gz");
|
||||
chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
||||
chooser.setFileFilter(filter);
|
||||
if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
|
||||
BinaryGraphReader reader;
|
||||
try {
|
||||
reader = new BinaryGraphReader(
|
||||
Openfile.open(chooser.getSelectedFile().getAbsolutePath()));
|
||||
} catch (IOException e1) {
|
||||
JOptionPane.showMessageDialog(MainWindow.this, "Cannot open the selected file.");
|
||||
return ;
|
||||
}
|
||||
try {
|
||||
graph = reader.read();
|
||||
}
|
||||
catch (Exception exception) {
|
||||
JOptionPane.showMessageDialog(MainWindow.this, "Unable to read graph from the selected file.");
|
||||
return ;
|
||||
}
|
||||
drawing.clear();
|
||||
new GraphDrawing(drawing).drawGraph(graph);
|
||||
|
||||
for (JMenuItem item: graphItems) {
|
||||
item.setEnabled(true);
|
||||
}
|
||||
mapIdPanel.setText("Map ID: 0x" + Integer.toHexString(graph.getMapId()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Open Path item...
|
||||
JMenuItem openPathItem = new JMenuItem("Open Path... ", KeyEvent.VK_P);
|
||||
openPathItem.setAccelerator(KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_P, ActionEvent.ALT_MASK));
|
||||
openPathItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
FileNameExtensionFilter filter = new FileNameExtensionFilter(
|
||||
"Path & compressed path files", "path", "path.gz");
|
||||
chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
||||
chooser.setFileFilter(filter);
|
||||
if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
|
||||
BinaryPathReader reader;
|
||||
try {
|
||||
reader = new BinaryPathReader(
|
||||
Openfile.open(chooser.getSelectedFile().getAbsolutePath()));
|
||||
} catch (IOException e1) {
|
||||
JOptionPane.showMessageDialog(MainWindow.this, "Cannot open the selected file.");
|
||||
return ;
|
||||
}
|
||||
try {
|
||||
currentPath = reader.readPath(graph);
|
||||
}
|
||||
catch (MapMismatchException exception) {
|
||||
JOptionPane.showMessageDialog(MainWindow.this, "The selected file does not contain a path for the current graph.");
|
||||
return;
|
||||
}
|
||||
catch (Exception exception) {
|
||||
JOptionPane.showMessageDialog(MainWindow.this, "Unable to read path from the selected file.");
|
||||
return ;
|
||||
}
|
||||
new PathDrawing(drawing).drawPath(currentPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
graphItems.add(openPathItem);
|
||||
|
||||
// Close item
|
||||
JMenuItem closeItem = new JMenuItem("Quit", KeyEvent.VK_Q);
|
||||
closeItem.setAccelerator(KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_Q, ActionEvent.ALT_MASK));
|
||||
closeItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MainWindow.this.dispatchEvent(new WindowEvent(MainWindow.this, WindowEvent.WINDOW_CLOSING));
|
||||
}
|
||||
});
|
||||
|
||||
//Build the first menu.
|
||||
JMenu fileMenu = new JMenu("File");
|
||||
fileMenu.add(openMapItem);
|
||||
fileMenu.add(openPathItem);
|
||||
fileMenu.addSeparator();
|
||||
fileMenu.add(closeItem);
|
||||
|
||||
// Second menu
|
||||
JMenuItem drawGraphItem = new JMenuItem("Redraw", KeyEvent.VK_R);
|
||||
drawGraphItem.setAccelerator(KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_R, ActionEvent.ALT_MASK));
|
||||
drawGraphItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
drawing.clear();
|
||||
drawing.setAutoRepaint(true);
|
||||
new GraphDrawing(drawing).drawGraph(graph);
|
||||
drawing.setAutoRepaint(false);
|
||||
}
|
||||
});
|
||||
graphItems.add(drawGraphItem);
|
||||
JMenuItem drawGraphBWItem = new JMenuItem("Redraw (B&W)", KeyEvent.VK_B);
|
||||
drawGraphBWItem.setAccelerator(KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_B, ActionEvent.ALT_MASK));
|
||||
drawGraphBWItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
drawing.clear();
|
||||
drawing.setAutoRepaint(true);
|
||||
new GraphDrawing(drawing, new BlackAndWhiteGraphPalette()).drawGraph(graph);
|
||||
drawing.setAutoRepaint(false);
|
||||
}
|
||||
});
|
||||
graphItems.add(drawGraphBWItem);
|
||||
|
||||
JMenu graphMenu = new JMenu("Graph");
|
||||
graphMenu.add(drawGraphItem);
|
||||
graphMenu.add(drawGraphBWItem);
|
||||
|
||||
// Algo menu
|
||||
JMenu algoMenu = new JMenu("Algorithms");
|
||||
|
||||
JMenuItem wccItem = new JMenuItem("Weakly Connected Components");
|
||||
wccItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
WeaklyConnectedComponentsInstance instance = new WeaklyConnectedComponentsInstance(graph);
|
||||
WeaklyConnectedComponentsAlgorithm algo = new WeaklyConnectedComponentsAlgorithm(instance);
|
||||
algo.addObserver(new WeaklyConnectedComponentGraphicObserver(drawing));
|
||||
|
||||
(new Thread(algo)).start();
|
||||
}
|
||||
});
|
||||
graphItems.add(wccItem);
|
||||
|
||||
algoMenu.add(wccItem);
|
||||
|
||||
// Create the menu bar.
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
|
||||
menuBar.add(fileMenu);
|
||||
menuBar.add(graphMenu);
|
||||
menuBar.add(algoMenu);
|
||||
|
||||
for (JMenuItem item: graphItems) {
|
||||
item.setEnabled(false);
|
||||
}
|
||||
|
||||
return menuBar;
|
||||
}
|
||||
|
||||
private JPanel createStatusBar() {
|
||||
// create the status bar panel and shove it down the bottom of the frame
|
||||
JPanel statusPanel = new JPanel();
|
||||
statusPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.GRAY));
|
||||
statusPanel.setPreferredSize(new Dimension(getWidth(), 20));
|
||||
statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.X_AXIS));
|
||||
|
||||
mapIdPanel = new JLabel();
|
||||
mapIdPanel.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
statusPanel.add(mapIdPanel);
|
||||
|
||||
return statusPanel;
|
||||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
MainWindow w = new MainWindow();
|
||||
w.setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
w.setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package org.insa.base ;
|
||||
|
||||
import java.io.* ;
|
||||
import java.util.zip.* ;
|
||||
|
||||
/* Ne lisez pas cette classe. Lancez javadoc et lisez la doc generee plutot. */
|
||||
|
||||
/**
|
||||
* La classe Openfile permet de lire les fichiers contenant les cartes :
|
||||
* <ul>
|
||||
* <li> en trouvant le bon dossier parmi les dossiers pre-configures </li>
|
||||
* <li> en dezippant automatiquement si besoin </li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
public class Openfile {
|
||||
|
||||
// Le programme examine chaque dossier dans l'ordre jusqu'a trouver celui qui contient la carte voulue
|
||||
private static final String[] datadirs =
|
||||
{ // NE MODIFIEZ PAS CELUI-CI
|
||||
// car il permet de tester en etant a l'INSA.
|
||||
"/home/commetud/3eme Annee MIC/Graphes-et-Algorithmes/Maps",
|
||||
|
||||
// Celui-ci pour les chemins
|
||||
"/home/commetud/3eme Annee MIC/Graphes-et-Algorithmes/",
|
||||
|
||||
// On cherche aussi dans le sous-repertoire local "Maps" (s'il existe)
|
||||
"Maps",
|
||||
|
||||
// et dans le repertoire courant (Unix uniquement)
|
||||
".",
|
||||
|
||||
// Si vous utilisez votre propre dossier pour les donnees, mettez-le ici.
|
||||
"/home/votrepropredossier/a/vous",
|
||||
} ;
|
||||
|
||||
// Extension testees. Garder l'extension vide dans la liste.
|
||||
private static final String[] extensions = { ".map", ".gz", ".map.gz", ".path", ".path.gz", "" } ;
|
||||
|
||||
/**
|
||||
* Ouvre le fichier indiqué et renvoie un DataInputStream sur ce fichier.
|
||||
* Le fichier ne sera pas ferme avant la fin de l'application.
|
||||
* @param filename Nom du fichier a ouvrir (sans chemin)
|
||||
*/
|
||||
public static DataInputStream open (String filename) {
|
||||
|
||||
if (!filename.equals (new File(filename).getName())) {
|
||||
System.out.println("Le nom du fichier ne doit pas contenir un chemin (ni absolu, ni relatif).") ;
|
||||
System.out.println("Il doit juste contenir le nom du fichier contenant la carte.") ;
|
||||
System.out.println("Si vous voulez utiliser un dossier specifique, configurez base/Openfile.java") ;
|
||||
System.exit(1) ;
|
||||
}
|
||||
|
||||
boolean trouve = false ;
|
||||
InputStream fileinput = null ;
|
||||
String fname = null ;
|
||||
String fullpath = null ;
|
||||
|
||||
for (int extn = 0 ; !trouve && extn < extensions.length ; extn++) {
|
||||
fname = filename + extensions[extn] ;
|
||||
for (int index = 0 ; !trouve && index < datadirs.length ; index++) {
|
||||
fullpath = datadirs[index] + File.separator + fname ;
|
||||
File file = new File(fullpath) ;
|
||||
if (file.canRead()) {
|
||||
trouve = true ;
|
||||
try {
|
||||
fileinput = new FileInputStream(file) ;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace() ;
|
||||
System.exit(1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!trouve) {
|
||||
// Pas trouve
|
||||
System.out.println("Impossible de trouver le fichier " + filename) ;
|
||||
System.out.println(" pourtant j'ai cherche dans les dossiers : ") ;
|
||||
int existepas = 0 ;
|
||||
for (int i = 0 ; i < datadirs.length ; i++) {
|
||||
System.out.println(" - " + datadirs[i]) ;
|
||||
if (!new File(datadirs[i]).isDirectory()) {
|
||||
switch (existepas) {
|
||||
case 0: System.out.println(" (Ce dossier n'existe pas d'ailleurs)") ; break;
|
||||
case 1: System.out.println(" (Ce dossier n'existe pas non plus)") ; break;
|
||||
default: System.out.println(" (Celui-la non plus)") ; break;
|
||||
}
|
||||
existepas++ ;
|
||||
}
|
||||
System.out.println() ;
|
||||
}
|
||||
System.exit(1) ;
|
||||
}
|
||||
|
||||
System.out.println("Fichier utilisee : " + fullpath) ;
|
||||
System.out.println() ;
|
||||
|
||||
if (fname.endsWith(".gz")) {
|
||||
// The file is gzipped.
|
||||
try {
|
||||
fileinput = new GZIPInputStream(fileinput) ;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace() ;
|
||||
System.exit(1) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fileinput = new BufferedInputStream(fileinput) ;
|
||||
}
|
||||
|
||||
return new DataInputStream(fileinput) ;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
package org.insa.base ;
|
||||
|
||||
import java.io.* ;
|
||||
|
||||
/* Ne lisez pas cette classe. Lancez javadoc et lisez la doc generee plutot. */
|
||||
|
||||
/**
|
||||
* La classe Readarg facilite la lecture de donnees depuis le clavier ou depuis la ligne de commande.
|
||||
*
|
||||
*/
|
||||
public class Readarg {
|
||||
|
||||
private final String[] args ;
|
||||
private int next ;
|
||||
|
||||
// Le Java est le langage prefere des Shadoks.
|
||||
private final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
public Readarg(String[] argz) {
|
||||
this.args = argz ;
|
||||
this.next = 0 ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtient une chaine, ou bien depuis la ligne de commande, ou depuis l'entree standard.
|
||||
* @param msg Message affiche avant de demander la chaine
|
||||
*/
|
||||
public String lireString (String msg) {
|
||||
|
||||
String resultat = "" ;
|
||||
|
||||
System.out.print(msg) ;
|
||||
|
||||
if (this.next >= this.args.length) {
|
||||
try {
|
||||
resultat = br.readLine () ;
|
||||
} catch (Exception e) {
|
||||
System.err.println ("Erreur de lecture de l'entree standard.") ;
|
||||
System.exit(1) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
resultat = this.args[this.next] ;
|
||||
this.next++ ;
|
||||
System.out.println (resultat) ;
|
||||
}
|
||||
|
||||
return resultat ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtient un entier, ou bien depuis la ligne de commande, ou depuis l'entree standard.
|
||||
* @param msg Message affiche avant de demander l'entier
|
||||
*/
|
||||
public int lireInt (String msg) {
|
||||
String lu = lireString (msg) ;
|
||||
int result = 0 ;
|
||||
try {
|
||||
result = Integer.parseInt(lu) ;
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println ("Un entier est attendu mais je lis " + lu) ;
|
||||
System.exit(1) ;
|
||||
}
|
||||
return result ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtient un float, ou bien depuis la ligne de commande, ou depuis l'entree standard.
|
||||
* @param msg Message affiche avant de demander le float.
|
||||
*/
|
||||
public float lireFloat (String msg) {
|
||||
String lu = lireString (msg) ;
|
||||
float result = 0 ;
|
||||
try {
|
||||
result = Float.parseFloat(lu) ;
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println ("Un reel est attendu mais je lis " + lu) ;
|
||||
System.exit(1) ;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package org.insa.base ;
|
||||
|
||||
import java.io.* ;
|
||||
|
||||
import org.insa.drawing.Drawing;
|
||||
|
||||
/**
|
||||
* Fonctions accessoires dont vous n'avez pas a vous servir directement.
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
|
||||
// Calibrer la sortie graphique en fonction de la carte
|
||||
// Vous pouvez modifier les coordonnees pour ameliorer le rendu.
|
||||
public static void calibrer(String nomCarte, Drawing dessin) {
|
||||
|
||||
if (nomCarte.startsWith("insa")) {
|
||||
// L'INSA
|
||||
dessin.setBB (1.462, 1.473, 43.567, 43.5744) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("paris")) {
|
||||
// Ile de la Cité, Paris
|
||||
dessin.setBB (2.329, 2.372, 48.839, 48.867) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("mayot")) {
|
||||
// Mayotte
|
||||
dessin.setBB (44.5, 45.5, -13.25, -12.25) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("reuni")) {
|
||||
// La Réunion
|
||||
dessin.setBB (55.0, 56.0, -21.5, -20.5) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("midip")) {
|
||||
dessin.setBB (-0.6, 3.8, 42.2, 45.3) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("franc")) {
|
||||
dessin.setBB (-5.2, 10.0, 41.0, 51.5) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("pfranc")) {
|
||||
dessin.setBB (-5.2, 10.0, 41.0, 51.5) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("morbihan")) {
|
||||
dessin.setBB (-3.53, -2.452, 47.27, 47.665) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("newzealand")) {
|
||||
dessin.setBB (153.415, 179.912, -47.931, -33.980) ;
|
||||
}
|
||||
else if (nomCarte.startsWith("fract") || nomCarte.startsWith("carr")) {
|
||||
dessin.setBB (-0.05, 1.05, -0.05, 1.05) ;
|
||||
}
|
||||
else {
|
||||
dessin.setBB (-20.0, 50.0, 20.0, 70.0) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -37,11 +37,16 @@ public interface Drawing {
|
|||
/**
|
||||
* Set the pencil color.
|
||||
*
|
||||
* param color Color for the pencil.
|
||||
* @param color Color for the pencil.
|
||||
*
|
||||
*/
|
||||
public void setColor(Color col);
|
||||
|
||||
/**
|
||||
* Clear the drawing.
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Indique les bornes de la fenetre graphique.
|
||||
* Le calcul des coordonnees en pixel se fera automatiquement
|
||||
|
|
|
@ -35,4 +35,10 @@ public class DrawingInvisible implements Drawing {
|
|||
@Override
|
||||
public void repaint() { }
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
package org.insa.drawing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.*;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
/**
|
||||
* Cette implementation de la classe Dessin produit vraiment un affichage
|
||||
* (au contraire de la classe DessinInvisible).
|
||||
*/
|
||||
|
||||
public class DrawingVisible extends Canvas implements Drawing {
|
||||
public class DrawingVisible extends JPanel implements Drawing {
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -21,8 +27,9 @@ public class DrawingVisible extends Canvas implements Drawing {
|
|||
private float long2;
|
||||
private float lat1;
|
||||
private float lat2;
|
||||
private final float width;
|
||||
private final float height;
|
||||
|
||||
// Width and height of the image
|
||||
private final int width, height;
|
||||
|
||||
private boolean bb_is_set ;
|
||||
|
||||
|
@ -34,15 +41,18 @@ public class DrawingVisible extends Canvas implements Drawing {
|
|||
/**
|
||||
* Cree et affiche une nouvelle fenetre de dessin.
|
||||
*/
|
||||
public DrawingVisible (int largeur, int hauteur) {
|
||||
public DrawingVisible() {
|
||||
super();
|
||||
|
||||
this.zoomAndPanListener = new ZoomAndPanListener(this, 0, ZoomAndPanListener.DEFAULT_MAX_ZOOM_LEVEL, 1.2);
|
||||
this.zoomAndPanListener = new ZoomAndPanListener(this, ZoomAndPanListener.DEFAULT_MIN_ZOOM_LEVEL, 20, 1.2);
|
||||
this.addMouseListener(zoomAndPanListener);
|
||||
this.addMouseMotionListener(zoomAndPanListener);
|
||||
this.addMouseWheelListener(zoomAndPanListener);
|
||||
|
||||
BufferedImage img = new BufferedImage (largeur, hauteur, BufferedImage.TYPE_3BYTE_BGR);
|
||||
this.width = 2000;
|
||||
this.height = 1600;
|
||||
|
||||
BufferedImage img = new BufferedImage (this.width, this.height, BufferedImage.TYPE_3BYTE_BGR);
|
||||
|
||||
this.image = img;
|
||||
this.gr = img.createGraphics();
|
||||
|
@ -51,40 +61,24 @@ public class DrawingVisible extends Canvas implements Drawing {
|
|||
|
||||
this.bb_is_set = false;
|
||||
|
||||
this.width = largeur;
|
||||
this.height = hauteur;
|
||||
|
||||
this.long1 = (float)0.0;
|
||||
this.long2 = (float)largeur;
|
||||
this.lat1 = (float)0.0;
|
||||
this.lat2 = (float)hauteur;
|
||||
this.long1 = 0.0f;
|
||||
this.long2 = this.width;
|
||||
this.lat1 = 0.0f;
|
||||
this.lat2 = this.height;
|
||||
|
||||
this.setColor(Color.white);
|
||||
gr.fillRect(0,0, largeur, hauteur);
|
||||
this.clear();
|
||||
this.repaint();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g1) {
|
||||
public void paintComponent(Graphics g1) {
|
||||
Graphics2D g = (Graphics2D)g1;
|
||||
g.setTransform(zoomAndPanListener.getCoordTransform());
|
||||
g.drawImage(image, 0, 0, this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension size = new Dimension(0, 0);
|
||||
|
||||
if (image != null) {
|
||||
int w = image.getWidth(null);
|
||||
int h = image.getHeight(null);
|
||||
size = new Dimension(w > 0 ? w : 0, h > 0 ? h : 0);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAutoRepaint(boolean autoRepaint) {
|
||||
this.autoRepaint = autoRepaint;
|
||||
|
@ -96,48 +90,41 @@ public class DrawingVisible extends Canvas implements Drawing {
|
|||
}
|
||||
}
|
||||
|
||||
public void setWidth (int width) {
|
||||
public void setWidth(int width) {
|
||||
this.gr.setStroke(new BasicStroke(width));
|
||||
}
|
||||
|
||||
public void setColor (Color col) {
|
||||
this.gr.setColor (col);
|
||||
public void setColor(Color col) {
|
||||
this.gr.setColor(col);
|
||||
}
|
||||
|
||||
public void setBB (double long1, double long2, double lat1, double lat2) {
|
||||
public void clear() {
|
||||
this.gr.setColor(Color.WHITE);
|
||||
this.gr.fillRect(0, 0, this.width, this.height);
|
||||
}
|
||||
|
||||
public void setBB(double long1, double long2, double lat1, double lat2) {
|
||||
|
||||
if (long1 > long2 || lat1 > lat2) {
|
||||
throw new Error("DessinVisible.setBB : mauvaises coordonnees.");
|
||||
}
|
||||
|
||||
/* Adapte la BB en fonction de la taille du dessin, pour préserver le ratio largeur/hauteur */
|
||||
double deltalong = long2 - long1 ;
|
||||
double deltalat = lat2 - lat1 ;
|
||||
double ratiobb = deltalong / deltalat ;
|
||||
double ratiogr = width / height ;
|
||||
this.long1 = (float)long1;
|
||||
this.long2 = (float)long2;
|
||||
this.lat1= (float)lat1;
|
||||
this.lat2 = (float)lat2;
|
||||
|
||||
/* On ne peut qu'agrandir la BB, pour ne rien perdre.
|
||||
* Si le ratiobb est trop petit, il faut agrandir deltalong
|
||||
* s'il est trop grand, il faut agrandir deltalat. */
|
||||
if (ratiobb < ratiogr) {
|
||||
/* De combien faut-il agrandir ? */
|
||||
double delta = (ratiogr - ratiobb) * deltalat ;
|
||||
this.bb_is_set = true;
|
||||
|
||||
this.long1 = (float)(long1 - 0.5*delta) ;
|
||||
this.long2 = (float)(long2 + 0.5*delta) ;
|
||||
this.lat1 = (float)lat1 ;
|
||||
this.lat2 = (float)lat2 ;
|
||||
}
|
||||
else {
|
||||
double delta = (deltalong / ratiogr) - deltalat ;
|
||||
double scale = 1 / Math.max(this.width / (double)this.getWidth(), this.height / (double)this.getHeight());
|
||||
|
||||
this.long1 = (float)long1 ;
|
||||
this.long2 = (float)long2 ;
|
||||
this.lat1 = (float)(lat1 - 0.5*delta);
|
||||
this.lat2 = (float)(lat2 + 0.5*delta);
|
||||
}
|
||||
this.zoomAndPanListener.getCoordTransform().setToIdentity();
|
||||
this.zoomAndPanListener.getCoordTransform().translate((this.getWidth() - this.width * scale) / 2,
|
||||
(this.getHeight() - this.height * scale) / 2);
|
||||
this.zoomAndPanListener.getCoordTransform().scale(scale, scale);
|
||||
this.zoomAndPanListener.setZoomLevel(0);
|
||||
this.repaint();
|
||||
|
||||
this.bb_is_set = true ;
|
||||
}
|
||||
|
||||
private int projx(float lon) {
|
||||
|
@ -154,7 +141,7 @@ public class DrawingVisible extends Canvas implements Drawing {
|
|||
}
|
||||
}
|
||||
|
||||
public void drawLine (float long1, float lat1, float long2, float lat2) {
|
||||
public void drawLine(float long1, float lat1, float long2, float lat2) {
|
||||
this.checkBB() ;
|
||||
int x1 = this.projx(long1) ;
|
||||
int x2 = this.projx(long2) ;
|
||||
|
@ -165,7 +152,7 @@ public class DrawingVisible extends Canvas implements Drawing {
|
|||
this.doAutoPaint();
|
||||
}
|
||||
|
||||
public void drawPoint (float lon, float lat, int width) {
|
||||
public void drawPoint(float lon, float lat, int width) {
|
||||
this.checkBB() ;
|
||||
int x = this.projx(lon) - width / 2 ;
|
||||
int y = this.projy(lat) - width / 2 ;
|
||||
|
@ -173,7 +160,7 @@ public class DrawingVisible extends Canvas implements Drawing {
|
|||
this.doAutoPaint();
|
||||
}
|
||||
|
||||
public void putText (float lon, float lat, String txt) {
|
||||
public void putText(float lon, float lat, String txt) {
|
||||
this.checkBB() ;
|
||||
int x = this.projx(lon) ;
|
||||
int y = this.projy(lat) ;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
package org.insa.drawing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
@ -32,6 +33,11 @@ public class ZoomAndPanListener implements MouseListener, MouseMotionListener, M
|
|||
this.zoomMultiplicationFactor = zoomMultiplicationFactor;
|
||||
}
|
||||
|
||||
public void translate(double dx, double dy) {
|
||||
coordTransform.translate(dx, dy);
|
||||
targetComponent.repaint();
|
||||
}
|
||||
|
||||
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
}
|
||||
|
|
97
src/main/org/insa/drawing/graph/BasicGraphPalette.java
Normal file
97
src/main/org/insa/drawing/graph/BasicGraphPalette.java
Normal file
|
@ -0,0 +1,97 @@
|
|||
package org.insa.drawing.graph;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.insa.graph.RoadInformation.RoadType;
|
||||
|
||||
public class BasicGraphPalette implements GraphPalette {
|
||||
|
||||
// Color types for arc.
|
||||
static final Color motorway = Color.RED;
|
||||
static final Color bigroad = new Color(255, 105, 0);
|
||||
static final Color smallroad = new Color(255, 234, 0);
|
||||
static final Color coastline = Color.BLUE;
|
||||
|
||||
// Default point width
|
||||
static final int DEFAULT_POINT_WIDTH = 1;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BasicGraphPalette() { }
|
||||
|
||||
@Override
|
||||
public int getDefaultPointWidth() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getDefaultPointColor() {
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColorForType(RoadType type) {
|
||||
Color color = Color.BLACK;
|
||||
switch (type) {
|
||||
case MOTORWAY:
|
||||
color = motorway;
|
||||
break;
|
||||
case TRUNK:
|
||||
case PRIMARY:
|
||||
case SECONDARY:
|
||||
case MOTORWAY_LINK:
|
||||
case TRUNK_LINK:
|
||||
case PRIMARY_LINK:
|
||||
color = bigroad;
|
||||
break;
|
||||
case SECONDARY_LINK:
|
||||
case TERTIARY:
|
||||
case RESIDENTIAL:
|
||||
case UNCLASSIFIED:
|
||||
case ROAD:
|
||||
case LIVING_STREET:
|
||||
case SERVICE:
|
||||
case ROUNDABOUT:
|
||||
color = smallroad;
|
||||
break;
|
||||
case COASTLINE:
|
||||
color = coastline;
|
||||
break;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidthForType(RoadType type) {
|
||||
int width = 1;
|
||||
switch (type) {
|
||||
case MOTORWAY:
|
||||
width = 2;
|
||||
break;
|
||||
case TRUNK:
|
||||
case PRIMARY:
|
||||
case SECONDARY:
|
||||
case MOTORWAY_LINK:
|
||||
case TRUNK_LINK:
|
||||
case PRIMARY_LINK:
|
||||
width = 1;
|
||||
break;
|
||||
case SECONDARY_LINK:
|
||||
case TERTIARY:
|
||||
case RESIDENTIAL:
|
||||
case UNCLASSIFIED:
|
||||
case ROAD:
|
||||
case LIVING_STREET:
|
||||
case SERVICE:
|
||||
case ROUNDABOUT:
|
||||
width = 1;
|
||||
break;
|
||||
case COASTLINE:
|
||||
width = 4;
|
||||
break;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.insa.drawing.graph;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.insa.graph.RoadInformation.RoadType;
|
||||
|
||||
public class BlackAndWhiteGraphPalette extends BasicGraphPalette {
|
||||
|
||||
// Road colors (index
|
||||
private final static Color[] ROAD_COLOR_FROM_WIDTH = {
|
||||
null, new Color(140, 140, 140), new Color(80, 80, 80), new Color(40, 40, 40), new Color(30, 30, 30)
|
||||
};
|
||||
|
||||
@Override
|
||||
public Color getDefaultPointColor() {
|
||||
return Color.BLACK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColorForType(RoadType type) {
|
||||
int width = getWidthForType(type);
|
||||
return ROAD_COLOR_FROM_WIDTH[width];
|
||||
}
|
||||
|
||||
}
|
134
src/main/org/insa/drawing/graph/GraphDrawing.java
Normal file
134
src/main/org/insa/drawing/graph/GraphDrawing.java
Normal file
|
@ -0,0 +1,134 @@
|
|||
package org.insa.drawing.graph;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.insa.drawing.Drawing;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.Node;
|
||||
import org.insa.graph.Point;
|
||||
import org.insa.graph.RoadInformation.RoadType;
|
||||
|
||||
public class GraphDrawing {
|
||||
|
||||
// Drawing
|
||||
private Drawing drawing;
|
||||
|
||||
// Palette
|
||||
private GraphPalette palette;
|
||||
|
||||
public GraphDrawing(Drawing drawing) {
|
||||
this.drawing = drawing;
|
||||
this.palette = new BasicGraphPalette();
|
||||
}
|
||||
|
||||
public GraphDrawing(Drawing drawing, GraphPalette palette) {
|
||||
this.drawing = drawing;
|
||||
this.palette = palette;
|
||||
}
|
||||
|
||||
public void drawLine(Point p1, Point p2) {
|
||||
drawing.drawLine(p1.getLongitude(), p1.getLatitude(),
|
||||
p2.getLongitude(), p2.getLatitude());
|
||||
}
|
||||
|
||||
public void drawPoint(Point p) {
|
||||
drawPoint(p, palette.getDefaultPointWidth());
|
||||
}
|
||||
|
||||
public void drawPoint(Point p, int width) {
|
||||
drawing.drawPoint(p.getLongitude(), p.getLatitude(), width);
|
||||
}
|
||||
|
||||
public void drawPoint(Point p, int width, Color c) {
|
||||
drawing.setColor(c);
|
||||
drawing.drawPoint(p.getLongitude(), p.getLatitude(), width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the given arc with automatic color and width depending
|
||||
* on the road type.
|
||||
*
|
||||
* @param arc Arc to draw.
|
||||
*/
|
||||
public void drawArc(Arc arc) {
|
||||
drawArc(arc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the given arc.
|
||||
*
|
||||
* @param arc Arc to draw.
|
||||
* @param autoColorAndWidth Set to true to set color and width based
|
||||
* on the road type of the arc.
|
||||
*/
|
||||
public void drawArc(Arc arc, boolean autoColorAndWidth) {
|
||||
ArrayList<Point> pts = arc.getPoints();
|
||||
if (!pts.isEmpty()) {
|
||||
if (autoColorAndWidth) {
|
||||
drawing.setColor(palette.getColorForType(arc.getInfo().getType()));
|
||||
drawing.setWidth(palette.getWidthForType(arc.getInfo().getType()));
|
||||
}
|
||||
Iterator<Point> it1 = pts.iterator();
|
||||
Point prev = it1.next();
|
||||
while (it1.hasNext()) {
|
||||
Point curr = it1.next();
|
||||
drawLine(prev, curr);
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the drawing for the given graph.
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
public void initialize(Graph graph) {
|
||||
double minLon = Double.POSITIVE_INFINITY, minLat = Double.POSITIVE_INFINITY,
|
||||
maxLon = Double.NEGATIVE_INFINITY, maxLat = Double.NEGATIVE_INFINITY;
|
||||
for (Node node: graph.getNodes()) {
|
||||
Point pt = node.getPoint();
|
||||
if (pt.getLatitude() < minLat) {
|
||||
minLat = pt.getLatitude();
|
||||
}
|
||||
if (pt.getLatitude() > maxLat) {
|
||||
maxLat = pt.getLatitude();
|
||||
}
|
||||
if (pt.getLongitude() < minLon) {
|
||||
minLon = pt.getLongitude();
|
||||
}
|
||||
if (pt.getLongitude() > maxLon) {
|
||||
maxLon = pt.getLongitude();
|
||||
}
|
||||
}
|
||||
|
||||
double deltaLon = 0.02 * (maxLon - minLon),
|
||||
deltaLat = 0.02 * (maxLat - minLat);
|
||||
|
||||
drawing.setBB(minLon - deltaLon, maxLon + deltaLon,
|
||||
minLat - deltaLat, maxLat + deltaLat);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the drawing and draw the given graph on the drawing.
|
||||
*
|
||||
* @param graph Graph to draw.
|
||||
*/
|
||||
public void drawGraph(Graph graph) {
|
||||
|
||||
drawing.clear();
|
||||
|
||||
initialize(graph);
|
||||
|
||||
for (Node node: graph.getNodes()) {
|
||||
for (Arc arc: node.getSuccessors()) {
|
||||
drawArc(arc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
33
src/main/org/insa/drawing/graph/GraphPalette.java
Normal file
33
src/main/org/insa/drawing/graph/GraphPalette.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
package org.insa.drawing.graph;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.insa.graph.RoadInformation.RoadType;
|
||||
|
||||
public interface GraphPalette {
|
||||
|
||||
/**
|
||||
* @return The default point width for this palette.
|
||||
*/
|
||||
public int getDefaultPointWidth();
|
||||
|
||||
/**
|
||||
* @return The default point color for this palette.
|
||||
*/
|
||||
public Color getDefaultPointColor();
|
||||
|
||||
/**
|
||||
* @param type Type of the road.
|
||||
*
|
||||
* @return Color associated to the given type of road.
|
||||
*/
|
||||
public Color getColorForType(RoadType type);
|
||||
|
||||
/**
|
||||
* @param type Type of the road.
|
||||
*
|
||||
* @return Width associated to the given type of road.
|
||||
*/
|
||||
public int getWidthForType(RoadType type);
|
||||
|
||||
}
|
52
src/main/org/insa/drawing/graph/PathDrawing.java
Normal file
52
src/main/org/insa/drawing/graph/PathDrawing.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
package org.insa.drawing.graph;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.insa.drawing.Drawing;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Path;
|
||||
|
||||
public class PathDrawing {
|
||||
|
||||
// Default color
|
||||
public static final Color DEFAULT_PATH_COLOR = new Color(255, 0, 255);
|
||||
|
||||
// Drawing
|
||||
private Drawing drawing;
|
||||
private GraphDrawing graphDrawing;
|
||||
|
||||
/**
|
||||
* @param drawing
|
||||
*/
|
||||
public PathDrawing(Drawing drawing) {
|
||||
this.drawing = drawing;
|
||||
this.graphDrawing = new GraphDrawing(drawing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the given path with the given color.
|
||||
*
|
||||
* @param path
|
||||
* @param color
|
||||
*/
|
||||
public void drawPath(Path path, Color color) {
|
||||
this.graphDrawing.drawPoint(path.getFirstNode().getPoint(), 4, color);
|
||||
this.drawing.setColor(color);
|
||||
this.drawing.setWidth(2);
|
||||
for (Arc arc: path.getArcs()) {
|
||||
this.graphDrawing.drawArc(arc, false);
|
||||
}
|
||||
this.graphDrawing.drawPoint(path.getLastNode().getPoint(), 4, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the given path with default color.
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
public void drawPath(Path path) {
|
||||
drawPath(path, DEFAULT_PATH_COLOR);
|
||||
drawing.repaint();
|
||||
}
|
||||
|
||||
}
|
|
@ -45,7 +45,7 @@ public class Arc {
|
|||
/**
|
||||
* @return Destination node of this arc.
|
||||
*/
|
||||
public Node getDest() {
|
||||
public Node getDestination() {
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ public class Graph {
|
|||
// Nodes of the graph.
|
||||
private ArrayList<Node> nodes;
|
||||
|
||||
/**
|
||||
* @param mapId
|
||||
* @param nodes
|
||||
*/
|
||||
public Graph(int mapId, ArrayList<Node> nodes) {
|
||||
this.mapId = mapId;
|
||||
this.nodes = nodes;
|
||||
|
@ -25,4 +29,12 @@ public class Graph {
|
|||
*/
|
||||
public int getMapId() { return mapId; }
|
||||
|
||||
/**
|
||||
* @return Return the transpose graph of this graph.
|
||||
*/
|
||||
public Graph transpose() {
|
||||
// TODO:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package org.insa.graph;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Node {
|
||||
public class Node implements Comparable<Node> {
|
||||
|
||||
// ID of the node.
|
||||
private int id;
|
||||
|
@ -49,4 +49,17 @@ public class 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ package org.insa.graph.io;
|
|||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.sound.midi.ControllerEventListener;
|
||||
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Graph;
|
||||
|
@ -149,7 +152,9 @@ public class BinaryGraphReader extends BinaryReader implements AbstractGraphRead
|
|||
// And reverse arc if its a two-way road.
|
||||
if (!info.isOneWay()) {
|
||||
// Add without segments.
|
||||
dest.addSuccessor(new Arc(orig, length, info));
|
||||
ArrayList<Point> rPoints = new ArrayList<Point>(points);
|
||||
Collections.reverse(rPoints);
|
||||
dest.addSuccessor(new Arc(orig, length, info, rPoints));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.io.DataInputStream;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.Node;
|
||||
import org.insa.graph.Path;
|
||||
|
@ -35,23 +36,36 @@ public class BinaryPathReader extends BinaryReader implements AbstractPathReader
|
|||
// Number of nodes in the path (without first and last).
|
||||
int nbNodes = dis.readInt();
|
||||
|
||||
ArrayList<Node> nodes = new ArrayList<Node>(nbNodes + 2);
|
||||
ArrayList<Arc> arcs = new ArrayList<Arc>();
|
||||
|
||||
// Read first node
|
||||
nodes.add(readNode(graph));
|
||||
|
||||
// Read last node
|
||||
Node lastNode = readNode(graph);
|
||||
// Skip (duplicate) first and last node
|
||||
readNode(graph);
|
||||
readNode(graph);
|
||||
|
||||
// Read intermediate nodes:
|
||||
for (int node = 0; node < nbNodes; ++node) {
|
||||
ArrayList<Node> nodes = new ArrayList<Node>();
|
||||
for (int i = 0; i < nbNodes; ++i) {
|
||||
nodes.add(readNode(graph));
|
||||
}
|
||||
|
||||
// Add last node
|
||||
nodes.add(lastNode);
|
||||
Node current = nodes.get(0);
|
||||
for (int i = 1; i < nodes.size(); ++i) {
|
||||
Node node = nodes.get(i);
|
||||
Arc minArc = null;
|
||||
for (Arc arc: current.getSuccessors()) {
|
||||
if (arc.getDestination().equals(node)
|
||||
&& (minArc == null || arc.getMinimumTravelTime() < minArc.getMinimumTravelTime())) {
|
||||
minArc = arc;
|
||||
}
|
||||
}
|
||||
arcs.add(minArc);
|
||||
if (minArc == null) {
|
||||
System.out.println("No arc found between nodes " + current.getId() + " and " + node.getId() + "\n");
|
||||
}
|
||||
current = node;
|
||||
}
|
||||
|
||||
return new Path(graph, nodes);
|
||||
return new Path(graph, nodes.get(0), arcs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
83
src/main/org/insa/graph/io/Openfile.java
Normal file
83
src/main/org/insa/graph/io/Openfile.java
Normal file
|
@ -0,0 +1,83 @@
|
|||
package org.insa.graph.io ;
|
||||
|
||||
import java.io.* ;
|
||||
import java.util.zip.* ;
|
||||
|
||||
/**
|
||||
* Class that can be used to open (compressed) files from a specified
|
||||
* set of folders or for a full path.
|
||||
*
|
||||
*/
|
||||
public class Openfile {
|
||||
|
||||
/**
|
||||
* These folders will be looked up for the files.
|
||||
*
|
||||
*/
|
||||
private static final String[] datadirs = {
|
||||
|
||||
// INSA folder containing maps.
|
||||
"/home/commetud/3eme Annee MIC/Graphes-et-Algorithmes/Maps",
|
||||
|
||||
// INSA folder containing paths.
|
||||
"/home/commetud/3eme Annee MIC/Graphes-et-Algorithmes/",
|
||||
|
||||
// Maps sub-folder.
|
||||
"Maps",
|
||||
|
||||
// Current folder.
|
||||
"."
|
||||
};
|
||||
|
||||
/**
|
||||
* Available extensions.
|
||||
*
|
||||
*/
|
||||
private static final String[] extensions = { ".map", ".gz", ".map.gz", ".path", ".path.gz", "" };
|
||||
|
||||
/**
|
||||
* Open the given file and return a corresponding DataInputStream.
|
||||
*
|
||||
* @param filename Name of the file to open (without extension) or full path to the given file.
|
||||
* @throws IOException
|
||||
*/
|
||||
public static DataInputStream open(String filename) throws IOException {
|
||||
|
||||
File file = null;
|
||||
String fullpath = null;
|
||||
|
||||
// If the filename containing only a name (not a path):
|
||||
if (filename.equals (new File(filename).getName())) {
|
||||
|
||||
|
||||
for (String ext: extensions) {
|
||||
String fname = filename + ext;
|
||||
for (int index = 0; file == null && index < datadirs.length; ++index) {
|
||||
fullpath = datadirs[index] + File.separator + fname;
|
||||
file = new File(fullpath);
|
||||
if (!file.exists()) {
|
||||
file = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
fullpath = filename;
|
||||
file = new File(filename);
|
||||
}
|
||||
|
||||
InputStream fileInput = new FileInputStream(new File(fullpath));
|
||||
|
||||
// If the file is compressed.
|
||||
if (fullpath.endsWith(".gz")) {
|
||||
fileInput = new GZIPInputStream(fileInput) ;
|
||||
}
|
||||
else {
|
||||
fileInput = new BufferedInputStream(fileInput) ;
|
||||
}
|
||||
|
||||
return new DataInputStream(fileInput) ;
|
||||
}
|
||||
|
||||
}
|
60
src/test/org/insa/graph/io/BinaryGraphReaderTest.java
Normal file
60
src/test/org/insa/graph/io/BinaryGraphReaderTest.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
package org.insa.graph.io;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.Node;
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class BinaryGraphReaderTest {
|
||||
|
||||
// Epsilon for latitude and longitude.
|
||||
private static final double EPS = 1e-5;
|
||||
|
||||
private static Graph midip;
|
||||
|
||||
@BeforeAll
|
||||
static void initAll() throws IOException {
|
||||
BinaryGraphReader reader = new BinaryGraphReader(Openfile.open("midip"));
|
||||
midip = reader.read();
|
||||
}
|
||||
|
||||
void assertPointAt(Point p1, double longitude, double latitude) {
|
||||
assertEquals(p1.getLongitude(), longitude, EPS);
|
||||
assertEquals(p1.getLatitude(), latitude, EPS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMidipNodes() {
|
||||
ArrayList<Node> nodes = midip.getNodes();
|
||||
|
||||
assertEquals(nodes.size(), 150827);
|
||||
|
||||
// Check the locations of some nodes.
|
||||
assertPointAt(nodes.get(58411).getPoint(), 1.799864, 43.92864);
|
||||
assertPointAt(nodes.get(133312).getPoint(), 0.539752, 43.317505);
|
||||
assertPointAt(nodes.get(113688).getPoint(), 1.682739, 44.799774);
|
||||
assertPointAt(nodes.get(118141).getPoint(), 0.274857, 43.47475);
|
||||
assertPointAt(nodes.get(146918).getPoint(), 0.116148, 43.811386);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMidipArcs() {
|
||||
// TODO: Check the number of edges.
|
||||
// TODO: Check information for some edges.
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue